我讨厌成为回答自己问题的人,但我讨厌成为不分享更有效的方法的人。
我最终创建了一个在数据级别执行连接和检查的视图。这使它成为一个简单的join 和ifnull,然后更改我的模型以使用该表而不是基础。这非常适合读取和查询,但显然不适用于 CRUD 操作。
由于此视图不可更新,我最终在准备进行任何写入时利用模型事件系统将模型切换到基表,然后在完成后返回。我选择了观察者模式,因为它让一切都保持整洁。
观察者:
<?php
namespace App\Models\Observers;
use App\Models\Contracts\IPersistTo;
/**
* Class PersistToObserver
*
*
* @package App\Models\Observers
*/
class PersistToObserver
{
protected function useReadTable(IPersistTo $model)
{
$model->setTable($model->getReadTable());
}
protected function useWriteTable(IPersistTo $model)
{
$model->setTable($model->getWriteTable());
}
/**
* Switch the model to use the write table before it goes to the DB
* @param IPersistTo $model
*/
public function creating(IPersistTo $model)
{
$this->useWriteTable($model);
}
/**
* Switch the model to use the write table before it goes to the DB
* @param IPersistTo $model
*/
public function updating(IPersistTo $model)
{
$this->useWriteTable($model);
}
/**
* Switch the model to use the write table before it goes to the DB
* @param IPersistTo $model
*/
public function saving(IPersistTo $model)
{
$this->useWriteTable($model);
}
/**
* Switch the model to use the write table before it goes to the DB
* @param IPersistTo $model
*/
public function deleting(IPersistTo $model)
{
$this->useWriteTable($model);
}
/**
* Switch the model to use the write table before it goes to the DB
* @param IPersistTo $model
*/
public function restoring(IPersistTo $model)
{
$this->useWriteTable($model);
}
/**
* Model has been written to the BD, switch back to the read table
* @param IPersistTo $model
*/
public function created(IPersistTo $model)
{
$this->useReadTable($model);
}
/**
* Model has been written to the BD, switch back to the read table
* @param IPersistTo $model
*/
public function updated(IPersistTo $model)
{
$this->useReadTable($model);
}
/**
* Model has been written to the BD, switch back to the read table
* @param IPersistTo $model
*/
public function saved(IPersistTo $model)
{
$this->useReadTable($model);
}
/**
* Model has been written to the BD, switch back to the read table
* @param IPersistTo $model
*/
public function deleted(IPersistTo $model)
{
$this->useReadTable($model);
}
/**
* Model has been written to the BD, switch back to the read table
* @param IPersistTo $model
*/
public function restored(IPersistTo $model)
{
$this->useReadTable($model);
}
}
IPersistTo 合约/接口
<?php
namespace App\Models\Contracts;
interface IPersistTo
{
/**
* @return string - the name of the table to read from (should be the same as the default $table)
*/
public function getReadTable();
/**
* @return string - the name of the table to write to
*/
public function getWriteTable();
/**
* Set the table associated with the model. Fulfilled by Model.
*
* @param string $table
* @return $this
*/
public function setTable($table);
}
我的模型中的设置(被截断为相关信息)
class Game extends Model implements IPersistTo {
protected $table = 'game_with_album_fallback';
/**
* @return string - the name of the table to read from (should be the same as the default $table)
*/
public function getReadTable()
{
return 'game_with_album_fallback';
}
/**
* @return string - the name of the table to write to
*/
public function getWriteTable()
{
return 'games';
}
}
最后将所有这些连接在一起,将以下行添加到 AppServiceProvider 的启动方法中:
Game::Observe(PersistToObserver::class);