简体   繁体   English

PHP中的动态方法

[英]Dynamic methods in PHP

I found a way to do the following call using dynamic methods in PHP (input and img are just example, this could create anything): 我找到了一种使用PHP中的动态方法进行以下调用的方法(input和img只是示例,这可以创建任何东西):

$Form->insert->input(array('type' => 'text', 'name' => 'firstName', 'maxlength' => '100', 'value' => 'First name'))
$Form->insert->img(array('id' => 'banner', 'src' => '/images/banner.svg'))

This trick uses two object (Form and FormInsert). 此技巧使用两个对象(Form和FormInsert)。 And Form insert uses the _call method which means I could create any HTML object with this method. 表单插入使用_call方法,这意味着我可以使用此方法创建任何HTML对象。

While this works well, I was wondering if there is a way to use the following, nicer syntax instead?: 虽然这很好用,但我想知道是否有一种方法可以使用以下更好的语法?

$Form->insert->input->type('text')->name('firstName')->maxlength('100')->value('First name')
$Form->insert->img->id('banner')->src('/images/banner.svg')

The idea would be to create not just inputs but any sort of HTML element. 这个想法不仅是要创建输入,而且还要创建任何种类的HTML元素。

What you ask is common practice in jQuery and you surely can do it in PHP, all you need to do is to return the object every time: 您要问的是jQuery中的惯例,您肯定可以在PHP中做到这一点,您要做的就是每次都返回对象:

class FormInsert
{
    ...

    public function __call( $method, $args )
    {
        // do the cool stuff 

        return $this;
    }
    ...
}

This way you'd be coming back to the FomrInput object to add details about the tag you are building. 这样,您将回到FomrInput对象以添加有关正在构建的标签的详细信息。


The idea sounds interesting. 这个想法听起来很有趣。 I see a few problems there though if you limit yourself to just two classes. 如果您将自己限制在两个班级,我会在这里看到一些问题。 It would seem to me that the FormInsert class would be huge and full of controls to deal with particular cases and "HTML-tag syntax". 在我看来, FormInsert类将非常庞大,并且充满了处理特殊情况和“ HTML标记语法”的控件。

If I think of ways to solve those problems, I end up with a class per HTML tag and no need for the magic method __call() ... then again, I haven't gone that deep into the problem. 如果我想出解决这些问题的方法,那么最终每个HTML标记都有一个类,不需要魔术方法__call() ……那么,我又没有深入探讨这个问题。

This might be useful to others but I managed to get the following 3 classes which can help semantically create HTML objects in PHP while tracking some information that can be reused in PHP (such as IDs within an object or 'names' within a form). 这可能对其他人有用,但是我设法获得了以下3个类,这些类可以帮助在PHP中语义创建HTML对象,同时跟踪可以在PHP中重用的某些信息(例如,对象中的ID或表单中的“名称”)。 The following object is for a form but could be used for a 'body' object as well. 以下对象用于表单,但也可以用于“ body”对象。

class ElementAttribute {

    protected $parent; // Parent class object

    function __construct(&$parent, $element) {
        $this->parent = &$parent;

        $this->rootElement = &$this->parent;
        if (@is_object($this->rootElement->parent)) {
            $this->rootElement = &$this->rootElement->parent; // Set root element
        }
        $this->rootClassName = strtolower(get_class($this->rootElement)); // Set root class name object
        $this->element = $element; // Define current HTML element
        $this->s = '<'.$this->element; // Initialize HTML string
    }

    public function __call($method, $args) {

        $method = strtolower($method); // User lowercase by convention for HTML5

        if (isset($args[0])) {
            // Add available attributes to root element when created
            if ($this->element == $this->rootClassName) {
                if (@property_exists($this->rootElement, $method)) {
                    $this->rootElement->$method = $args[0];
                }
            }
            // Add available attribute arrays to root element when created
            $a = $method.'s';
            if (@property_exists($this->rootElement, $a)) {
                array_push($this->rootElement->$a, $args[0]);
            }
            $this->s .= ' '.$method.'="'.$args[0].'"';
        }
        return $this;
    }

    public function __toString() {
        $s = $this->s.'>';
        $m = $this->rootElement->lastUsedMethod;
        unset($this->rootElement->$m); // Unset HTML object from root object so that a new object can replace it
        return $s;
    }
}

class HtmlElement {

    protected $parent; // Parent class object

    function __construct(&$parent) {
        $this->parent = &$parent;
    }

    function __get($name) {
        if (!@is_object($this->$name)) {
            $this->$name = new ElementAttribute($this, $name);
        }
        return $this->$name;
    }

}

class Form {

    public $id; // Form Id
    public $name = ''; // Form Name
    public $ids = array(); // List of object Ids within the form
    public $names = array(); // List of object Names within the form
    public $lastUsedMethod; // Track last used dynamic method

    function __get($name) {
        if ($name == 'open') { // Open current HTML element tag
            $this->$name = new ElementAttribute($this, get_class($this));
        } else if ($name == 'insert') { // Insert new HTML element
            $this->$name = new HtmlElement($this);
        }
        $this->lastUsedMethod = $name;
        return $this->$name;
    }

}

Some examples on how to use it: 有关如何使用它的一些示例:

$Form = new Form();

echo $Form->open->id('signup')->method('post')->autocomplete('off')->autocorrect('off')->action('/toto');

var_dump($Form);

echo $Form->insert->input->type('text')->name('firstName')->maxlength('100')->value('First name');

var_dump($Form);

echo $Form->insert->input->type('text')->name('lastName')->maxlength('100')->value('Last name');

var_dump($Form);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM