I am using the Laravel Framework and this question is directly related to using Eloquent within Laravel.
我试图建立一个Eloquent 的模型,可以在多个不同的表格中使用.原因是我有多个基本相同但每年都不同的表,但我不想重复代码来访问这些不同的表.
- gamedata_2015_nations
- gamedata_2015_leagues
- gamedata_2015_团队
- gamedata_2015_players
我当然可以有一个带有年份栏的大桌子,但由于每年有超过35万行,而且要处理很多年,我决定最好将它们拆分为多个表格,而不是在每个请求上都有额外"where"的4个大桌子.
So what I want to do is have one class for each and do something like this within a Repository class:
public static function getTeam($year, $team_id)
{
$team = new Team;
$team->setYear($year);
return $team->find($team_id);
}
I have used this discussion on the Laravel forums to get me started: http://laravel.io/forum/08-01-2014-defining-models-in-runtime
So far I have this:
class Team extends \Illuminate\Database\Eloquent\Model {
protected static $year;
public function setYear($year)
{
static::$year= $year;
}
public function getTable()
{
if(static::$year)
{
//Taken from https://github.com/laravel/framework/blob/4.2/src/Illuminate/Database/Eloquent/Model.php#L1875
$tableName = str_replace('\\', '', snake_case(str_plural(class_basename($this))));
return 'gamedata_'.static::$year.'_'.$tableName;
}
return Parent::getTable();
}
}
这似乎有效,但我担心它没有以正确的方式工作.
因为我使用的是静电关键字,所以属性$Year保留在类中,而不是每个单独的对象中,所以每当我创建新对象时,它仍然持有基于上次在不同对象中设置的$Year属性.我宁愿$Year与单个对象相关联,并且需要在每次创建对象时进行设置.
Now I am trying to track the way that Laravel creates Eloquent models but really struggling to find the right place to do this.
For instance if I change it to this:
class Team extends \Illuminate\Database\Eloquent\Model {
public $year;
public function setYear($year)
{
$this->year = $year;
}
public function getTable()
{
if($this->year)
{
//Taken from https://github.com/laravel/framework/blob/4.2/src/Illuminate/Database/Eloquent/Model.php#L1875
$tableName = str_replace('\\', '', snake_case(str_plural(class_basename($this))));
return 'gamedata_'.$this->year.'_'.$tableName;
}
return Parent::getTable();
}
}
当试图组建单个团队时,这一点工作得很好.然而,在人际关系中,这是行不通的.这是我在人际关系中try 过的:
public function players()
{
$playerModel = DataRepository::getPlayerModel(static::$year);
return $this->hasMany($playerModel);
}
//This is in the DataRepository class
public static function getPlayerModel($year)
{
$model = new Player;
$model->setYear($year);
return $model;
}
Again this works absolutely fine if i'm using static::$year, but if I try and change it to use $this->year then this stops working.
The actual error stems from the fact that $this->year is not set within getTable() so that the parent getTable() method is called and the wrong table name returned.
我的下一步是try 找出为什么它使用静电属性,而不是非静态属性(不确定用于该属性的正确术语).当我试图建立球员关系时,我假设它只是使用团队类中的静电::$Year.然而,情况并非如此.如果我try 使用类似于以下内容的命令强制执行错误,请执行以下操作:
public function players()
{
//Note the hard coded 1800
//If it was simply using the old static::$year property then I would expect this still to work
$playerModel = DataRepository::getPlayerModel(1800);
return $this->hasMany($playerModel);
}
现在发生的是,我得到一个错误,说找不到gamedata_1800_玩家.也许这并不奇怪.但它排除了Eloquent只是使用Team类中的static::$year属性的可能性,因为它明确地设置了我发送给getPlayerModel()方法的自定义年份.
所以现在我知道,当$Year在关系中设置并且是静态设置的时候,gettable()可以访问它,但是如果它是非静态设置的,那么它就会丢失在某个地方,并且对象在调用gettable()时不知道这个属性.
(note the significance of it working different when simply creating a new object and when using relationships)
我意识到我已经给出了很多细节,所以为了简化和澄清我的问题:
1) Why does static::$year work but $this->year not work for relationships, when both work when simply creating a new object.
2) Is there a way that I can use a non static property and achieve what I am already achieving using a static property?
理由:静态属性将保留在类中,即使我已经完成了一个对象,并试图用该类创建另一个对象,这似乎是不对的.
Example:
//Get a League from the 2015 database
$leagueQuery = new League;
$leagueQuery->setYear(2015);
$league = $leagueQuery->find(11);
//Get another league
//EEK! I still think i'm from 2015, even though nobodies told me that!
$league2 = League::find(12);
This may not be the worst thing in the world, and like I said, it is actually working using the static properties with no critical errors. However it is dangerous for the above code sample to work in that way, so I would like to do it properly and avoid such a danger.