参数输入 PHP 的动态方法
Dynamic methods with parameters typing in PHP
我有下面的 PHP 遗留代码,它打算动态 return 方法的名称。
public function getMethod($fieldName){
//do stuff
return $methodName;
}
returned 方法名称类似于:
setClient
setName
setAge
好的,就在这里。
问题是当我使用这些方法时。我有一个名为 class 的模型,它具有以下方法:
class Model {
public function find () {
$nameClass = get_called_class();
$instance = new $nameClass;
$result = $this->conn->select();//the select method returns a SQL SELECT from the database
if (isset($result[0])) {
foreach ($result[0] as $key => $val) {
$methodProp = $this->getMethod(key);
$instance->$methodProp($val);
}
} else {
throw new Exception('You have a error in your class');
}
}
}
这里是要求的 var_dump($result)
:
array (size=1)
0 =>
object(stdClass)[6]
public 'id' => string '1' (length=1)
public 'id_erp' => string '0' (length=1)
public 'name' => string 'Derp' (length=18)
public 'email' => null
public 'type_ota' => null
public 'user' => string 'derp_derp' (length=7)
public 'password' => string '1234' (length=4)
public 'url_logo' => null
public 'status' => string '1' (length=1)
public 'date' => string '2015-06-08 14:41:50' (length=19)
然后我有一些 classes 扩展了这个模型:
class Company extends Model {
public function setClient (Client $cli) {
//do stuff
}
public function setName($name) {
//do stuff
}
public function setAge($age) {
//do stuff
}
}
//here I use the class
$myCompany = new Company();
$myCompany->find();
方法 setName()
和 setAge()
工作正常,但是 setClient()
returns
Catchable fatal error: Argument 1 passed to setClient() must be an instance of Client, string given
简而言之,如何处理动态方法和输入PHP?
寻求帮助,我发现了一些关于 Reflection 的信息,但我以前从未使用过这个 class,而且我发现的示例对我没有帮助,尽管我认为这是正确的方法。
有没有人有过类似的经历?
更新
我试图在我的问题中加入一些代码来澄清我的问题。
你的问题就在这里
public function setClient (Client $cli) {
//do stuff
}
看到参数旁边有一个 class 名称了吗?那叫type hinting。这意味着该参数必须是您指定的 class 的实例,否则您将收到您发布的错误。您正在调用的代码中的某处
$method($param);
并且 $param
不是 Client
的实例。所以这就是你必须解决的问题。任何调用 setClient
都必须有一个 Client
.
的实例
$param = new Client();
$method($param);
如果我正确理解你的问题,你想检查方法需要什么类型提示。我从 the docs.
中获取了这段代码片段
<?php
//Target our class
$reflector = new ReflectionClass('MyClass');
//Get the parameters of a method
$parameters = $reflector->getMethod('FireCannon')->getParameters();
//Loop through each parameter and get the type
foreach($parameters as $param)
{
//Before you call getClass() that class must be defined!
echo $param->getClass()->name;
}
将上面的代码添加到您的代码中。这将检查方法中的参数是否是一个对象,如果是一个对象,它将检查 class 是否与给定的值相同。如果参数不是对象,您可以直接调用该方法,或者如果您对非对象参数进行类型提示,您也可以检查它们是否相等。这段代码绝对应该修改和清理,但我认为这足以让我的观点得到理解。
class Model {
public function find () {
$nameClass = get_called_class();
$instance = new $nameClass;
$result = $this->conn->select();//the select method returns a SQL SELECT from the database
if (!isset($result[0])) {
throw new Exception('You have a error in your class');
}
foreach ($result[0] as $key => $val) {
$methodProp = $this->getMethod($key);
$reflector = new ReflectionClass($nameClass);
$reflectorMethod = $reflector->getMethod($methodProp);
// Make sure method doesn't require more than one param,
// and it has defined at least one param.
if ($reflectorMethod->getNumberOfRequiredParameters() > 1 ||
$reflectorMethod->getNumberOfParameters() < 1
) {
// Throw error
}
//Get the parameters of a method
$parameters = $reflectorMethod->getParameters();
if (is_object($parameters[0])) {
if (!is_object($val) {
// Throw error
}
//Before you call get_class() that class must be defined!
//Use either class_exists($nameClass); or
//in_array($nameClass, get_declared_classes()); to check.
if ($val->getClass()->name !== get_class($parameters[0])) {
// Throw error
}
} else if (gettype($parameters[0]) !== gettype($val)) {
// Throw error
}
$instance->$methodProp($val);
}
}
}
我有下面的 PHP 遗留代码,它打算动态 return 方法的名称。
public function getMethod($fieldName){
//do stuff
return $methodName;
}
returned 方法名称类似于:
setClient
setName
setAge
好的,就在这里。 问题是当我使用这些方法时。我有一个名为 class 的模型,它具有以下方法:
class Model {
public function find () {
$nameClass = get_called_class();
$instance = new $nameClass;
$result = $this->conn->select();//the select method returns a SQL SELECT from the database
if (isset($result[0])) {
foreach ($result[0] as $key => $val) {
$methodProp = $this->getMethod(key);
$instance->$methodProp($val);
}
} else {
throw new Exception('You have a error in your class');
}
}
}
这里是要求的 var_dump($result)
:
array (size=1)
0 =>
object(stdClass)[6]
public 'id' => string '1' (length=1)
public 'id_erp' => string '0' (length=1)
public 'name' => string 'Derp' (length=18)
public 'email' => null
public 'type_ota' => null
public 'user' => string 'derp_derp' (length=7)
public 'password' => string '1234' (length=4)
public 'url_logo' => null
public 'status' => string '1' (length=1)
public 'date' => string '2015-06-08 14:41:50' (length=19)
然后我有一些 classes 扩展了这个模型:
class Company extends Model {
public function setClient (Client $cli) {
//do stuff
}
public function setName($name) {
//do stuff
}
public function setAge($age) {
//do stuff
}
}
//here I use the class
$myCompany = new Company();
$myCompany->find();
方法 setName()
和 setAge()
工作正常,但是 setClient()
returns
Catchable fatal error: Argument 1 passed to setClient() must be an instance of Client, string given
简而言之,如何处理动态方法和输入PHP? 寻求帮助,我发现了一些关于 Reflection 的信息,但我以前从未使用过这个 class,而且我发现的示例对我没有帮助,尽管我认为这是正确的方法。
有没有人有过类似的经历?
更新
我试图在我的问题中加入一些代码来澄清我的问题。
你的问题就在这里
public function setClient (Client $cli) {
//do stuff
}
看到参数旁边有一个 class 名称了吗?那叫type hinting。这意味着该参数必须是您指定的 class 的实例,否则您将收到您发布的错误。您正在调用的代码中的某处
$method($param);
并且 $param
不是 Client
的实例。所以这就是你必须解决的问题。任何调用 setClient
都必须有一个 Client
.
$param = new Client();
$method($param);
如果我正确理解你的问题,你想检查方法需要什么类型提示。我从 the docs.
中获取了这段代码片段<?php
//Target our class
$reflector = new ReflectionClass('MyClass');
//Get the parameters of a method
$parameters = $reflector->getMethod('FireCannon')->getParameters();
//Loop through each parameter and get the type
foreach($parameters as $param)
{
//Before you call getClass() that class must be defined!
echo $param->getClass()->name;
}
将上面的代码添加到您的代码中。这将检查方法中的参数是否是一个对象,如果是一个对象,它将检查 class 是否与给定的值相同。如果参数不是对象,您可以直接调用该方法,或者如果您对非对象参数进行类型提示,您也可以检查它们是否相等。这段代码绝对应该修改和清理,但我认为这足以让我的观点得到理解。
class Model {
public function find () {
$nameClass = get_called_class();
$instance = new $nameClass;
$result = $this->conn->select();//the select method returns a SQL SELECT from the database
if (!isset($result[0])) {
throw new Exception('You have a error in your class');
}
foreach ($result[0] as $key => $val) {
$methodProp = $this->getMethod($key);
$reflector = new ReflectionClass($nameClass);
$reflectorMethod = $reflector->getMethod($methodProp);
// Make sure method doesn't require more than one param,
// and it has defined at least one param.
if ($reflectorMethod->getNumberOfRequiredParameters() > 1 ||
$reflectorMethod->getNumberOfParameters() < 1
) {
// Throw error
}
//Get the parameters of a method
$parameters = $reflectorMethod->getParameters();
if (is_object($parameters[0])) {
if (!is_object($val) {
// Throw error
}
//Before you call get_class() that class must be defined!
//Use either class_exists($nameClass); or
//in_array($nameClass, get_declared_classes()); to check.
if ($val->getClass()->name !== get_class($parameters[0])) {
// Throw error
}
} else if (gettype($parameters[0]) !== gettype($val)) {
// Throw error
}
$instance->$methodProp($val);
}
}
}