我正在尝试获取所有模型的关联数组。我有以下型号:
class Article extends Eloquent
{
protected $guarded = array();
public static $rules = array();
public function author()
{
return $this->belongsTo('Author');
}
public function category()
{
return $this->belongsTo('Category');
}
}
从这个模型中,我试图获得以下关系数组:
array(
'author',
'category'
)
我正在寻找一种方法从模型中自动拉出这个数组。
我在Eloquent模型上找到了relationshipToArray方法的this定义,它似乎返回了模型关系的数组。它似乎使用了Eloquent模型的$ this-> relations属性。但是,尽管我的关系设置正确,但此方法返回一个空数组,而relations属性是一个空数组。
什么是$ this->关系如果不存储模型关系?有什么方法可以自动获得模型关系的数组吗?
答案 0 :(得分:29)
这是不可能的,因为只有在使用with
(用于预先加载)或使用模型中定义的关系公共方法请求时才会加载关系,例如,如果创建了Author
模型以下关系
public function articles() {
return $this->hasMany('Article');
}
当您将此方法称为:
时$author = Author::find(1);
$author->articles; // <-- this will load related article models as a collection
另外,正如我所说with
,当你使用这样的东西时:
$article = Article::with('author')->get(1);
在这种情况下,第一篇文章(ID为1)将加载其相关模型Author
,您可以使用
$article->author->name; // to access the name field from related/loaded author model
所以,如果没有使用适当的方法来加载关系,就不可能神奇地获得关系,但是一旦加载了关系(相关模型),那么你可以使用类似的东西来获得关系:
$article = Article::with(['category', 'author'])->first();
$article->getRelations(); // get all the related models
$article->getRelation('author'); // to get only related author model
要将它们转换为array
,您可以使用toArray()
方法,例如:
dd($article->getRelations()->toArray()); // dump and die as array
relationsToArray()
方法适用于加载了相关模型的模型。此方法将相关模型转换为数组形式,其中toArray()
方法将模型的所有数据(带关系)转换为数组,这里是源代码:
public function toArray()
{
$attributes = $this->attributesToArray();
return array_merge($attributes, $this->relationsToArray());
}
在转换为数组后,它会合并模型属性及其相关模型的属性,然后返回它。
答案 1 :(得分:3)
使用它:
class Article extends Eloquent
{
protected $guarded = array();
public static $rules = array();
public $relationships = array('Author', 'Category');
public function author() {
return $this->belongsTo('Author');
}
public function category() {
return $this->belongsTo('Category');
}
}
所以在课外你可以这样做:
public function articleWithAllRelationships()
{
$article = new Article;
$relationships = $article->relationships;
$article = $article->with($relationships)->first();
}
答案 2 :(得分:1)
GruBhub,非常感谢您的评论。我已经更正了你提到的错字。
你说得对,运行未知方法是危险的,因此我在执行后添加了回滚。
也非常感谢来自 laracasts 的 phildawson,https://laracasts.com/discuss/channels/eloquent/get-all-model-relationships
您可以使用以下特征:
<?php
namespace App\Traits;
use Illuminate\Database\Eloquent\Relations\Relation;
trait EloquentRelationshipTrait
{
/**
* Get eloquent relationships
*
* @return array
*/
public static function getRelationships()
{
$instance = new static;
// Get public methods declared without parameters and non inherited
$class = get_class($instance);
$allMethods = (new \ReflectionClass($class))->getMethods(\ReflectionMethod::IS_PUBLIC);
$methods = array_filter(
$allMethods,
function ($method) use ($class) {
return $method->class === $class
&& !$method->getParameters() // relationships have no parameters
&& $method->getName() !== 'getRelationships'; // prevent infinite recursion
}
);
\DB::beginTransaction();
$relations = [];
foreach ($methods as $method) {
try {
$methodName = $method->getName();
$methodReturn = $instance->$methodName();
if (!$methodReturn instanceof Relation) {
continue;
}
} catch (\Throwable $th) {
continue;
}
$type = (new \ReflectionClass($methodReturn))->getShortName();
$model = get_class($methodReturn->getRelated());
$relations[$methodName] = [$type, $model];
}
\DB::rollBack();
return $relations;
}
}
然后你可以在任何模型中实现它。
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;
use App\Traits\EloquentRelationshipTrait;
class User extends Authenticatable
{
use Notifiable, HasApiTokens, EloquentRelationshipTrait;
最后使用 (new User)->getRelationships() 或 User::getRelationships() 你会得到:
[
"notifications" => [
"MorphMany",
"Illuminate\Notifications\DatabaseNotification",
],
"readNotifications" => [
"MorphMany",
"Illuminate\Notifications\DatabaseNotification",
],
"unreadNotifications" => [
"MorphMany",
"Illuminate\Notifications\DatabaseNotification",
],
"clients" => [
"HasMany",
"Laravel\Passport\Client",
],
"tokens" => [
"HasMany",
"Laravel\Passport\Token",
],
]