Home  >  Article  >  PHP Framework  >  A late static binding in Laravel

A late static binding in Laravel

藏色散人
藏色散人forward
2019-10-23 13:43:092212browse

Regarding PHP's new static delayed static binding, or late static binding, I encountered a usage problem in Laravel. As follows, when calling the Model in Laravel to add new data, first add a method to the Model to obtain the sub-table:

protected function addToMessage($msgType, $userID, $commentID, $replyCommentID, $replyUserID, $gameID)
{
    if (!$userID) {
        return false;
    }
 
    $table = 't_message_' . hashID($userID, 100);
    $this->message->setTable($table)->create([
        'msg_type'         => $msgType,
        'user_id'          => $userID,
        'comment_id'       => $commentID,
        'reply_comment_id' => $replyCommentID,
        'reply_user_id'    => $replyUserID,
        'game_id'          => $gameID,
        'is_read'          => 0,
        'created_at'       => date('Y-m-d H:i:s'),
    ]);
    return true;
}

The setTable method here is the method defined in the Model to obtain the sub-table:

public function setTable($table)
{
    $this->table = $table;
    return $this;
}

I found from the error log that $this->table did not take effect, but in fact when the table name was printed before calling the create method, it was the expected value. Why was $this->table not being used when the create method was called here? What about reset?

Here $this->message is a model class that inherits the Model class, where the create method:

public static function create(array $attributes = [])
{
    $model = new static($attributes);
 
    $model->save();
 
    return $model;
}

is located in vendorlaravelframeworksrcIlluminateDatabaseEloquentModel.php Line 557.

Because of the Laravel framework This Model class is an abstract type. In PHP, abstract classes can be instantiated using new static late static binding, and $model = new static($attributes) in the create method actually re-instantiates and returns, and calling The Model class does not define the table attribute, so $this->table has no value at this time.

A late static binding in Laravel

The solution is to use the save method, as shown in the figure. In fact, the create method also calls the save method.

Experiment

An abstract class A has a create method, which is instantiated and returned through delayed static binding. Class B inherits A, and the name attribute of the parent class is modified in the test method.

<?php
 
abstract class A
{
    protected $name = "tanteng";
 
    public static function create()
    {
        return new static();
    }
}
 
class B extends A
{
    //protected $name = &#39;纸牌屋弗兰克&#39;;
 
    public function test()
    {
        $this->name = "Tony Tan";
        return $this;
    }
}
 
$obj1 = (new B)->test();
$obj2 = (new B)->test()->create();
var_dump($obj1);
var_dump($obj2);

The results show that both instances of $obj1 and $obj2 are instances of B. The attribute name has changed by calling the test method, but the name attribute has not changed after calling the create method. This is the scene encountered in Lavarel mentioned in this article. (If the annotation is turned on here, the printed name is the rewritten value)

If the abstract class A is changed to a normal class, and new static is changed to new self for instantiation, the result will be different, the printed The attribute name is an attribute of the respective class.

For more Laravel related technical articles, please visit the Laravel Framework Getting Started Tutorial column to learn!

The above is the detailed content of A late static binding in Laravel. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete