水平分割させたいモデルの基底クラス
HorizonModelBase.php
class HorizonModelBase
{
use SoftDeletingTrait;
private static $isEnableGlobalConnection = false;
public function newQuery($excludeDeleted = true)
{
$this->setOwnConnection();
$builder = parent::newQuery($excludeDeleted);
$this->resetOwnConnection();
return $builder;
}
public function newFromBuilder($attributes = array())
{
$this->setOwnConnection();
$result = parent::newFromBuilder($attributes);
$this->resetOwnConnection();
return $result;
}
public static function aroundQuery($func)
{
self::$isEnableGlobalConnection = true;
$result_collection = new Collection();
foreach(self::getAroundConnections() as $connection)
{
Config::set('database.default', $connection);
$result_collection = $result_collection->merge(call_user_func($func));
}
Config::set('database.default', "mastar_data");
$result_collection->sortBy(function($record){return $record->id;})->values();
self::$isEnableGlobalConnection = false;
return $result_collection;
}
public static function aroundAll()
{
return self::aroundQuery(function(){
return self::all();
});
}
private static function getAroundConnections()
{
return Config::get("database.user_db_connections");
}
private function setOwnConnection()
{
if (self::$isEnableGlobalConnection) { return; }
if (property_exists($this, "user_id"))
{
$connection_no = $this->user_id % Config::get("database.user_db_connection_count");
}
else
{
$connection_no = $this->id % Config::get("database.user_db_connection_count");
}
$connection = "user_data_" . strval($connection_no);
$this->setConnection($connection);
}
private function resetOwnConnection()
{
if (self::$isEnableGlobalConnection) { return; }
$this->setConnection('user_data_0');
}
}
Eloquentの変更を最小限にしつつ、従来通りの使い方で、データアクセス出来ないだろうかと模索した結果、こんな感じになった。
Config::get("database.user_db_connections");
global.phpのどっかで、上記コンフィグの設定はしとかないとダメ。
使うときは
User.php
class User extends HorizonModelBase
{
}
Test.php
$users = User::aroundQuery(function(){
User::where('level', 10)->where('friend_num', '>', '3')->get();
}
echo $users;
みたいな感じ。
かなりやっつけ実装だが、まあ正常に動く。
ページネートどうするかとか、凝ったクエリー流したいときとか、
色々問題は出ててきそうだが・・・
もっと良い実装は無いだろうか・・・。