Laravel动态扩展或使用Traits

时间:2017-10-12 07:32:07

标签: php laravel laravel-5 model traits

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

实施例: 假设我们有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

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

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();
    }

}

3 个答案:

答案 0 :(得分:0)

使用该模型值来调用函数

$player = Player::get();

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

在播放器模型中,您只需调用

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

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

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

答案 1 :(得分:0)

在不使用eval或者脏兮兮的黑客攻击的情况下,无法在运行时编写calss。你必须重新考虑你的课堂设计,因为你不太可能需要用一个好的设计来做到这一点。

您可以做的是使用方法setTableon在模型实例上更改运行时的表和数据库连接:

Player::on('db_b')->setTable('player_info_b')->find($id);

另一种方法(首选)是定义扩展PlayerInfoC模型的模型PlayerInfoBPlayer,然后根据您的条件实例化类B

C

答案 2 :(得分: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中,当你通过集合方法撤回数据时,无论如何它都会执行这个神奇的方法,因为所有属性都存储在一个名为attributes的嵌套对象中,所以__set()和__get()看起来像这样:

function __get($key){

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

}

function __set($key, $value){

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

}

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