Laravel - 背包选择依赖于另一个选择

Posted

技术标签:

【中文标题】Laravel - 背包选择依赖于另一个选择【英文标题】:Laravel - Backpack select dependent from another select 【发布时间】:2020-10-09 14:54:43 【问题描述】:

我最近在我的 Laravel 项目中安装了 Laravel Backpack admin。目前我正在努力。但我需要帮助。所以...

我想要什么:

我想要两个选择,第一个是Category,第二个是Article。所以Article select 必须依赖于Category select。还有ArticlebelongsToCategory

类别-文章

Category 1 = [ Article 1, Article 2, Article 3 ]
Category 2 = [ Article 4, Article 5 ]

这只是显示哪个文章属于类别。例如,当我在category 上单击Category 1 选择时,在article 上选择它应该只显示Article 1, Article 2 and Article 3

我做了什么

我遵循了 Backpack 文档中的说明,在此 link 上为 Add a select2 field that depends on another field。所以我首先做了什么:

我创建了两个表,Category 表和 Article 表。他们的模型:

class Category extends Model

    use CrudTrait;

    /*
    |--------------------------------------------------------------------------
    | GLOBAL VARIABLES
    |--------------------------------------------------------------------------
    */

    protected $table = 'categories';
    protected $primaryKey = 'id';
    // public $timestamps = false;
    // protected $guarded = ['id'];
    protected $fillable = ['title'];
    // protected $hidden = [];
    // protected $dates = [];

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

    public function articles()
        return $this->hasMany('App\Models\Article');
    

这是Category 模型,这是Article 模型:

class Article extends Model

    use CrudTrait;

    /*
    |--------------------------------------------------------------------------
    | GLOBAL VARIABLES
    |--------------------------------------------------------------------------
    */

    protected $table = 'articles';
    protected $primaryKey = 'id';
    // public $timestamps = false;
    // protected $guarded = ['id'];
    protected $fillable = ['title', 'category_id'];
    // protected $hidden = [];
    // protected $dates = [];

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

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

    public function category()
        return $this->belongsTo('App\Models\Category');
    

我在这两个模型之间建立了这样的关系。所以当我创建Article 时,它会显示我的标题,我必须从category select 中选择category_id

毕竟我做了Archive 表,这些是我的迁移:

Schema::create('archives', function (Blueprint $table) 
   $table->increments('id');
   $table->string('title');

   $table->bigInteger('category_id')->unsigned();
   $table->foreign('category_id')->references('id')->on('categories');

   $table->bigInteger('article_id')->unsigned();
   $table->foreign('article_id')->references('id')->on('articles');

   $table->timestamps();
);

还有我的Archive.php 模特:

class Archive extends Model

    use CrudTrait;

    /*
    |--------------------------------------------------------------------------
    | GLOBAL VARIABLES
    |--------------------------------------------------------------------------
    */

    protected $table = 'archives';
    protected $primaryKey = 'id';
    // public $timestamps = false;
    // protected $guarded = ['id'];
    protected $fillable = ['title', 'category', 'article'];
    // protected $hidden = [];
    // protected $dates = [];

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

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

    public function category()
        return $this->belongsTo('App\Models\Category');
    

    public function article()
        return $this->belongsTo('App\Models\Article');
    

然后我按照backpack docs 的指示进行操作。 这是我的ArchiveCrudController

public function setup()
    
        /*
        |--------------------------------------------------------------------------
        | CrudPanel Basic Information
        |--------------------------------------------------------------------------
        */
        $this->crud->setModel('App\Models\Archive');
        $this->crud->setRoute(config('backpack.base.route_prefix') . '/archive');
        $this->crud->setEntityNameStrings('archive', 'archives');

        $this->crud->setColumns(['title', 'category', 'article']);
        $this->crud->addField([
            'name' => 'title',
            'type' => 'text',
            'label' => "Archive title"
        ]);

        $this->crud->addField([    // SELECT2
            'label'         => 'Category',
            'type'          => 'select',
            'name'          => 'category_id',
            'entity'        => 'category',
            'attribute'     => 'title',
        ]);
        $this->crud->addField([ // select2_from_ajax: 1-n relationship
            'label'                => "Article", // Table column heading
            'type'                 => 'select2_from_ajax',
            'name'                 => 'article_id', // the column that contains the ID of that connected entity;
            'entity'               => 'article', // the method that defines the relationship in your Model
            'attribute'            => 'title', // foreign key attribute that is shown to user
            'data_source'          => url('api/article'), // url to controller search function (with /id should return model)
            'placeholder'          => 'Select an article', // placeholder for the select
            'minimum_input_length' => 0, // minimum characters to type before querying results
            'dependencies'         => ['category'], // when a dependency changes, this select2 is reset to null
            //'method'                    => ‘GET’, // optional - HTTP method to use for the AJAX call (GET, POST)
        ]);


        /*
        |--------------------------------------------------------------------------
        | CrudPanel Configuration
        |--------------------------------------------------------------------------
        */

        // TODO: remove setFromDb() and manually define Fields and Columns
        //$this->crud->setFromDb();

        // add asterisk for fields that are required in ArchiveRequest
        $this->crud->setRequiredFields(StoreRequest::class, 'create');
        $this->crud->setRequiredFields(UpdateRequest::class, 'edit');
    

来自backpack docs。然后我在App\Http\Controller 中创建了Api 文件夹,然后在其中创建了ArticleController,如下所示:

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Article;
use Illuminate\Http\Request;

class ArticleController extends Controller

    public function index(Request $request)
    
        $search_term = $request->input('q');
        $form = collect($request->input('form'))->pluck('value', 'name');

        $options = Article::query();

        // if no category has been selected, show no options
        if (! $form['category']) 
            return [];
        

        // if a category has been selected, only show articles in that category
        if ($form['category']) 
            $options = $options->where('category_id', $form['category']);
        

        if ($search_term) 
            $results = $options->where('title', 'LIKE', '%'.$search_term.'%')->paginate(10);
         else 
            $results = $options->paginate(10);
        

        return $options->paginate(10);
    

    public function show($id)
    
        return Article::find($id);
    

我只是从docs 复制粘贴代码,但当然我根据需要更改了模型。 最后是我的routes

Route::get('api/article', 'App\Http\Controllers\Api\ArticleController@index');
Route::get('api/article/id', 'App\Http\Controllers\Api\ArticleController@show');

我将这些路由复制粘贴到我的web.php 中的routes 文件夹和custom.php 中的routes/backpack 文件夹中。

但是当我在Archive create 中选择类别时,没有articles 显示。 有人可以帮我解决这个问题吗?

【问题讨论】:

【参考方案1】:

从背包 4.1 开始,您应该在依赖字段中包含 'include_all_form_fields' => true 属性。

【讨论】:

【参考方案2】:

您的代码中有一些问题,我希望这能解决它们:

1- 在 ArchiveCrudController 中:确保具有 category_id 的依赖项不是 category ...

'dependencies'         => ['category_id'], 

 $this->crud->addField([ // select2_from_ajax: 1-n relationship
            'label'                => "Article", 
            'type'                 => 'select2_from_ajax',
            'name'                 => 'article_id',
            'entity'               => 'article',
            'attribute'            => 'title', 
            'data_source'          => url('api/article'), 
            'placeholder'          => 'Select an article',
            'minimum_input_length' => 0, querying results
            'dependencies'         => ['category_id'], 
            //'method'                    => ‘GET’,
        ]);

2- 在存档模型 $fillable 中应该采用数据库列名而不是关系...

 protected $fillable = ['title', 'category_id', 'article_id'];

3- 当你得到 $form 请求参数时,它带有名称 category_id 就像你在 Crud 中命名它不是(类别)

public function index(Request $request)
    
        $search_term = $request->input('q');
        $form = collect($request->input('form'))->pluck('value', 'name');

        $options = Article::query();

        // if no category has been selected, show no options
        if (! $form['category_id']) 
            return [];
        

        // if a category has been selected, only show articles in that category
        if ($form['category_id']) 
            $options = $options->where('category_id', $form['category_id']);
        

        if ($search_term) 
            $results = $options->where('title', 'LIKE', '%'.$search_term.'%')->paginate(10);
         else 
            $results = $options->paginate(10);
        

        return $options->paginate(10);
    

【讨论】:

以上是关于Laravel - 背包选择依赖于另一个选择的主要内容,如果未能解决你的问题,请参考以下文章

组合框依赖于另一个组合框 - JavaFX

下拉列表依赖于另一个? ASP.NET MVC

从服务器中的两个 selectInputs 中,如何使一个依赖于另一个?

有依赖的背包问题(树状dp 深搜)

背包九讲

如何查看依赖于另一个值 vue 的值?