我已经在这里呆了5个小时了,似乎无法弄清错误。我在Laravel 4.1中使用了多态多对多关系。
一个工作和一个事件都可以有一个标签,我已经相应地设置了东西。但是每当我打电话给
$job->tags
它返回空。
我有这3个类(BaseModel扩展了Eloquent,名称空间始终是App \ Models,我必须在例如“ morphToMany”函数中引用它们,不适用于“ use”):
class Job extends BaseModel {
public function tags()
{
return $this->morphToMany('\App\Models\Tag', 'taggable');
}
[...]
}
标记模型:
class Tag extends BaseModel {
public function jobs(){
return $this->morphedByMany('\App\Models\Job', 'taggable');
}
public function events(){
return $this->morphedByMany('\App\Models\Event', 'taggable');
}
[...]
}
事件模型(如会议,研讨会中的“事件”-具有自己的命名空间App \ Models以避免冲突):
class Event extends BaseModel {
[... nothing relevant yet ...]
}
在我的JobsController中(测试用例,ID为14的作业存在)
public function show($slug)
{
$job = Job::find(14);
return \View::make('jobs.show', ['job' => $job]);
}
和我的应用程序/视图/作业/show.blade.php
[...]
echo $job->name;
echo $job->company;
foreach($job->tags as $tag) {
echo $tag->name;
}
[...]
第一个输出工作正常,它正确显示了$ job-> name和$ job-> company,因此它正确地从jobs表中读取,但是
$job->tags
返回空AND $ tag-> name不会被调用。我有一个标签和可标记表(MySQL),这是相关行
taggables (table)
-> id->increments()
-> tag_id->integer()->unsigned()->index
->foreign('tag_id')->references('id')->on('tag')
-> taggable_id->integer()->unsigned()->index()
-> taggable_type->string()->index()
tags (table)
-> id->increments()
-> name->string()
-> slug->string()
测试1
当我这样做
$jobs = Job::has('tags')->get();
在我的JobsController.php视图中,它实际上仅返回具有标签的作业,因此我有点希望它能起作用。
测试2
但是当我尝试获取标签时,例如在这种index.blade.php情况下
foreach($jobs as $job){
foreach($job->tags as $tag){
echo $tag->name;
}
}
它进入$ jobs循环很好,但没有进入$ job-> tags循环。在我的标签表中,我有一个数据集
taggables
id: 1
tag_id: 1 (exists)
taggable_id: 14 (via foreign key)
taggable_type: Job
我疯了,无法弄清楚问题出在哪里。我想念什么吗?
更清洁的溶液
我已经一直使用扩展了Eloquent的BaseModel。然后,模型仅扩展BaseModel,因此可以对Eloquent进行一些更改。然后,我可以使用相同的内容,只需做一个小小的改动就可以轻松地覆盖Eloquent morphToMany()
函数:
<?php namespace App\Models;
class BaseModel extends \Illuminate\Database\Eloquent\Model {
public function morphToMany($related, $name, $table = null, $foreignKey = null, $otherKey = null, $inverse = false)
{
$caller = $this->getBelongsToManyCaller();
$foreignKey = $foreignKey ?: $name.'_id';
$instance = new $related;
$otherKey = $otherKey ?: $instance->getForeignKey();
$query = $instance->newQuery();
$table = $table ?: str_plural($name);
// Only Change: MyMorphToMany instead of the standard MorphToMany
return new \MyMorphToMany(
$query, $this, $name, $table, $foreignKey,
$otherKey, $caller, $inverse
);
}
[...]
}
由于morphedByMany()
函数实际上也调用了morphToMany()
,因此对于多态多对多关系,无需重写它。然后,我继续复制整个
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphToMany.php
to
app/models/MyMorphToMany.php
仅作一些更改:
<?
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\MorphPivot;
// no namespace, instead call it when extending
// additionally use Illuminate\Database\Eloquent\Relations\MorphPivot;
// Class MyMorphToMany instead of MorphToMany
class MyMorphToMany extends Illuminate\Database\Eloquent\Relations\BelongsToMany {
[...]
public function __construct(Builder $query, Model $parent, $name, $table, $foreignKey, $otherKey, $relationName = null, $inverse = false)
{
$this->inverse = $inverse;
$this->morphType = $name.'_type';
$this->morphClass = $inverse ? get_class($query->getModel()) : get_class($parent);
// This is the change to cut everything after "\" in the namespaced Class
$this->morphClass = substr($this->morphClass, strrpos($this->morphClass, '\\') + 1);
parent::__construct($query, $parent, $table, $foreignKey, $otherKey, $relationName);
}
[...]
}
我认为应该这样做。您现在应该可以使用现在将morphToMany('App\Models\Tag', 'taggable');
用于Laravel中的多态多对多关系。
感谢https://stackoverflow.com/a/19884991/3347365的提示。
先前的评论/解决方案
这很奇怪。当我删除名称空间时,它起作用了!我删除了Job和Tag类的名称空间,因此可以通过
进行调用public function tags(){
return $this->morphToMany('Tag', 'taggable');
}
在工作模型中代替
public function tags(){
return $this->morphToMany('App\Models\Tag', 'taggable');
}
并且有效!这是错误还是我执行错误?我主要使用PSR-4,但不确定是否与此有关。
对于较新版本的Laravel,有一个内置解决方案:morphMaphttps://laravel.com/docs/7.x/eloquent-relationships#custom-polymorphic-types