开发者

PHP OOP Good practice for accessing methods?

I have some code that often looks like this:

private $user;

public function __construct()
{
    $this->user = User::getInstance(); //singleton
}

public function methodOne()
{
    return $this->user->foo();
}

public function methodTwo()
{
    return $this->user->foo2();
}

public function methodThree()
{
    return $this->user->foo3();
}

I figure if I set user property to the instance I can reuse a shorter name in my method开发者_运维问答s (well in this case it's not that much shorter). I also thought doing it this way might save a little resources (beginning to doubt it), but when I look at other people's code I rarely see people do this. They would usually just call:

User::getInstance()->foo();
User::getInstance()->foo2();
User::getInstance()->foo3();

Is there any sort of best practice for this? Maybe if it's not a singleton class you might do it this way? Or maybe you should never do it this way? Hope to get some clarification, thanks.

Edit: Incase there is any misunderstanding I'm just wondering if I should the first example with creating a property to store the instance vs this:

public function methodOne()
{
    return User::getInstance()->foo();
}

public function methodTwo()
{
    return User::getInstance()->foo2();
}

public function methodThree()
{
    return User::getInstance()->foo3();
}

Actually now that I think about it this may be less code as I don't need the constructor...


There are indeed some problems with your approach.

  • It is not clear that your class depends on the User class. You can solve this with adding User as a constructor parameter.
  • Singletons are often bad practice. Your code demonstrates why: it is globally accessible and hence difficult to track dependencies using it (this points to the above problem).
  • Static methods are too often used as global access points (in response to what you see people usually do User::method()). Global access points give the same problem as singletons. They are also a tad more difficult to test.

I also don't see the point in repeating the User object with your new object, unless you would use eg the adapter pattern. Maybe if you could clarify this I would be able to come up with a better alternative than the generic:

class Foo {
    public function __construct(User $user) {
        $this->user = $user;
    }
    public function doXsimplified() {
        $this->user->doXbutMoreComplex($arg1,$arg2, $arg20);
    }
}


My personal preference in PHP is to use classes with just static methods for singletons, so you have

User::foo();
User::bar();


I would not create a new class just to wrap around a singleton like that. But if your new class adds some extra logic then your example makes sense. Remember, if you're worried that you're too verbose you can always use a temporary variable for successive function calls.

$user = User::getInstance();
$user->foo();
$user->bar();

But personally, I don't use Singletons anymore. Instead, I use Dependency Injection. I like the sfServiceContainer, but there are others. Have a look at this series of articles: http://fabien.potencier.org/article/11/what-is-dependency-injection

UPDATE

Based on the additional comments, this is how I would do it:

class UserWrapper
{
    private $user = null;

    public function __construct($user)
    {
        $this->user = $user;
    }

    public function foo()
    {
         return $this->user->foo();
    }

    ...
}

Then use it like this:

$user = new UserWrapper(User::getInstance());

Why? So I can pass in a fake User object if I want to test the UserWrapper class. E.g:

class UserMock { ... } // A fake object that looks like a User
$userTest = new UserWrapper(new UserMock());


I usually go like this, if you have already included the class in a bootstrap of some sort or a config file. I would usually declear the $user variable in a bootstrap that will get called on every page load, then just reference it as a global variable on other php files, this is what I would have in the bootstrap file.

$user = new User();

Then this is what I would have in the calling php file

global $user;
$user->foo();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜