Mar*_*der 20
不,它不是,至少没有一些额外的工作,因为你的模型在实际加载之前不知道它支持哪种关系.
我在我自己的一个Laravel软件包中遇到了这个问题.没有办法获得模型与Laravel的关系列表.如果你看看它们是如何定义的,那就很明显了.返回Relation对象的简单函数.你甚至无法使用php的反射类获得函数的返回类型,因此无法区分关系函数和任何其他函数.
您可以做的更容易的是定义一个添加所有关系的函数.为此,您可以使用eloquents查询范围(感谢Jarek Tkaczyk在评论中提及它).
public function scopeWithAll($query)
{
$query->with('foo', 'bar', 'baz');
}
Run Code Online (Sandbox Code Playgroud)
使用范围而不是静态函数不仅允许您直接在模型上使用函数,而且还可以在where以任何顺序链接查询构建器方法时使用:
Model::where('something', 'Lorem ipsum dolor')->withAll()->where('somethingelse', '>', 10)->get();
Run Code Online (Sandbox Code Playgroud)
虽然Laravel不支持开箱即用的东西,但你可以自己添加它.
我使用注释来确定函数是否是我上面提到的包中的关系.注释不是php的正式部分,但很多人使用doc块来模拟它们.Laravel 5也将在其路线定义中使用注释,因此我认为在这种情况下它不是不好的做法.优点是,您不需要维护单独的受支持关系列表.
为每个关系添加注释:
/**
* @Relation
*/
public function foo()
{
return $this->belongsTo('Foo');
}
Run Code Online (Sandbox Code Playgroud)
并编写一个函数来解析模型中所有方法的doc块并返回名称.您可以在模型或父类中执行此操作:
public static function getSupportedRelations()
{
$relations = [];
$reflextionClass = new ReflectionClass(get_called_class());
foreach($reflextionClass->getMethods() as $method)
{
$doc = $method->getDocComment();
if($doc && strpos($doc, '@Relation') !== false)
{
$relations[] = $method->getName();
}
}
return $relations;
}
Run Code Online (Sandbox Code Playgroud)
然后在你的withAll函数中使用它们:
public function scopeWithAll($query)
{
$query->with($this->getSupportedRelations());
}
Run Code Online (Sandbox Code Playgroud)
有些像php中的注释,有些则没有.我喜欢这个简单的用例.
您还可以维护所有受支持关系的数组.然而,这需要您始终将其与可用关系同步,尤其是如果涉及多个开发人员,这并不总是那么容易.
protected $supportedRelations = ['foo','bar', 'baz'];
Run Code Online (Sandbox Code Playgroud)
然后在你的withAll函数中使用它们:
public function scopeWithAll($query)
{
return $query->with($this->supportedRelations);
}
Run Code Online (Sandbox Code Playgroud)
你当然也可以覆盖with他的答案中提到的lukasgeiter.这似乎比使用更清洁withAll.如果您使用注释或配置数组,则是一个意见问题.
如果不亲自指定它们,就无法知道所有关系是什么。发布的其他答案都很好,但我想补充一些内容。
我感觉你想在多个模型中执行此操作,所以BaseModel如果你还没有的话,首先我会创建一个。
class BaseModel extends Eloquent {
public $allRelations = array();
}
Run Code Online (Sandbox Code Playgroud)
我建议您使用成员变量,而不是将关系硬编码到方法中。正如你在上面看到的,我已经添加了$allRelations. 请注意,您无法命名它,$relations因为 Laravel 已经在内部使用了它。
with()既然你愿意,with(*)你也可以这样做。将其添加到BaseModel
public static function with($relations){
$instance = new static;
if($relations == '*'){
$relations = $instance->allRelations;
}
else if(is_string($relations)){
$relations = func_get_args();
}
return $instance->newQuery()->with($relations);
}
Run Code Online (Sandbox Code Playgroud)
(顺便说一下,这个函数的某些部分来自于原来的Model类)
class MyModel extends BaseModel {
public $allRelations = array('foo', 'bar');
}
MyModel::with('*')->get();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12058 次 |
| 最近记录: |