在 PHP 中对受保护方法使用 _call


Usage of _call for protected methods in PHP

我有受保护的方法(Set_SelectedElementStyleSet_SelectedElementAttribute),接受一些(正好是4个 - 但最后一个不是必需的)参数。

这些论点是:

  • order - 数字,表示将获得某些属性或样式的元素索引
  • 元素 - 元素
  • 名称 - 属性或样式的名称
  • value - 属性
  • 或样式的值(不是必需的 - 则忽略样式,属性可能为空)

我以为我会使用不存在的函数,其中包含元素名称和单词样式属性(这意味着将使用上述哪个调用方法)来简化它们的调用。

参数顺序将在我想用来调用该不存在的方法__call中准备和设置。

调用不存在的函数可能是(例如 - 但这是无意义的 - 因为 XML 标签不需要格式化)

$this -> Person_Style('font-family', 'Arial');

但我在Stackoverflow的其他地方读到,这会导致致命的错误。

那么,还有什么方法可以以我认为的方式调用这些受保护的函数。

编辑:

具有四个参数的两个受保护方法之一

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 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 类中)使用上面写的受保护的公共方法。这接受三个参数。

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 个或更多参数的方法。鲍勃叔叔在"清洁代码"中建议最多 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)