dongtuo1482 2013-01-08 14:05
浏览 20

具有自己属性的特征

The objective of PHP traits is to manage a bunch of logic. However what is the best way to make this bunch of logic works according some dedicated attributes and avoiding naming conflicts ?

I'm thinking about MVC and particularly the model class. Indeed models seems to be good candidates for traits. Models can implement tree structure, be draftable, revisionnable, sluggable, and so on.

I would like to write something like this:

class MyModel extends Model {
    use Tree, Revision, Slug;
    protected $_behaviors = array(
        'Tree' => array('parentFieldname' => 'p_id'),
        'Revision' => array(/* some options */),
        'Slug' => array(/* some options */)
    );
    public function __construct() {
        foreach($this->_behaviors as &$options) {
            $options += /* trait defaults ? */
        }
    }
}

If I intend to set the Tree trait like this :

trait Tree {
    protected $_defaults = array(
        'parentFieldname' => 'parent_id',
        /*...other options...*/
    );
    public function moveUp();
    public function moveDown();
    public function setParent(); //<- need the `'parentFieldname' => 'p_id'`attribute
    /*...and so on...*/
}

I'll reach into naming conflicts because of $_defaults since each trait needs its own defaults. Using the name of the trait as attribute name imply using something like (new ReflectionClass(__CLASS__))->getTraits())... which is not really awesome.

In other words is there a way to create traits with "overridable defaults" and avoid naming conflicts ?

  • 写回答

4条回答 默认 最新

  • dounai9592 2013-01-08 14:07
    关注

    Like you will do in every OOP-concept: Open your eyes! Thats exactly the same, as you extends a class and misuse already existing property. Nothing more.

    class A {
      protected $defaults = array ('foo' => 'bar');
    }
    class B extends A {
      protected $defaults = array('foo2' => 42); // Bum: 'foo' disappeared
    }
    

    Having a generic $_defaults-property sounds to me like a code smell anyway: What "defaults"? This defaults? System defaults? Application defaults? [1] Setup your class with values, not "defaults", because thats (spreading default value) something for an initialization process, or the initialization of the concrete properties (public $parentFieldName = 'parent_id';)

    trait A {
      public $parentFieldName = 'parent_id';
      public function construct ($options) { /
         if (isset($options['parentFieldName'])) {
           $this->parentFieldName = $options['parentFieldName'];
         }
      }
    }
    class Foo {
      use A {
        A::construct as protected constructA;
      }
      public function __construct ($options) {
        $this->constructA($options['A']);
      }
    }
    

    Some notes: It's important, that you alias construct() because it would conflict with other methods (from other traits) as well, and construct() is not a special method. It's only named this way (from me) to clarify, that it is "a kind of" constructor. Other names like init() or such would work as well of course ;) You must call it within the "real" constructor (see Foo::__construct()) yourself.

    [1] "default" as an identifier is like "type", "status", "i", ...: They are to generic to be useful.

    评论

报告相同问题?

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效