Laravel 同一模型上的多对多

Posted

技术标签:

【中文标题】Laravel 同一模型上的多对多【英文标题】:Laravel Many-to-many on the same model 【发布时间】:2021-10-31 03:40:18 【问题描述】:

它应该很简单,但是出了点问题,我想知道为什么。 我需要同一模型的多对多关系,理论上我知道如何做到这一点,但我收到了奇怪的结果。可能是由非整数索引列引起的。 Pn 型号:

class Pn extends Model

    protected $primaryKey = 'pn';
    protected $guarded = [];
    public function bom()
    
        return $this->belongsToMany(
            'App\Models\Pn',
            'boms',
            'parent_pn',
            'child_pn',
        );
    
    public function where_used()
    
        return $this->belongsToMany(
            'App\Models\Pn',
            'boms',
            'child_pn',
            'parent_pn',
        );
    

Pn 迁移:

class CreatePnsTable extends Migration

    public function up()
    
        Schema::create('pns', function (Blueprint $table) 
            $table->string('pn')->primary()->index();
            $table->string('pd');
            $table->string('ifs_pn');
            $table->string('ifs_pd');
            $table->timestamps();
        );
    

BOM(枢轴)迁移:

class CreateBomsTable extends Migration

    public function up()
    
        Schema::create('boms', function (Blueprint $table) 
            $table->id();
            $table->string('parent_pn');
            $table->foreign('parent_pn')->references('pn')->on('pns');
            $table->string('child_pn');
            $table->foreign('child_pn')->references('pn')->on('pns');
            $table->integer('sort');
            $table->string('dp')->default('0');
            $table->float('qty')->default(0);
            $table->string('note')->default('');
            $table->timestamps();
        );
    

PN 播种机:


    public function run()
    
        Pn::create([
            'pn' => 'A1',
            'pd' => "first_part",
            'ifs_pn' => 'IFS_A1',
            'ifs_pd' => "IFS_first_part",
        ]);
        Pn::create([
            'pn' => 'A2',
            'pd' => "second_part",
            'ifs_pn' => 'IFS_A2',
            'ifs_pd' => "IFS_second_part",
        ]);
        Pn::create([
            'pn' => 'A3',
            'pd' => "third_part",
            'ifs_pn' => 'IFS_A3',
            'ifs_pd' => "IFS_third_part",
        ]);
        Pn::create([
            'pn' => 'A4',
            'pd' => "fourth_part",
            'ifs_pn' => 'IFS_A4',
            'ifs_pd' => "IFS_fourth_part",
        ]);
        Pn::create([
            'pn' => 'A5',
            'pd' => "fifth_part",
            'ifs_pn' => 'IFS_A5',
            'ifs_pd' => "IFS_fifth_part",
        ]);
        Pn::create([
            'pn' => 'A6',
            'pd' => "sixth_part",
            'ifs_pn' => 'IFS_A6',
            'ifs_pd' => "IFS_sixth_part",
        ]);
        Pn::create([
            'pn' => 'A7',
            'pd' => "seventh_part",
            'ifs_pn' => 'IFS_A7',
            'ifs_pd' => "IFS_seventh_part",
        ]);
    

BOM 播种机:


    public function run()
    
        Bom::create([
            'parent_pn' => 'A3',
            'child_pn' => "A4",
            'sort' => 10,
            'dp' => "front",
            'qty' => 1,
            'note' => 'test',
        ]);
        Bom::create([
            'parent_pn' => 'A3',
            'child_pn' => "A5",
            'sort' => 20,
            'dp' => "back",
            'qty' => 4,
            'note' => '',
        ]);
        Bom::create([
            'parent_pn' => 'A1',
            'child_pn' => "A2",
            'sort' => 10,
            'dp' => "top",
            'qty' => 2,
            'note' => 'test2s',
        ]);
        Bom::create([
            'parent_pn' => 'A1',
            'child_pn' => "A3",
            'sort' => 20,
            'dp' => "bottom",
            'qty' => "2.5",
            'note' => '',
        ]);
        Bom::create([
            'parent_pn' => 'A1',
            'child_pn' => "A4",
            'sort' => 30,
            'dp' => "back",
            'qty' => 1,
            'note' => '',
        ]);
        Bom::create([
            'parent_pn' => 'A1',
            'child_pn' => "A4",
            'sort' => 40,
            'dp' => "front",
            'qty' => 5,
            'note' => '',
        ]);
        Bom::create([
            'parent_pn' => 'A1',
            'child_pn' => "A6",
            'sort' => 50,
            'dp' => "under",
            'qty' => 5,
            'note' => '',
        ]);
    

正在执行(对于 $id = 'A1'):


    public function show($id)
    
        $pn = PN::find($id);
        $bom = $pn->bom()->get();
        $where_used = $pn->where_used()->get();
        return [
            'pn' => $pn,
            'bom' => $bom,
            'where_used' => $where_used,
        ];
    

结果:

    "pn":
    
        "pn":0,
        "pd":"first_part",
        "ifs_pn":"IFS_A1",
        "ifs_pd":"IFS_first_part",
        "created_at":"2021-09-01T14:10:30.000000Z",
        "updated_at":"2021-09-01T14:10:30.000000Z"
    ,
    "bom":
    [
        
            "pn":0,
            "pd":"fourth_part",
            "ifs_pn":"IFS_A4",
            "ifs_pd":"IFS_fourth_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "parent_pn":"A3",
                "child_pn":"A4"
            
        ,
        
            "pn":0,
            "pd":"fifth_part",
            "ifs_pn":"IFS_A5",
            "ifs_pd":"IFS_fifth_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "parent_pn":"A3",
                "child_pn":"A5"
            
        ,
        
            "pn":0,
            "pd":"second_part",
            "ifs_pn":"IFS_A2",
            "ifs_pd":"IFS_second_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "parent_pn":"A1",
                "child_pn":"A2"
            
        ,
        
            "pn":0,
            "pd":"third_part",
            "ifs_pn":"IFS_A3",
            "ifs_pd":"IFS_third_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "parent_pn":"A1",
                "child_pn":"A3"
            
        ,
        
            "pn":0,
            "pd":"fourth_part",
            "ifs_pn":"IFS_A4",
            "ifs_pd":"IFS_fourth_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "parent_pn":"A1",
                "child_pn":"A4"
            
        ,
        
            "pn":0,
            "pd":"fourth_part",
            "ifs_pn":"IFS_A4",
            "ifs_pd":"IFS_fourth_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "parent_pn":"A1",
                "child_pn":"A4"
            
        ,
        
            "pn":0,
            "pd":"sixth_part",
            "ifs_pn":"IFS_A6",
            "ifs_pd":"IFS_sixth_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "parent_pn":"A1",
                "child_pn":"A6"
            
        
    ],
    "where_used":
    [
        
            "pn":0,
            "pd":"third_part",
            "ifs_pn":"IFS_A3",
            "ifs_pd":"IFS_third_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "child_pn":"A4",
                "parent_pn":"A3"
            
        ,
        
            "pn":0,
            "pd":"third_part",
            "ifs_pn":"IFS_A3",
            "ifs_pd":"IFS_third_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "child_pn":"A5",
                "parent_pn":"A3"
            
        ,
        
            "pn":0,
            "pd":"first_part",
            "ifs_pn":"IFS_A1",
            "ifs_pd":"IFS_first_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "child_pn":"A2",
                "parent_pn":"A1"
            
        ,
        
            "pn":0,
            "pd":"first_part",
            "ifs_pn":"IFS_A1",
            "ifs_pd":"IFS_first_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "child_pn":"A3",
                "parent_pn":"A1"
            
        ,
        
            "pn":0,
            "pd":"first_part",
            "ifs_pn":"IFS_A1",
            "ifs_pd":"IFS_first_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "child_pn":"A4",
                "parent_pn":"A1"
            
        ,
        
            "pn":0,
            "pd":"first_part",
            "ifs_pn":"IFS_A1",
            "ifs_pd":"IFS_first_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "child_pn":"A4",
                "parent_pn":"A1"
            
        ,
        
            "pn":0,
            "pd":"first_part",
            "ifs_pn":"IFS_A1",
            "ifs_pd":"IFS_first_part",
            "created_at":"2021-09-01T14:10:30.000000Z",
            "updated_at":"2021-09-01T14:10:30.000000Z",
            "pivot":
            
                "child_pn":"A6",
                "parent_pn":"A1"
            
        
    ]

它将所有来自 DB 的 PN 作为孩子和父母返回,为什么? PN = 0 而不是 A1、A2 等... 请帮忙

【问题讨论】:

【参考方案1】:

我找到了! 我已添加:

    protected $keyType = 'string';

到 PN 模型,它的工作原理!

【讨论】:

以上是关于Laravel 同一模型上的多对多的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 多列上的多对多同步()

同一模型上的 Laravel 多对多关系

Laravel 上的多对多问题关系

Laravel 雄辩的多对多模型

Laravel Eloquent 三个模型之间的多对多关系

如何通过 Laravel 中的多对多关系获取模型