Filter values in select fields - laravel

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 ...

Related

backpack laravel - searchLogic not working for select_multiple

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));
});

how to update key/value database with laravel?

I'm just learning laravel. I want update key / value in database with laravel api but not work.
My products model is one to many with ProductMeta and many to many with contents model.
My Models
class Product extends Model
{
use HasFactory;
protected $guarded = [];
public function productMeta()
{
return $this->hasMany(ProductMeta::class);
}
public function content()
{
return $this->belongsToMany(Content::class, 'product_contents')->withTimestamps();
}
}
class ProductMeta extends Model
{
use HasFactory;
protected $guarded = [];
public function products()
{
return $this->belongsTo(Product::class);
}
}
class Content extends Model
{
use HasFactory;
protected $guarded= [];
public function product()
{
return $this->belongsToMany(Product::class, 'product_contents');
}
Controller
public function update(Request $request, $id)
{
$product = Product::findOrFail($id);
DB::table('product_metas')
->upsert(
[
[
'product_id' => $product->id,
'key' => 'name',
'value' => $request->name,
],
[
'product_id' => $product->id,
'key' => 'price',
'value' => $request->name,
],
[
'product_id' => $product->id,
'key' => 'amount',
'value' => $request->name,
],
],
['product_id','key'],
['value']
);
return \response()->json([], 204);
}
Table Structure
API parameter
I tried with update and updateOrcreate and updateOrInsert and upsert methods.
just in upsert method writed database but inserted new data.not updated.
In your case, you should use updateOrCreate() instead of upsert.
Product::updateOrCreate([
'product_id' => $id,
'name' => $request->name,
'price' => $request->price,
'amount' => $request->amount
]);
or
Product::upsert([
[
'product_id' => $id,
'name' => $request->name,
'price' => $request->price,
'amount' => $request->amount
]
], ['product_id'], ['name', 'price', 'amount']);
In addition your problem is your table name is not matching with your structure table name. In your controller DB::table('product_metas') should be DB::table('products_meta').
my problem solved this way:
ProductMeta::query()->where('product_id', $id)->upsert([
['product_id' => $id, 'key' => 'name', 'value' => $request->name],
['product_id' => $id, 'key' => 'price', 'value' => $request->price],
['product_id' => $id, 'key' => 'amount', 'value' => $request->amount]],
['product_id'], ['value']);
$contentRecord = Product::find($id);
$contentRecord->content()->update(['path'=>$request->path]);
return response()->json([], 204);
I forget use query() method for ProductMeta and added $table->unique(['product_id', 'key']); to product meta migration.
**products relation one to many with product Meta
And Many to many with content.

How to disaplay relation data on update action backpack?

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');

Laravel Backpack Polymorphic CRUD field

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');
}

How can I maintain foreign keys when seeding database with Faker?

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..

Resources