Why use static method in PHP's laravel model c

2020-05-24 05:39发布

问题:

In PHP laravel, we have codes like

$user = User::find(1);
var_dump($user->name);

I am not concerning how to use the find method, I am concerning why laravel use a static method? Shouldn't the use of static method make the method hard to test?

Will it be better if they designed using singleton?

e.g.

$user = User::getInstance()->find(1);
var_dump($user->name);

回答1:

In fact, your example is very similar to what Laravel does behind the scene. When you do User::find(), you are actually asking for a new instance, either an instance of Collection or a QueryBuilder.

Illuminate\Database\Eloquent\Model (reference):

public static function find($id, $columns = array('*'))
{
    if (is_array($id) && empty($id)) return new Collection;

    $instance = new static;

    return $instance->newQuery()->find($id, $columns);
}

As a side note, you'll also see another way of using static methods in Laravel e.g. Input::get(). These are called Facades.

Facades provide a "static" interface to classes that are available in the application's IoC container ... Laravel "facades" serve as "static proxies" to underlying classes in the IoC container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.

When a user references any static method on the ... facade, Laravel resolves the cache binding from the IoC container and runs the requested method (in this case, get) against that object.

You can read more about Larave's Facades at: http://laravel.com/docs/facades



回答2:

Unnawut has a very good answer, however I felt it necessary to add in further explanation.

In your example

$user = User::find(1);
var_dump($user->name);

Laravel isn't using a static method, you are. Another way to do this which you are probably looking for is to use dependency injection, which Laravel makes very easy because it can be done automatically. So in whatever class you are using your User model in, you should be setting up something like this in the constructor...

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

And then you can modify your code to not use the static bindings.

$user = $this->user->find(1);
var_dump($user->name);


回答3:

This would restrict the system from only having one User. Whilst the find method may be static, the User class will have other methods and properties that aren't, a likely example is in your example: $user->name

A method that does not rely upon any instance variables, I.e variables who's value is specific to the particular object instance, but instead provides generic functionality that applies to all instances, can, and probably should, be static. This is why the $this operator is illegal within static methods, as it can make no reference to a particular object instance.



回答4:

Following the GRASP patterns, User object doesn't have the knowledge to able to search a User.

You need a kind of Filter or Collection object, the ::find() method helps you to create that Collection filter and cast the result in a useful entity.

For the uses of the User entity, you will just change the value of the properties and retrieve the values. The entity doesn't have the responsibility to search instances based on conditions.

With this logic you will be able to decouple logic in the code in atomic pieces.