Yii Framework Forum

General Object Oriented PHP question


(Cshehadi) #1

Hi,

I have a general “best practices” question.

I’m setting up a Yii application that will make heavy use of three objects. I’ve set up a “beforeAction” a parent controller, that all others inherit from. That beforeAction sets the three objects (let’s call them A, B and C) up as components, so they will be available throughout the applications via Yii::$app->A, Yii::$app->B, and Yii::$app->C. So far so good. It turns out the the methods in object C make very heavy use of objects A and B - referring to them constantly.

So… my question is: within Object C, is it better to just assume that Yii::$app->A and Yii::$app->B exist, and refer to them directly, over and over again? I’m tempted to create private variables in C that hold A and B, so I can refer to them more easily and so I can test once for the existence of A and B right when C is created. But will that create a copy of A and B?

Is there a best practice or design pattern for this sort of set up?

Thanks for your help.


(Jacob Moen) #2

Make a construct function that takes two objects, an instance of A and an instance of B.

$c = New C($a, $b)

https://secure.php.net/manual/en/language.oop5.decon.php


(Cshehadi) #3

thanks - actually I ended up making two get methods in C - getA() and getB() - each of them checked for the existence of the appropriate component (e.g. Yii::$app->A) then returned it. If there’s something better about your way, please let me know. And thanks for the reply!


(Jacob Moen) #4

If it depends on those instances, then pass them to the class in the constructor and assign them to two private member variables.
Having to check for them or refer to them outside of the class at runtime is both costly and error prone and not good design at all.


(Cshehadi) #5

thank you! if I assign them in the constructor to two private member variables will this make copies of A and B? or must I pass a reference?


(Jacob Moen) #6

You pass by reference like in my first answer. That way you make sure that they are valid and available for C. :slight_smile:


(Cshehadi) #7

Thanks once again for your time.

The actual implementation is a bit more complex than the example I’ve given above.

C is actually initialized by a factory class that uses findOne to create and populate the appropriate C object. The list of classes that C could possibly be all extend from a base class which then extends from ActiveRecord.

So ActiveRecord -> CBaseClass -> CClasses.

in the controller beforeAction, the Factory class figures out which CClass to use, then calls findOne to populate it and assigns that to C. So I’m not sure how to pass arguments to the constructor, since I’m calling findOne, and that calls the constructor.

So what I’ve done, adapting your advice, is to add the two properties A and B to CBaseClass, and then added an init() function to CBaseClass. So that when the object is created, it checks for the existence of Yii::$app->A and Yii::$app->B, and then assigns a reference to the local properties, e.g.

$this->A = &Yii::$app->A;

$this->B = &Yii::$app->B;

Seems to be working OK.