问题
I recently installed Laravel Backpack
admin in my Laravel project. Currently right now I'm working on it. But I need help. So...
What I want:
I want to have two selects, first one is Category
and the second one is Article
. So Article
select must depend on Category
select. And Article
belongsTo
Category
.
Category-Article
Category 1 = [ Article 1, Article 2, Article 3 ]
Category 2 = [ Article 4, Article 5 ]
This is just a showing of which article belongs to category. So for example, when I click Category 1
on category
select, on article
select it should show me only Article 1, Article 2 and Article 3
.
What I did
I followed instructions on Backpack docs, for Add a select2 field that depends on another field
on this link. So what I did first:
I created two tables, Category
table and Article
table. Their models:
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');
}
}
This is a Category
model, and this is Article
model:
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');
}
}
I made relationships between these two models like this. So when I create Article
it shows me title and I have to choose category_id
from category select
.
After all this I made Archive
table and these are my migrations:
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();
});
And my Archive.php
model:
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');
}
}
And then I followed instructions from the backpack docs
.
This is my 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');
}
Like from backpack docs
. Then I made Api
folder in App\Http\Controller
and then I made ArticleController
in it, like this:
<?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);
}
}
I just copy-paste code from docs
but of course I changed model for my need.
And finally my routes
:
Route::get('api/article', 'App\Http\Controllers\Api\ArticleController@index');
Route::get('api/article/{id}', 'App\Http\Controllers\Api\ArticleController@show');
I copy-paste these routes in my web.php
in routes
folder and in custom.php
in routes/backpack
folder.
But when I choose category in my Archive create
no articles
showing.
Can someone please help me with this?
回答1:
you have some issue in your code i hope this would solve them:
1- in ArchiveCrudController: be sure that the dependencies with category_id not 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- in Archive Model $fillable should take db column names not relations ...
protected $fillable = ['title', 'category_id', 'article_id'];
3- also when you get $form request parameter, it comes with name category_id like you name it in Crud not (category)
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);
}
来源:https://stackoverflow.com/questions/62468799/laravel-backpack-select-dependent-from-another-select