在 PHP 中对受保护方法使用 _call
Usage of _call for protected methods in PHP
我有受保护的方法(Set_SelectedElementStyle
和 Set_SelectedElementAttribute
)接受一些(恰好 4 个——但不需要最后一个)参数。
这些参数是:
- order - 表示将获得某些属性或样式的元素索引的数字
- 元素-元素
- name - 属性或样式的名称
- value - 属性或样式的值(不需要 - 然后忽略样式并且属性可能为空)
我认为我会使用 不存在的 函数,其名称将包含元素名称和单词 style 或 attribute(这意味着将使用上面调用的方法中的哪一个)来简化它们的调用。
参数 order 将准备好并在方法内部设置 __call
我想用来调用那个不存在的方法。
调用不存在的函数可能是(例如 - 但这是无意义的 - 因为 XML 标签不需要格式化)
$this -> Person_Style('font-family', 'Arial');
但我在 Whosebug 的其他地方读到这会导致致命错误。
所以,还有什么方法可以按照我想的方式调用那些受保护的函数。
编辑:
具有四个参数的两个受保护方法之一
protected function Set_SelectedElementStyles($Order, $Element, $Name, $Value="")
{
try
{
if(empty($Order) && $Order != 0)
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_MISSING);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0]);
}
try
{
if(!is_integer($Order))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_WRONGVALTYPE);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0], gettype($Order), 'integer');
}
try
{
if($Order < 0)
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_LOWNUMBER1);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0], 0);
}
try
{
if(empty($Element))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_MISSING);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[1]);
}
try
{
if(empty($Name))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_MISSING);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[2]);
}
/*
* sets styles;
* Element - element name;
* Order - number of position of element that will get style;
* Name - style name;
* Value - style value
*/
$this -> ElementStyles_Selected[$Element][$Order][$Name] = $Value;
}
由 public 方法调用,其中四个参数中的两个从其他条件中提取
public function __call($Function, array $Parameters)
{
$Options = array('Element_Style', 'Element_Attribute');
try
{
if(!in_array($Function, $Options))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_DMDOPTION);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0], $Options);
}
if($Function == $Options[0])
{
$Element = split('_', $Function)[0];
if($Element == $this -> Elements['top'])
{
call_user_func_array(array($this, 'Set_SelectedElementStyles'), array_unshift($Parameters, 0, $Element));
}
else
{
call_user_func_array(array($this, 'Set_SelectedElementStyles'), array_unshift($Parameters, array_flip($this -> Elements['sub'])[$Element], $Element));
}
}
else
{
$Element = split('_', $Function)[0];
if($Element == $this -> Elements['top'])
{
call_user_func_array(array($this, 'Set_SelectedElementAttributes'), array_unshift($Parameters, 0, $Element));
}
else
{
call_user_func_array(array($this, 'Set_SelectedElementAttributes'), array_unshift($Parameters, array_flip($this -> Elements['sub'])[$Element], $Element));
}
}
}
或者 else(以及其他地方 - 在 else 类中)public 上面写的受保护方法的使用方法。这接受三个参数。
public function Set_SubLevelAttributes($Order="", $Name="", $Value="")
{
try
{
if(empty($Order) && $Order != 0)
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_MISSING);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0]);
}
try
{
if(!is_integer($Order))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_WRONGVALTYPE);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0], gettype($Order), 'integer');
}
try
{
if($Order < 0)
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_LOWNUMBER1);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0], 0);
}
try
{
if(empty($Name))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_MISSING);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[1]);
}
/*
* checks attribute name;
* sets attribute to chosen element;
* sets order to list of used orders
*/
if($this -> Check_AttributeName($Name))
{
$this -> Set_SelectedElementAttributes($Order, $this -> Elements['sub']['set'], $Name, $Value);
$this -> Set_OrderToList($Order);
}
}
你可以在这里使用__call
。但请注意,在大多数情况下,不需要使用具有 4 个或更多参数的方法。 “Clean Code”中的 Uncle Bob 推荐最多 3 个参数,最好是 1 或 2 个。例如,您可以通过将参数封装到一个对象来实现这一点。
您案例的示例代码:
class TestClass
{
public function __call($name, $arguments)
{
$nameArguments = explode('_', $name);
$methodName = 'Set_SelectedElement'.$nameArguments[1];
if(method_exists($this, $methodName) && count($arguments) > 1) {
return $this->$methodName($nameArguments[0], $arguments[0], $arguments[1]);
}
return 'Noooooo.';
}
protected function Set_SelectedElementStyle($element, $name, $value = null)
{
return 'Style for '.$element.': '.$name.': '.$value;
}
protected function Set_SelectedElementAttribute($element, $name, $value = null)
{
return 'Attribute for '.$element.': '.$name.'="'.$value.'"';
}
}
$testClass = new TestClass();
var_dump(
$testClass->Person_Style('font-family', 'Arial'),
$testClass->Element_Attribute('name', 'CustomName'),
$testClass->Person_Style('font-family'),
$testClass->Super_No('test', 'test')
);
var_dump的效果如下:
string 'Style for Person: font-family: Arial' (length=36)
string 'Attribute for Element: name="CustomName"' (length=40)
string 'Noooooo.' (length=8)
string 'Noooooo.' (length=8)
我有受保护的方法(Set_SelectedElementStyle
和 Set_SelectedElementAttribute
)接受一些(恰好 4 个——但不需要最后一个)参数。
这些参数是:
- order - 表示将获得某些属性或样式的元素索引的数字
- 元素-元素
- name - 属性或样式的名称
- value - 属性或样式的值(不需要 - 然后忽略样式并且属性可能为空)
我认为我会使用 不存在的 函数,其名称将包含元素名称和单词 style 或 attribute(这意味着将使用上面调用的方法中的哪一个)来简化它们的调用。
参数 order 将准备好并在方法内部设置 __call
我想用来调用那个不存在的方法。
调用不存在的函数可能是(例如 - 但这是无意义的 - 因为 XML 标签不需要格式化)
$this -> Person_Style('font-family', 'Arial');
但我在 Whosebug 的其他地方读到这会导致致命错误。
所以,还有什么方法可以按照我想的方式调用那些受保护的函数。
编辑:
具有四个参数的两个受保护方法之一
protected function Set_SelectedElementStyles($Order, $Element, $Name, $Value="")
{
try
{
if(empty($Order) && $Order != 0)
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_MISSING);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0]);
}
try
{
if(!is_integer($Order))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_WRONGVALTYPE);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0], gettype($Order), 'integer');
}
try
{
if($Order < 0)
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_LOWNUMBER1);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0], 0);
}
try
{
if(empty($Element))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_MISSING);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[1]);
}
try
{
if(empty($Name))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_MISSING);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[2]);
}
/*
* sets styles;
* Element - element name;
* Order - number of position of element that will get style;
* Name - style name;
* Value - style value
*/
$this -> ElementStyles_Selected[$Element][$Order][$Name] = $Value;
}
由 public 方法调用,其中四个参数中的两个从其他条件中提取
public function __call($Function, array $Parameters)
{
$Options = array('Element_Style', 'Element_Attribute');
try
{
if(!in_array($Function, $Options))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_DMDOPTION);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0], $Options);
}
if($Function == $Options[0])
{
$Element = split('_', $Function)[0];
if($Element == $this -> Elements['top'])
{
call_user_func_array(array($this, 'Set_SelectedElementStyles'), array_unshift($Parameters, 0, $Element));
}
else
{
call_user_func_array(array($this, 'Set_SelectedElementStyles'), array_unshift($Parameters, array_flip($this -> Elements['sub'])[$Element], $Element));
}
}
else
{
$Element = split('_', $Function)[0];
if($Element == $this -> Elements['top'])
{
call_user_func_array(array($this, 'Set_SelectedElementAttributes'), array_unshift($Parameters, 0, $Element));
}
else
{
call_user_func_array(array($this, 'Set_SelectedElementAttributes'), array_unshift($Parameters, array_flip($this -> Elements['sub'])[$Element], $Element));
}
}
}
或者 else(以及其他地方 - 在 else 类中)public 上面写的受保护方法的使用方法。这接受三个参数。
public function Set_SubLevelAttributes($Order="", $Name="", $Value="")
{
try
{
if(empty($Order) && $Order != 0)
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_MISSING);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0]);
}
try
{
if(!is_integer($Order))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_WRONGVALTYPE);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0], gettype($Order), 'integer');
}
try
{
if($Order < 0)
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_LOWNUMBER1);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[0], 0);
}
try
{
if(empty($Name))
{
throw new MarC_Exception(UniCAT::UNICAT_EXCEPTIONS_MAIN_CLS, UniCAT::UNICAT_EXCEPTIONS_MAIN_FNC, UniCAT::UNICAT_EXCEPTIONS_MAIN_PRM, UniCAT::UNICAT_EXCEPTIONS_SEC_PRM_MISSING);
}
}
catch(MarC_Exception $Exception)
{
$Exception -> ExceptionWarning(get_called_class(), __FUNCTION__, $Exception -> Get_Parameters(__CLASS__, __FUNCTION__)[1]);
}
/*
* checks attribute name;
* sets attribute to chosen element;
* sets order to list of used orders
*/
if($this -> Check_AttributeName($Name))
{
$this -> Set_SelectedElementAttributes($Order, $this -> Elements['sub']['set'], $Name, $Value);
$this -> Set_OrderToList($Order);
}
}
你可以在这里使用__call
。但请注意,在大多数情况下,不需要使用具有 4 个或更多参数的方法。 “Clean Code”中的 Uncle Bob 推荐最多 3 个参数,最好是 1 或 2 个。例如,您可以通过将参数封装到一个对象来实现这一点。
您案例的示例代码:
class TestClass
{
public function __call($name, $arguments)
{
$nameArguments = explode('_', $name);
$methodName = 'Set_SelectedElement'.$nameArguments[1];
if(method_exists($this, $methodName) && count($arguments) > 1) {
return $this->$methodName($nameArguments[0], $arguments[0], $arguments[1]);
}
return 'Noooooo.';
}
protected function Set_SelectedElementStyle($element, $name, $value = null)
{
return 'Style for '.$element.': '.$name.': '.$value;
}
protected function Set_SelectedElementAttribute($element, $name, $value = null)
{
return 'Attribute for '.$element.': '.$name.'="'.$value.'"';
}
}
$testClass = new TestClass();
var_dump(
$testClass->Person_Style('font-family', 'Arial'),
$testClass->Element_Attribute('name', 'CustomName'),
$testClass->Person_Style('font-family'),
$testClass->Super_No('test', 'test')
);
var_dump的效果如下:
string 'Style for Person: font-family: Arial' (length=36)
string 'Attribute for Element: name="CustomName"' (length=40)
string 'Noooooo.' (length=8)
string 'Noooooo.' (length=8)