View Single Post
Old 09-14-2012, 09:22 PM   PM User | #6
Fou-Lu
God Emperor


 
Fou-Lu's Avatar
 
Join Date: Sep 2002
Location: Saskatoon, Saskatchewan
Posts: 15,635
Thanks: 4
Thanked 2,448 Times in 2,417 Posts
Fou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to all
Bring the concept of storage up to a more abstract level. It doesn't matter what your storage is, it can be filesystem files or database calls. When I say alternative, I simply mean different or controlled by this object (as in you are not limited to storing only in a database or only in a filesystem, you can store in both or multiple of either database or filesystem both local and remote).

What I mean is that if you have anything that can control its own storage and choose to write to different storage be that database or filesystem, then let it do so by constructing its own handling (ie, its own connection object). If you dictate that the application must use a specific storage regardless of what the storage is or what the classes are, then I'd recommend that they be passed to the class during the construction and at no time will this object ever created its own connection. Singletons become murky here since both are an acceptable approach as both are valid either within the class or passed into the class (since the end result is the same connection).

As for children, child classes will contain all members of their parent, even the private ones. The difference is that if the member is private, the child cannot directly access it. If the scope is modified to protected instead, then it will let you access it within a child. I'd suggest private member properties, and public (if warranted) or protected access methods instead, as that will prevent a child class from overwriting a parent member; however, PHP does not implicitly construct a parent object. If a child has overridden the __construct method, you must explicitly call parent::__construct(...) within the child. If the child has no reason to declare its own constructor, then a parent may mark that constructor as final to prevent the child from overriding it.

Oh, I should mention too, that even if you decide to construct an object as a composite from required data, there's nothing that says you cannot provide it with alternative at this level. For an example:
PHP Code:
class User
{
    private 
$storage;
    public function 
__construct(Storage $storage)
    {
          
$this->storage $storage;
    }
}

//. . .
$storage = new Storage(/* default config */);
$p = new NewsItem($storage);

$userStorage = new Storage(/* config from user */);
$u = new User($userStorage); 
Now, with the above if config is drawn from a location that User dictates as its config, then it is provided with an object during construction with the same config that User would otherwise have used during its construction.
There is a difference here though, and that difference is containment. User is no longer responsible for drawing its own storage, rather another class or main is responsible for constructing it based off of configurations that would be dictated by the User class. While this is valid code, I wouldn't do this myself as now you have a reliance created by the calling application to read the configuration that is controlled by the User class.
Does this make any sense? Its a bit on the complicated side, but I'm trying to say that anything controlled directly or sole responsibility of class User should be controlled immediately by class User and not controlled in any way by the primary application or main methods. Unfortunately without creating a mass of classes and relations in a UML this is very difficult to explain as to whether passing an object to a class during construction is better than constructing within the class itself.

If it helps you, for the most part of what I read your requirements are, I'd suggest that your classes using storage are more composite, so you should accept the Connection object into the class as a construction argument.
PHP Code:
class User
{
    private 
$con;
    public function 
__construct(Connection $con)
    {
        
$this->con $con;
    }
}

class 
NewsItem
{
    private 
$con;
    public function 
__construct(Connection $con)
    {
        
$this->con $con;
    }
}

//. . .
$con Connection::getInstance();
$user = new User($con);
$user->setuserid(1);
$user->load();

$ni = new NewsItem($con);
$ni->setUser($user);
$ni->setComment('This is an article');
$ni->save(); 
Is more how I perceive you are going. If you implement error handling within the Connection class itself, then you can guarantee that each of these are provided with a valid connection object.
Fou-Lu is offline   Reply With Quote
Users who have thanked Fou-Lu for this post:
Oatley (09-14-2012)