数组中的函数,

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (31)

我正在创建一个PHP类,它将函数存储在一个数组中,以便您可以在任何地方覆盖这些函数。我面临的问题是函数接受X个参数但是当我调用它时它发送一个包含参数的数组。

这是类

<?php
/**
 * Controller Class
 * 
 * This class will handle the controllers, it will contain an array with the
 * functions that will handle each controller (I know it's a bad description but
 * read the code and you'll know what I mean -.- :* ). Anyway, read the code
 * I think it's big enough to make it look something cool
 * 
 * @author Manulaiko
 */
class Controller
{
    /**
     * array functions
     * 
     * It will contain the functions that will be used by the controller.
     * The key of each index is a name that describes the function, don't change
     * them, if you want to make a plugin, just keep same name and add a diferent
     * function.
     * 
     * The value is the function itself, it will accept an array as parameter
     * that will contain the arguments, whether you want to be the array, I don't
     * just make it works
     */
    private $functions;

    /**
     * Constructor
     * 
     * This will set the default indexes in the $functions array, you don't need
     * to change anything here, this are the default functions of Alexya's core
     */
    public function __construct()
    {
        $this->functions = array(
            /**
             * This is an example, it's never used
             * 
             * You can add the functions directly here or use Controller::set()
             * which accepts the key of the index as first parameter (a string)
             * and the value of the index as second parameter (a function)
             * 
             * To call this function just use Controller::load() which accepts
             * a string as first parameter (in this case "test") and an array
             * as second parameter (which will be the parameters of the function)
             */
            "test" => function($params) {
                var_dump($params);
            },

            /**
             * Register function
             *
             * @see clases/Session.php
             */
            "register_user" => "Session::register"
        );
    }

    /**
     * Adds an entry to the array
     * 
     * Use this method if you want to add a function that Alexya will execute
     * Use the default names if you want to override an existing function or
     * use your own if not.
     * 
     * @param string name name of the function that will be saved in the array
     * @param function function the function that will be executed
     * 
     * @return true if $name already exists and was overwrited, false if it didn't
     *         exist but was added properly
     */
    public function __set($name, $function)
    {
        if(array_key_exists($name, $this->functions)) {
            $this->functions[$name] = $function;
            return true;
        } else {
            $this->functions[$name] = $function;
            return false;
        }
    }

    /**
     * Executes a function
     * 
     * This method will execute a function of the array.
     * 
     * @param string name name of the function to execute
     * @param mixed param parameters that will be passed to the function
     * 
     * @returns true if functions exists false if not
     */
    public function __call($name, $param)
    {
        if(!array_key_exists($name, $this->functions)) {
            if(DEBUG) {
                echo "Call to undefined function $name in Controller class!";
            }
            return false;
        }

        return call_user_func($this->functions[$name], $param);
    }
}

这就是我所说的:

<?php
/**
 * Index page
 * 
 * This file will contain the behaivour of the site, everything will be here
 * 
 * @author Manulaiko
 */

//include Alexya's Core
require_once("globConfig.php");

//Redirect user if he cant access the page
$Controller->user_can_access_website();

echo "<br/>";

$Controller->test(array(1,2,3,4,5,6,7,8,9));

echo "<br/>";

$Controller->register_user("asdfasdf", "asdfasdf", "asdfasdf@g.as");

第一次调用Controller是可以的,因为check_user_has_access数组中不存在的函数显示错误。

下一个调用,$Controller->test转储包含一个包含1- 的数组的数组9

最后一次调用发送一个包含给定参数的数组。但是,调用的函数不接受数组,而是接受这3个参数。

有什么办法可以解决吗?

这是我正在调用的函数:

/**
     * Performs a register attempt
     * 
     * Will try to perform a register attempt with the given username and password
     * if the register succed user will be redirected to home page
     * 
     * @param string username user's name
     * @param string password text password (will be encrypted here)
     * @param string mail register email
     * 
     * @return false if register failed
     */
    public function register($username, $password, $email)
    {
        global $Database;
        global $Alexya;

        /**
         * Can continue, boolean
         *
         * If an error happened this flag will be switched to false
         */
        $can_continue = true;

        //check username
        if(empty($username)) {
            Results::addFlash(array(
                        "result" => "error",
                        "message" => "Username can't be empty!"
                    ));
            $can_continue = false;
        } else if(strlen($username) < $Alexya->min_username_length) {
            Results::addFlash(array(
                        "result" => "error",
                        "message" => "Username can't be shorter than $Alexya->min_username_length characters!"
                    ));
            $can_continue = false;
        } else if(strlen($username) > $Alexya->max_username_length) {
            Results::addFlash(array(
                        "result" => "error",
                        "message" => "Username can't be longer than $Alexya->max_username_length characters!"
                    ));
            $can_continue = false;
        }

        //check password
        if(empty($password)) {
            Results::addFlash(array(
                        "result" => "error",
                        "message" => "Password can't be empty!"
                    ));
            $can_continue = false;
        } else if(strlen($password) < $Alexya->min_password_length) {
            Results::addFlash(array(
                        "result" => "error",
                        "message" => "Password can't be shorter than $Alexya->min_password_length characters!"
                    ));
            $can_continue = false;
        } else if(strlen($password) > $Alexya->max_password_lenght) {
            Result::addFlash(array(
                        "result" => "error",
                        "message" => "Password can\'t be longer than $Alexya->max_password_lenght characters!"
                    ));
            $can_continue = false;
        }

        //check email
        if(empty($email)) {
            Results::addFlash(array(
                        "result" => "error",
                        "message" => "Email can't be empty!"
                    ));
            $can_continue = false;
        } else if(preg_match("", $email)) {
            Results::addFlash(array(
                        "result" => "error",
                        "message" => "The email see,s to be incorrect!"
                    ));
            $can_continue = false;
        }

        //Check no error ocurred
        if($can_continue) {
            $password = md5($password);

            //check username/pass exists
            $username_exists = $Database->query("SELECT * FROM accounts WHERE username='$username'");

            if($username_exists && $username_exists->num_rows == 0) {
                $sessionID = $Controller->generate_sessionID();

                //insert user in database
                $userID = $Database->insert("users", array(
                                            "username"  => $username,
                                            "password"  => $password,
                                            "email"     => $email,
                                            "sessionID" => $sessionID
                                        ));

                if(is_numeric($userID)) {
                    $_SESSION["sessionID"] = $sessionID;
                    Results::addFlash(array(
                                "result" => "success",
                                "message" => "You're now registered!"
                            ));
                    Functions::redirect(URL."?page=home");
                } else {
                    Results::addFlash(array(
                                "result" => "error",
                                "message" => "Couldn't add user to database!"
                            ));
                }
            } else {
                Results::addFlash(array(
                            "result" => "error",
                            "message" => "Wrong username/password, please try again!"
                        ));
            }
        }

        return false;
    }

编辑:这是输出:

Call to undefined function user_can_access_website in Controller class!<br />
<b>Warning</b>:  Missing argument 2 for Session::register() in <b>/home/cabox/workspace/classes/Session.php</b> on line <b>126</b><br />
<br />
<b>Warning</b>:  Missing argument 3 for Session::register() in <b>/home/cabox/workspace/classes/Session.php</b> on line <b>126</b><br />
<br />
<b>Warning</b>:  strlen() expects parameter 1 to be string, array given in <b>/home/cabox/workspace/classes/Session.php</b> on line <b>145</b><br />
<br />
<b>Warning</b>:  strlen() expects parameter 1 to be string, array given in <b>/home/cabox/workspace/classes/Session.php</b> on line <b>151</b><br />
<br />
array(2) {
  [0]=>
  string(4) "test"
  [1]=>
  array(1) {
    [0]=>
    array(9) {
      [0]=>
      int(1)
      [1]=>
      int(2)
      [2]=>
      int(3)
      [3]=>
      int(4)
      [4]=>
      int(5)
      [5]=>
      int(6)
      [6]=>
      int(7)
      [7]=>
      int(8)
      [8]=>
      int(9)
    }
  }
}

编辑2:使用该函数call_user_func_array并添加一些调试行,这就是我在调用“test”函数时所拥有的:

__call function:
    name = test
    parameters: 
array(1) {
  [0]=>
  array(9) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(3)
    [3]=>
    int(4)
    [4]=>
    int(5)
    [5]=>
    int(6)
    [6]=>
    int(7)
    [7]=>
    int(8)
    [8]=>
    int(9)
  }
}
test function: string(4) "test"

如您所见,现在它不发送包含参数的数组,它现在从__call函数中发送的数组中发送第一个参数

提问于
用户回答回答于

好的,我发现了问题。

调用该函数的代码是这样的:

/**
 * Executes a function
 * 
 * This method will execute a function of the array.
 * 
 * @param string name name of the function to execute
 * @param mixed param parameters that will be passed to the function
 * 
 * @returns true if functions exists false if not
 */
public function __call($name, $param)
{
    if(!array_key_exists($name, $this->functions)) {
        if(DEBUG) {
            echo "Call to undefined function $name in Controller class!";
        }
        return false;
    }

    return call_user_func($this->functions[$name], $param);
}
return call_user_func($this->functions[$name], $param);

发送数组作为参数,该数组包含__call函数中给定的参数。

为了解决这个问题,@ deceze告诉我改用call_user_func_array(string, array)函数。我的错误是我这样使用它:

return call_user_func_array($this->functions[$name], func_get_args());

代码发送了magic方法的参数,__call而不是数组中给出的参数$param。为了解决这个问题我改变了func_get_args()$param所以这行看起来像这样:

return call_user_func_array($this->functions[$name], $param);

希望有人发现它有用

扫码关注云+社区

领取腾讯云代金券