Laravel5.4 怎么实现一个 Model 操作不同表名,并且做其他相关操作的时候,表名不发生变化

class Blog extends Model
{    
    protected  $table = 'default_table';
    private static $prefix;
    public $timestamps = false;
    public function __construct( $prefix = '' )
    {    
        self::$prefix = $prefix;
        $this->table= self::$prefix . '_blog';
        parent::__construct();        
    }
    
    public function insertOrUpdate($attributes, $prefix = '')
    {
        $ad = new self($prefix);
        return $ad;//这个位置的时候 调用的表名还是带有传进来的前缀的
        if (isset($attributes['id']) && $attributes['id']) {
//            $ad = DB::table($prefix . '_ad_category')->find($attributes['id']);
            $ad = $ad->where(['id'=>$attributes['id']])->first();
            dd($ad);//这个时候查的数据是带前缀的表名,但是对象里面的显示的表名发生了变化
            return $ad;
        }
        $ad->title = $attributes['title'];
        $ad->begin = $attributes['begin'];
        $ad->end = $attributes['end'];
        $ad->img = '';
        $ad->url = $attributes['url'];
        $ad->category_id = $attributes['category_id'];
        $ad->operator_id = $attributes['operator_id'];
        return $ad->save();//这个位置修改的就是未带前缀的表名了。我想知道怎么才能传进来前缀的时候,这个模型里全部使用的是指定的表,而不是在去调用默认的表

    }
    
}
阅读 9.5k
3 个回答

自问自答吧:
我们知道,要动态改变 Eloquent Model 的表名可以使用 setTable 方法:

$model = new MyLog();
$model->setTable('log_20170123');
echo $model->getTable(); // my_log

但是在 setTable 之后使用 create 插入数据,使用的还是原来的表:

$model = new MyLog();
$model->setTable('log_20170123');
echo $model->create($data); // insert into `my_log`...

来看看 setTable 的源码:

abstract class Model implements ArrayAccess...
{
    /**
     * Set the table associated with the model.
     *
     * @param  string  $table
     * @return $this
     */
    public function setTable($table)
    {
        $this->table = $table;

        return $this;
    }
//它设置的是 Model 类的表名。

//再来看看 create 方法:

    /**
     * Save a new model and return the instance.
     *
     * @param  array  $attributes
     * @return static
     */
    public static function create(array $attributes = [])
    {
        $model = new static($attributes);

        $model->save();

        return $model;
    }

注意,这里 new 的是 static 关键字。自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。 这里不做详细说明,具体参考:后期静态绑定。
也就是说 create 的时候并没有进行修改表名的操作,而实例化的是你继承了 Model 类的子类的类名。

那么怎么解决呢?

$model = new MyLog($data);
$model->setTable($your_table_name);
$model->save();

即可!
举例子:

$fix = 'ux';
$categories = new Post();
if(!!$fix)$categories->setTable($fix.'_'.$categories->getTable());
$post = $categories->find(8500);
$post->title= '999999';
$post->id = 8500;
$post->setTable($fix.'_'.$post->getTable());
dd($post->save());

作者:伍源辉
链接:http://www.jianshu.com/p/e119...

表名一般不用自己去拼接的吧。。。都是你设置prefix,系统调用的自己会去拼接

父类中,有实现表名的赋值吗? parent::__construct() 放到前面比较好。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题