Laravel 动态扩展或使用 Traits

问题描述 投票:0回答:4

可以在运行时扩展或使用不同的类吗?

示例: 假设我们有一个

model
称为
Player
(我们的 A 模型)

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Player extends Model{

}

我们还有另外 2 个型号(B 和 C 型号

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

protected $connection= 'db_b';

class PlayerInfoB extends Model{
    function getName(){
        return $this->name;
    }
}

我们的C型号

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

protected $connection= 'db_c';

class PlayerInfoC extends Model{
    function getName(){
        return $this->name_g;
    }
}

模型

A (Player)
如何在运行时根据配置或其他数据扩展
Model B or C

为什么我需要这个。 我有 2 个或更多不同的表,这些表的列有不同的名称,例如:

Table 1 - name

Table 2 - name_g

Table 3 - name_full

所以我需要一个可以随时调用的包装器

getName()
,而无需检查现在使用的表。

$player = Player::get();

echo $player->getName();

如果有不清楚的地方,请评论,我会更新我的问题。

更新基于madalin-ivascu答案可以这样完成吗?

class Player extends Model{
    protected $model;          

    public function __construct(){

        $this->setModel();

        parent::__construct();


    }
    protected function setModel(){
        $this->model = $this->column_model_name
    }
    function getAttributeName(){
        return $this->model->getName();
    }

}
php laravel laravel-5 model traits
4个回答
0
投票

如果不使用 eval 或 dirty hacks,就不可能在运行时编写一个类。您必须重新考虑您的类设计,因为您不太可能需要通过良好的设计来做到这一点。

您可以做的是使用方法

setTable
on
:

在运行时更改模型实例上的表和数据库连接
Player::on('db_b')->setTable('player_info_b')->find($id);

另一种方法(首选)是定义模型

PlayerInfoC
PlayerInfoB
来扩展您的
Player
模型,然后根据您的情况在需要时实例化类
B
C


0
投票

在您的代码中,您的脚本必须具有您检查的状态,以便知道何时使用正确的模型?

既然如此,为什么不在 get name 中使用参数呢?

class Player extends Model{

    function getName($field){
        return isset($this->{$field}) ? $this->{$field} : null;
    }

}

如果你经常这样做,那么使用魔法方法:

class Player extends Model{

    function __get($key){

        return isset($this->{$field}) ? $this->{$field} : null;
    }

}

...

echo $myModelInstance->{$field};

http://php.net/manual/en/language.oop5.overloading.php#object.get

在 Laravel 中,当你通过集合方法拉回数据时,它无论如何都会执行这个神奇的方法,因为所有属性都存储在称为属性的嵌套对象中,因此 __set() 和 __get() 看起来像这样:

function __get($key){

    return isset($this->attributes->{$key}) ? $this->attributes->{$key} : null;

}

function __set($key, $value){

    return $this->attributes->{$key} = $value;

}

建议后者带有属性子集,这样可以防止数据与返回的数据库列名称与模型中已使用的名称发生冲突。 这样,您只需在创建的每个模型中将一个属性名称作为保留名称进行管理,而不必担心您使用的数百个 var 名称会覆盖模型或模型扩展中的另一个属性名称。


0
投票

使用该模型值来调用函数

$player = Player::get();

echo Player::getName($player->id,'PlayerInfoC');

在 Player 模型中您只需调用

public static function getName($id,$class)
   return $class::where('player_id',$id)->getName();//each class will have the function
}

ps:您需要进行一些验证来测试该名称是否存在

另一种选择是在模型之间创建关系


0
投票

您可以在模型中使用与以下相同的启动方法来执行此操作:

protected static function booted()
{
    if (<--your condition-- >) {
        $traitInitializers[static::class][] = 'boot' . ExampleTrait::class;
        $traitInitializers[static::class][] = 'boot' . Organizations::class;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.