Len*_*eng 6 php mysql laravel eloquent laravel-4
此软件包中的所有模型都与IoC容器绑定并解析,以便在软件包的任何单独部署中轻松覆盖它们.
对于非多态关系,这有一定的魅力.
例如,一个Page有很多PageModules,所以它的关系改为:
// \Angel\Core\Page
public function modules()
{
return $this->hasMany('PageModule');
}
Run Code Online (Sandbox Code Playgroud)
至:
// \Angel\Core\Page
public function modules()
{
return $this->hasMany(App::make('PageModule'));
}
Run Code Online (Sandbox Code Playgroud)
但是我无法弄清楚如何用多态关系做同样的事情.
例如,菜单包含MenuItems,每个MenuItem可以绑定到一个其他模型,例如Page或BlogPost.
为了实现这个Laravel方式,我为MenuItem添加了以下关系:
// \Angel\Core\MenuItem
public function linkable()
{
return $this->morphTo();
}
Run Code Online (Sandbox Code Playgroud)
而这种关系LinkableModel,其全系车型,如网页和博客帖子延伸:
// \Angel\Core\LinkableModel
public function menuItem()
{
return $this->morphOne(App::make('MenuItem'), 'linkable');
}
Run Code Online (Sandbox Code Playgroud)
和menus_items表(其中的MenuItems使用)具有以下行:
linkable_type | linkable_id
-------------------|--------------
\Angel\Core\Page | 11
\Angel\Core\Page | 4
Run Code Online (Sandbox Code Playgroud)
这很好用,但是我需要linkable_type说'Page'而不是'\ Angel\Core\Page',并且要从IoC的'Page'中解析而不是硬编码到特定的命名空间类.
我试过的:
根据这个问题,它应该像为$morphClasslinkable()类定义属性一样容易,如下所示:
// \Angel\Core\Page
protected $morphClass = 'Page';
Run Code Online (Sandbox Code Playgroud)
但是当我应用它时,将menus_items表更改为如下所示:
linkable_type | linkable_id
---------------|--------------
Page | 11
Page | 4
Run Code Online (Sandbox Code Playgroud)
... Class 'Page' not found.只要在MenuItem上调用linkable(),我就会收到错误.
所以,我挖到了Eloquent,并认为我可以逃脱这样的事情:
// \Angel\Core\MenuItem
public function linkable()
{
return $this->morphTo(null, App::make($this->linkable_type));
}
Run Code Online (Sandbox Code Playgroud)
...感觉非常接近,但是唉:Eloquent在填充MenuItem的其余属性/列之前调用linkable(),因此$ this-> linkable_type为null,因此无法解决IoC中的任何问题.
非常感谢您提供任何指导!
public function linkable()
{
return $this->morphTo(null, App::make($this->linkable_type));
}
Run Code Online (Sandbox Code Playgroud)
这在任何情况下都不起作用,因为morphTo()在Illuminate\Database\Eloquent\Model中
期望
Page)如果没有提供它们,Laravel 足够聪明,可以猜测它们,然后相应地返回一个Illuminate\Database\Eloquent\MorphTo对象。
$this->linkable_type而且,$this->linkable_id实际上不应该null在这种情况下。
让我们快速浏览一下该morphTo()函数的相关部分:
$instance = new $class;
return new MorphTo(
$instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name
);
Run Code Online (Sandbox Code Playgroud)
注意:这是 4.2.6 版本中的代码,上面链接的代码似乎来自更高版本,并且略有不同,并且该函数返回 a
BelongsTo而不是MorphTo对象。
问题在于$instance = new $class;- 该类只是实例化而没有解决。但你可以抓住这部分魔法并自己处理它:
public function linkable()
{
$instance = App::make($this->linkable_type);
$id = 'linkable_id';
$type = 'linkable_type';
$name = 'linkable';
return new MorphTo(
$instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name
);
}
Run Code Online (Sandbox Code Playgroud)
这实际上应该有效(尚未测试过),但我不确定它在某些边缘情况下可能会导致任何副作用。
或者,也许您也可以覆盖模型中的整个函数MenuItem,然后调整相关部分:
public function morphTo($name = null, $type = null, $id = null)
{
if (is_null($name))
{
list(, $caller) = debug_backtrace(false);
$name = snake_case($caller['function']);
}
list($type, $id) = $this->getMorphs($name, $type, $id);
//eager loading
if (is_null($class = $this->$type))
{
return new MorphTo(
$this->newQuery(), $this, $id, null, $type, $name
);
}
// normal lazy loading
else
{
// this is the changed part
$instance = \App::make($class); // new $class;
return new MorphTo(
$instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name
);
}
}
Run Code Online (Sandbox Code Playgroud)
注意:这适用于延迟加载,但不适用于急切加载。 此处提出了寻求急切加载解决方案的问题。
那么关系就会像往常一样:
public function linkable()
{
return $this->morphTo();
}
Run Code Online (Sandbox Code Playgroud)