首页 > 解决方案 > 为什么 Laravel 实例化一个类来获取一个属性,而不是将该属性设置为静态?

问题描述

Eloquent\Model 类有一个名为table的受保护属性。为了获取该属性的值,Laravel 创建了一个父类的新实例,然后获取该值:

(new static)->table

为什么不将属性设置为静态?接着:

MyModel::$table

或者

static::$table

标签: phplaraveleloquent

解决方案


一个可能的原因是静态变量对于所有派生模型都是相同的,因此很难跟踪派生类型的表名。

class Base
{
    public static $table;
}

class Derived1 extends Base { }
class Derived2 extends Base { }

Base::$table = "Table";

echo Derived1::$table;
echo Derived2::$table;

在这里,两个派生类将具有相同的表名。

此外,new static()将创建调用该方法的类的实例。

class Base
{
    public $table;

    public static function create($table)
    {
        // Create instace of derived class
        $instance = new static();
        $instance->table = $table;
        return $instance;
    }
}

class Derived1 extends Base { }
class Derived2 extends Base { }

print_r(Derived1::create("Table1"));  
print_r(Derived2::create("Table2"));

在这种情况下,每个实例都有自己的表属性,甚至基类实例中的工厂方法也将是被调用的类型。

更新 如果您想在基类中使用静态变量并且仍然能够具有不同的值,那么您将使用类名是键的映射。

class Base
{
    private static $table;

    public static function create($table)
    {
        $instance = new static();
        self::$table[get_class($instance)] = $table;
        return $instance;
    }

    public function getTableName()
    {
        return self::$table[get_class($this)];
    }
}

class Derived1 extends Base { }
class Derived2 extends Base { }

$d1 = Derived1::create("Table1");
$d2 = Derived2::create("Table2");

echo $d1->getTableName(); //prints Table1
echo $d2->getTableName(); //prints Table2

推荐阅读