【问题标题】:Dynamic methods in PHPPHP中的动态方法
【发布时间】:2014-11-22 01:58:30
【问题描述】:

我找到了一种在 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'))

这个技巧使用两个对象(Form 和 FormInsert)。 Form insert 使用 _call 方法,这意味着我可以使用此方法创建任何 HTML 对象。

虽然这很好用,但我想知道是否有办法使用以下更好的语法来代替?:

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

我们的想法不仅仅是创建输入,还创建任何类型的 HTML 元素。

【问题讨论】:

    标签: php class object dynamic methods


    【解决方案1】:

    你问的是jQuery中的常见做法,你当然可以在PHP中做到,你需要做的就是每次都返回对象:

    class FormInsert
    {
        ...
    
        public function __call( $method, $args )
        {
            // do the cool stuff 
    
            return $this;
        }
        ...
    }
    

    这样您将返回FomrInput 对象以添加有关您正在构建的标签的详细信息。


    这个想法听起来很有趣。但是,如果您将自己限制在两个课程中,我会在那里看到一些问题。在我看来,FormInsert 类将是巨大的,并且充满了处理特定情况和“HTML 标记语法”的控件。

    如果我想办法解决这些问题,我最终会为每个 HTML 标记创建一个类,并且不需要魔术方法 __call()... 再说一次,我还没有深入研究这个问题。

    【讨论】:

    • 看起来很棒!你能提供一个完整的例子吗?由于某些原因,我试图实现这一点,但我遇到了一些奇怪的错误......
    • 注意:未定义的属性:C:\htdocs\index.php 中的 FormInsert::$input 第 48 行致命错误:在 C:\ 中的非对象上调用成员函数 type() htdocs\index.php 第 48 行
    • 我发现了问题,对于这种特殊情况,我可能需要 3 个类,除非我想使用 $Form->insert->img()->id('banner')-> src('/images/banner.svg') 而不是 $Form->insert->img->id('banner')->src('/images/banner.svg') - 仍在处理代码,但我应该弄清楚。谢谢
    【解决方案2】:

    这可能对其他人有用,但我设法获得了以下 3 个类,它们可以帮助在 PHP 中语义地创建 HTML 对象,同时跟踪一些可以在 PHP 中重用的信息(例如对象中的 ID 或对象中的“名称”)形式)。以下对象用于表单,但也可用于“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;
        }
    
    }
    

    一些使用方法的例子:

    $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);
    

    【讨论】:

      猜你喜欢
      • 2013-12-06
      • 1970-01-01
      • 2011-01-07
      • 1970-01-01
      • 2018-07-08
      • 2016-02-05
      • 2018-03-21
      • 2010-09-20
      • 1970-01-01
      相关资源
      最近更新 更多