Making CRUD on Backpack for Laravel, and got issue.
I have Domain and domainPrices table
Domain model:
public function domainPrice()
{
return $this->hasOne(DomainPrices::class, 'domain_id', 'id');
}
DomainPrices model:
public function domain()
{
return $this->belongsTo(Domain::class, 'id', 'domain_id');
}
Migration:
Schema::table('domain_prices', function(Blueprint $table) {
$table->foreign('domain_id')->references('id')->on('domains')
->onDelete('cascade')
->onUpdate('cascade');
});
For setupCreateOperation()
$this->crud->addField([
'name' => 'bin_price',
'type' => 'number',
'entity' => 'domainPrice',
'attribute' => 'bin_price',
'model' => 'DomainPrices',
'pivot' => false,
]);
setupUpdateOperation:
$this->setupCreateOperation();
And I'm able to store data with this, but when I use update route, there is empty field.
But it is display the value, on list view with:
CRUD::column('domainPrice')->attribute('bin_price');
PHP VERSION: PHP 8.0.5
LARAVEL VERSION: v8.44.0
BACKPACK VERSION: 4.1.46
Solution was more easy than I though
Instead of:
$this->crud->addField([
'name' => 'bin_price',
'type' => 'number',
'entity' => 'domainPrice',
'attribute' => 'bin_price',
'model' => 'DomainPrices',
'pivot' => false,
]);
I use:
$this->crud->field('domainPrice.bin_price');
Related
SearchLogic for select_multiple isn't working, I can't change the type of the column so, I have to make it searchable. any workaround?
thanks in advance
I tried to make it to different type as well but getting datatables popup error there.
$this->crud->setColumns([
[
'name' => 'item',
'label' => trans('admin.item_number'),
'type' => "select_multiple",
'entity' => 'item',
'attribute' => "item_number",
'model' => "App\Item",
'searchLogic' => function ($query, $column, $searchTerm)
{
$query->orWhereHas('item', function ($q) use ($column, $searchTerm,$value) {
$q->join('download_item','download_item.download_id', '=' , 'downloads.id')
->join('items','download_item.item_id', '=' , 'items.id')
->where('items.item_number', 'like', '%'.$searchTerm.'%');
});
}
],
]);
I have three tables and the relations are like
downloads table have items from items table but the relationship store in different table named as download_item which contains download_id and item_id.
Why not use a filter? That's much more useful for the user, IMHO.
Here's an example:
$this->crud->addFilter([
'name' => 'provider_state',
'type' => 'select2_multiple',
'label' => 'State',
], function () {
return [
'draft' => 'Draft',
'paid' => 'Paid',
'open' => 'Open',
'late' => 'Late',
'uncollectible' => 'Uncollectible',
'reminded' => 'Reminded',
'pending_payment' => 'Pending Payment',
];
}, function ($values) {
$this->crud->addClause('whereIn', 'provider_state', json_decode($values));
});
I have two model Users and Roles connected by a pivot table. I want to display a field from the role model in CrudUserController. For example
User model:
public function roles()
{
return $this->belongsToMany( Role::class, 'role_user', 'user_id', 'role_id');
}
Role model
public function user()
{
return $this->belongsToMany( User::class, 'role_user','role_id','user_id');
}
UserCrudController
$this->crud->addFields([
[
'type' => 'repeatable',
'label' => 'Role',
'name' => 'roles', <- this field shows select2 with a list of roles
'subfields' => [
[
'name' => 'description', <- this field is from the role model, it should change when changing the role in select2
'label' => 'Description',
'type' => 'text',
]
]
]
])
I'm not sure if this is possible because usually such manipulations are implemented using js
If you want to create inline entries I would suggest to use the InlineCreateOperation, it can work in a BelongsToMany field too: https://backpackforlaravel.com/docs/5.x/crud-operation-inline-create
Cheers
I'm using Laravel 7 + Backpack CRUD 4.1.
I have two models Payment and PaymentMethods and field in PaymentCrudController
$this->crud->addField([
'label' => 'Payment Method',
'type' => 'select2',
'name' => 'payment_method_id',
'entity' => 'paymentMethod',
'attribute' => 'name',
'model' => 'App\Models\PaymentMethod',
'wrapperAttributes' => [
'class' => 'form-group col-md-3',
],
]);
Relation in Payment model:
public function paymentMethod()
{
return $this->hasOne(PaymentMethod::class, 'id', 'payment_method_id');
}
Actually, this works as expected - I see all records from the PaymentMethod model in the options field. But I need to filter some values. I trying to modify model relation:
public function paymentMethod()
{
return $this->hasOne(PaymentMethod::class, 'id', 'payment_method_id')->where('name', '!=', 'Online');
}
But I still see all records in select options. How can I filter select values?
putting 'where' in relation make no sense, in my opinion, relation should be as it is, reflect tables 's relations ....
for your suituation you could use 'options' for 'select2' field:
$this->crud->addField([
'label' => 'Payment Method',
'type' => 'select2',
'name' => 'payment_method_id',
'entity' => 'paymentMethod',
'attribute' => 'name',
'model' => 'App\Models\PaymentMethod',
'options' => (function ($query) {
return $query->where('name', '!=', 'Online')->get();}),
'wrapperAttributes' => [
'class' => 'form-group col-md-3',
],
]);
something else ... for your one to many relation: it should be:
public function paymentMethod()
{
return $this->hasOne(PaymentMethod::class,'payment_method_id');
}
second parameter should be the foreign key ...
I'm wanting to be able to handle polymorphic relations with Backpack CRUD. I can't find any good explanations and I'm struggling to unpick its implementation in their other packages (e.g. PermissionManager). What I'm wanting to do is to be able to change the specialties Users & Clinicians are linked to - similar to how roles & permissions change in the Permission Manager.
I have a polymorphic n-n relationship with Users & Clinicians to Specialties. Each model CRUDTrait.
Specialty Model
public function user()
{
return $this->morphedByMany(User::class, 'model', 'model_has_specialties');
}
public function clinician()
{
return $this->morphedByMany(Clinician::class, 'model', 'model_has_specialties');
}
User Model
public function specialties()
{
return $this->morphToMany(Specialty::class, 'model', 'model_has_specialties');
}
Clinician Model
public function specialties()
{
return $this->morphMany(Specialty::class, 'model', 'model_has_specialties');
}
The pivot table is 'model_has_specialties' and contains:
$table->increments('id');
$table->timestamps();
$table->integer('model_id');
$table->string('model_type');
$table->integer('specialty_id');
$table->unique(['model_id', 'model_type', 'specialty_id']);
I have tried a number of different addField() configurations however I'm really struggling.
Example of addField() tried:
$this->crud->addField([
'label' => 'specialties',
'type' => 'select',
'morph' => true,
'name' => 'model_id',
'entity' => 'ModelHasSpecialties',
'attribute' => 'model_id',
'model' => 'App\Models\Clinician',
'pivot' => true,
]);
** Edit **
Here's the ClinicianCrudController which is the link between the clinician class & bootstrap.
class ClinicianCrudController extends CrudController
{
public function setup()
{
/*
|--------------------------------------------------------------------------
| CrudPanel Basic Information
|--------------------------------------------------------------------------
*/
$this->crud->setModel('App\Models\Clinician');
$this->crud->setRoute(config('backpack.base.route_prefix') . '/clinician');
$this->crud->setEntityNameStrings('clinician', 'clinicians');
$this->crud->setColumns(['surname', 'forename', 'title', 'specialties']);
$this->crud->addField([
'name' => 'surname',
'type' => 'text',
'label' => 'Surname'
]);
$this->crud->addField([
'name' => 'forename',
'type' => 'text',
'label' => 'Forename'
]);
$this->crud->addField([
'name' => 'title',
'type' => 'select_from_array',
'options' => [
'Dr' => 'Dr',
'Miss' => 'Miss',
'Mr' => 'Mr',
'Mrs' => 'Mrs',
'0Ms' => 'Ms',
'Prof' => 'Prof',
],
'label' => 'Title',
'allows_null' => false,
]);
$this->crud->addField([
'label' => 'specialties',
'type' => 'select',
'morph' => true,
'name' => 'model_id',
'entity' => 'ModelHasSpecialties',
'attribute' => 'model_id',
'model' => 'App\Models\Clinician',
'pivot' => true,
]);
/*
|--------------------------------------------------------------------------
| CrudPanel Configuration
|--------------------------------------------------------------------------
*/
// TODO: remove setFromDb() and manually define Fields and Columns
$this->crud->setFromDb();
// add asterisk for fields that are required in ClinicianRequest
$this->crud->setRequiredFields(StoreRequest::class, 'create');
$this->crud->setRequiredFields(UpdateRequest::class, 'edit');
}
Below is my model factory.
$factory->define(App\Business::class, function (Faker\Generator $faker){
return [
'name' => $faker->bs,
'slug' => $faker->slug,
'address' => $faker->streetAddress,
'phone_no' => $faker->phoneNumber,
'mobile_no' => $faker->phoneNumber,
'email' => $faker->companyEmail,
'website' => $faker->domainName,
'latitude' => $faker->latitude,
'longitude' => $faker->longitude,
'location' => $faker->city,
'business_days_from' => $faker->dayOfWeek,
'business_days_to' => $faker->dayOfWeek,
'description' => $faker->text,
'user_id' => $faker->factory(App\User::class),
];
});
and This my database seeder class
class DatabaseSeeder extends Seeder
{
public function run()
{
factory(App\Business::class, 300)->create();
}
}
But when I execute php artisan db:seed ...it does not work..
What should be the workaround here..any help would be appreciated..
you can get all ids using pluck (lists is depricated for laravel >= 5.2)
$userIds = User::all()->pluck('id')->toArray();
and get a random id for FK column:
'user_id' => $faker->randomElement($userIds)
You may also attach relationships to models using Closure attributes in your factory definitions.
'title' => $faker->title,
'content' => $faker->paragraph,
'user_id' => function () {
return factory(App\User::class)->create()->id;
}
I just found the workaround .. I replaced
'user_id' => $faker->factory(App\User::class),
with
'user_id' => $faker->randomElement(User::lists('id')->toArray()),
and that solves the problem for now..