Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 同一模型上的Laravel-Manytomy关系_Php_Mysql_Laravel_Eloquent_Relationship - Fatal编程技术网

Php 同一模型上的Laravel-Manytomy关系

Php 同一模型上的Laravel-Manytomy关系,php,mysql,laravel,eloquent,relationship,Php,Mysql,Laravel,Eloquent,Relationship,我试图在我的标签模型上建立一个双向的多人关系,但我遇到了这个“问题” 我的模型如下所示: <?php namespace App; use Illuminate\Database\Eloquent\Model; class Tag extends Model { protected $table = 'tags'; public $timestamps = false; public function tags() { return

我试图在我的标签模型上建立一个双向的多人关系,但我遇到了这个“问题”

我的模型如下所示:


<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    protected $table = 'tags';
    public $timestamps = false;

    public function tags()
    {
        return $this->belongsToMany(Tag::class, 'tag_tag', 'tag_one_id', 'tag_two_id');
    }

}

+----+------------+------------+
| id | tag_one_id | tag_two_id |
+----+------------+------------+
| 1  | 1          | 2          |
+----+------------+------------+
public function tags($tag1 = 'tag_one_id', $tag2 = 'tag_two_id')
{
    return $this->belongsToMany(Tag::class, 'tag_tag', $tag1, $tag2);
}
当我尝试此代码时:

$tag = Tag::find(1);
$tag->tags()->get();
$tag = Tag::find(2);
$tag->tags()->get();
我得到了Tag2实例,它是正确的

但当我尝试运行此代码时:

$tag = Tag::find(1);
$tag->tags()->get();
$tag = Tag::find(2);
$tag->tags()->get();
我想接收Tag1实例,但我没有


使用Laravel default Eloquent在模型上只使用一种方法就可以完成吗?

这是可能的。您必须将一个参数传递给
tags()
方法,并使用该参数修改关系上的主键/外键字段。不过,这可能是一个必须要处理的全部痛苦,而且几乎可以肯定的是,仅仅采用第二种关系方法不会那么令人头痛。结果会是这样的:


<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    protected $table = 'tags';
    public $timestamps = false;

    public function tags()
    {
        return $this->belongsToMany(Tag::class, 'tag_tag', 'tag_one_id', 'tag_two_id');
    }

}

+----+------------+------------+
| id | tag_one_id | tag_two_id |
+----+------------+------------+
| 1  | 1          | 2          |
+----+------------+------------+
public function tags($tag1 = 'tag_one_id', $tag2 = 'tag_two_id')
{
    return $this->belongsToMany(Tag::class, 'tag_tag', $tag1, $tag2);
}
然后,当您需要
Tag::find(2)->tags('Tag\u two\u id','Tag\u one\u id')时,只需修改这些值即可。

可以按如下所述加载:


您的用例可能比您的帖子所建议的要复杂得多,这可能会使它更合理。事实上,我会考虑一些其他的选择。 为什么它不起作用?

它不起作用,因为在您在
标记中添加的关系中,模型被定义为单向工作。但情况并非相反

如果我们可以定义两个名为
tags()
的方法,它将起作用,如下所示:

public function tags()
{
  return $this->belongsToMany(Tag::class, 'tag_tag', 'tag_one_id', 'tag_two_id');
}

//and

public function tags()
{
  return $this->belongsToMany(Tag::class, 'tag_tag', 'tag_two_id', 'tag_one_id');
}
不幸的是,这是不可能的

那么,可能的解决方案是什么

一个可能的解决办法是,不要触碰这种关系。相反,如果您能够设法为这些关系插入两个关系,那么它将起作用。 例如:

+----+------------+------------+
| id | tag_one_id | tag_two_id |
+----+------------+------------+
| 1  | 1          | 2          |
+----+------------+------------+
| 1  | 2          | 1          |
+----+------------+------------+

这就是我现在想到的解决办法。也许还有更好的解决办法

我找到了一个解决方案,我就是这样解决的

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    /**
     * @inheritdoc
     *
     * @var string
     */
    protected $table = 'tags';

    /**
     * @inheritdoc
     *
     * @var bool
     */
    public $timestamps = false;

    /*
    |--------------------------------------------------------------------------
    | RELATIONS
    |--------------------------------------------------------------------------
    */

    /**
     * Every tag can contain many related tags (TagOne has many TagTwo).
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    protected function tagsOneTwo()
    {
        return $this->belongsToMany(Tag::class, 'tag_tag', 'tag_one_id', 'tag_two_id');
    }

    /**
     * Every tag can contain many related tags (TagTwo has many TagOne).
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    protected function tagsTwoOne()
    {
        return $this->belongsToMany(Tag::class, 'tag_tag', 'tag_two_id', 'tag_one_id');
    }

    /**
     * This method returns a collection with all the tags related with this tag.
     * It is not a real relation, but emulates it.
     *
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function tags()
    {
        return $this->tagsOneTwo()->get()->merge($this->tagsTwoOne()->get())->unique('id');
    }

    /*
    |--------------------------------------------------------------------------
    | FUNCTIONS
    |--------------------------------------------------------------------------
    */

    /**
     * Function to relate two tags together.
     *
     * @param Tag $tag
     * @return void;
     */
    public function attach(Tag $tag)
    {
        if ($this->tags()->contains('id', $tag->getKey())) {
            return;
        }

        $this->tagsOneTwo()->attach($tag->getKey());
    }

    /**
     * Function to un-relate two tags.
     *
     * @param Tag $tag
     * @return void;
     */
    public function detach(Tag $tag)
    {
        if ($this->tags()->contains('id', $tag->getKey())) {
            // Detach the relationship in both ways.
            $this->tagsOneTwo()->detach($tag->getKey());
            $this->tagsTwoOne()->detach($tag->getKey());
        }
    }

    /*
    |--------------------------------------------------------------------------
    | ACCESORS
    |--------------------------------------------------------------------------
    */

    /**
     * Let access the related tags like if it was preloaded ($tag->tags).
     *
     * @return mixed
     */
    public function getTagsAttribute()
    {
        if (! array_key_exists('tags', $this->relations)) {
            $this->setRelation('tags', $this->tags());
        };

        return $this->getRelation('tags');
    }
}

实际上,我已经考虑过了,但问题是我必须合并这两个关系(tag\u one\u id->tag\u two\u id和tag\u two\u id->tag\u one\u id)。我不确定你的意思。我希望这样,但在某种程度上,我仍然可以从该方法返回一个关系。啊,所以您不希望查询生成器执行SQL。就像那个例子中的访问器一样,但它返回一个关系?是的,确切地说,这是可能的吗?