init() or __contruct()

So what is your suggestion? I have yet to see any concrete one yet.

Do you mean merging init() into the constructor for application component? As I already said, this means the constructor then must use the signature that pestaa suggested, which is too strong. Theoretically, any component can be an application component, as long as it implements IApplicationComponent. So asking for such strict constructor means this interface is incomplete.

I don’t think factory has anything to do here, and I don’t think using a lot of factory methods is a good thing. Factory itself has a lot of limitations.

http://php.net/manual/en/language.oop5.interfaces.php#85859

The documentation does not state anything against this statement.

They can be implemented inappropriately, of course, but I don’t think they are restrictive by definition.

Thanks for the pointer about constructor. I didn’t know this (it wasn’t allowed before). In general, I’m against posing a requirement on the constructor signature because it doesn’t follow the spirit of interface.

I don’t mean factory is useless. Factory is not good when subclassing is needed.

I think we should stop discussing on this. I realized this is more like personal preference, and it is hard for one to convince the other. As long as we use init() in a consistent way, I don’t see big problems.

It’s a shame, I was hoping to contribute to Yii both with the documentation and the code.

But you don’t! As I demonstrated. And there seems to be no way of persuading you about anything once you have you mind set, which is kind of limiting.

Many FOSS projects work well with a closed approach to development, and I’m happy to use them, but I’ve found it’s not fun to try to work that way. Different strokes.

I’ll still use Yii, I’ll just remove the obvious flaws and procedural code.

Right! I’m off to hack ActiveRecord now I’ve got init() out of the way (mostly).

I am open to your suggestions. But, please, give some concrete ones. Having typed in so many words and spent so much time, I have yet to see any from you yet (pestaa gave one, but it’s not convincing enough to make the change). That’s why I call for stopping discussing on this.

I did a Google search to find out factory drawbacks, but did not succeed. Please invest a few minutes to clarify what you meant by ‘not good’.

I’m willing to accept your decision without further questions if it is well reasoned. However, I can’t see any purpose why we should keep the existing instantiation process without considering alternatives.

If a factory method not only creates a new class but also configures it from an argument, you then have the ability to customize the configuration process. It also means that external classes know less about the components’ internals, which is always good, even if subclassing a component takes a bit longer.

Here’s an example of what I thought:




class CComponent

{

   protected function __construct()

   {

      // pre-initialization

   }


   public static function factory($config=null)

   {

      $class = new self;

      // do whatever configuration needs

      // a foreach might do so far


      // post init, or init as in current implementation

      return $class;

   }

}



Edit:

The only drawback I found (bug 30934):

Using the factory method, how would you write a child class that needs to do some initialization before parent’s initialization?

The "self" bug you mentioned is a big one. This can only be solved in PHP 5.3.

I needed to investigate first. Then experiment. I don’t know your code, and there are no tests, so it takes a lot more time than a well organised project. So I have to create tests, branch, and validate my ideas. That’s why I asked questions, to speed things along. I have no wish to rock the boat.

No problem. There are some unit tests under "tests" folder. They only cover part of the code. Adding more coverage of tests is one of the major tasks looking forward (mainly need to find good ways to set up different fixtures).

I apologize if my posts hurt you. I guess I am overheated.

This framework is far from perfect. There are many places that need to be improved. One of the biggest obstacles to these improvements is to maintain backward compatibility (BC). For this reason, I have to defend hard when a design change may break BC.

Having said that, I don’t mean we should sit on mistakes. We may take your suggestions when we do a major release or rewrite that doesn’t have keeping BC as top priority.

By extending constructor and calling parent implementation lastly.

Update:

Backward compatibility is definitely an important point of view, but as these ideas are really long term, I think they simply cannot be implemented before the next major version. But it’s fine.

Could you write some pseudo code to show this? Note that these initialization (both parent’s and child’s) need to be done after configuration.

Of course. Please note that prior to 5.3, PHP forces me to copy self-referential methods, which might turn the whole thing even more harmful than the current implementation. I can’t decide, though. I’m also not aware the possible workaround you mentioned regarding 5.3.




class CParent

{

   protected function __construct()

   {

      // before config

   }


   public function factory($config=null)

   {

      $class = new self;

      // config

      // ...

      return $class;

   }

}


class CChild extends CParent

{

   protected function __construct()

   {

      // before parent init

      parent::__construct();

      // after parent init

   }


   public function factory($config=null)

   {

      $class=new self;

      // config

      // ...

      return $class;

   }

}



Subclasses of CActiveRecord are required to have a model function to overcome this self issue. I know this is overwhelming.

If configuration is complex, we can dedicate a protected method for it. Otherwise it can be done in the constructor (which won’t make that ‘a big black box’). So only factory($config=null){return new self($config);} would be necessary in each descendant.

Nope, your code doesn’t meet the requirement. I was saying the init code is needed after the configuration is applied (e.g. establishing DB connection after the connection parameters are set).

I’m not at all offended. No pasa de nada.

Sure. Completely understood.

BC (and regresion, of course) was also one of the issues I was considering, which is why I needed good test coverage of the areas I was looking at. That’s not a ten minute job!

No problem,

w000000t, I was so happy ready this, and all of the sudden it stops? I deserve a conclusion!

:lol: so what 's your conclusion ?

Found a great use for having both __construct() and init() for CPortlet. I have a javascript library that I need to add to all pages on a client’s site, and for one view, a property of this CPortlet has a different specified value than any other view. I also have a need to override this value under certain conditions.

The class that Ive extended CPortlet has a property initialized to FALSE. During its __construct(), Ive added some logic to determine if the portlet is called from one particular controller/action, and change the value of this property to TRUE. When the widget is called within my viewfile via:


<?php $this->widget('MyPortlet'); ?>

I can choose to override this property, since the logic discussed above is performed in __construct(), and more specifically, not done in init() :


<?php $this->widget('MyPortlet', array('myProperty' => TRUE)); ?>

I rarely will configure “MyPortlet” with that config, however, and prefer to just let the constructor logic determine the necessary conditions for changing ‘myProperty’ from FALSE to TRUE.

Im aware there are many ways to do this same thing, but I feel this is a tidy way to accomplish what I need.