With mapping in laravel 7 app collect data - laravel

In laravel 7 app I use mapping when I need to collect columns in array
$retArray['categoryLabels'] = Category
::get()
->map(function ($item) {
return ['code' => $item->id, 'label' => $item->title];
})
->all();
I wonder if there is some method(like pluck) for this purpose ?
Thanks!

Say the categories are like
code: web label: Web Development
code: php label: PHP Programming
code: javascript label: Javascript Frameworks
Use mapWithKeys
$retArray['categoryLabels'] = Category::get()
->mapWithKeys(function ($item) {
return ['code' => $item->id, 'label' => $item->title];
})
->all();
mapWithKeys will give output as
//Value of $retArray['categoryLabels']
//similar to using pluck()
[
'web' => 'Web Development',
'php' => 'PHP Programming',
'javascript' => 'Javascript Frameworks'
}
Another way
$retArray['categoryLabels'] = Category::select('code', 'label')
->get()
->toArray();
will give output as
//Value of $retArray['categoryLabels']
[
['code' => 'web', 'label' => 'Web Development'],
['code' => 'php', 'label' => 'PHP Programming'],
['code' => 'javascript', 'label' => 'Javascript Frameworks']
]

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

Pagination with many to many relationships

I have products, categories and category_product (pivot) tables in my database.
I want to return the category info and products with pagination in the same response.
I know I can use Product::with('categories')->pagination(20),
but I don't want to attach the category to each product.
What is the proper way to get products belong to a specific category?
I have tried that but I can't get the pagination with that:
$category = Category::where('slug', $slug)->first();
$products = $category->products()->paginate(20);
return response()->json([
'category' => new CategoryResource($category),
'products' => ProductResource::collection($products),
]);
Here is my ProductResource
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'code' => $this->code,
'image' => $this->image,
'quantity' => $this->quantity,
'price' => $this->price,
'slug' => $this->slug,
'sort_order' => $this->sort_order,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'categories' => CategoryResource::collection($this->whenLoaded('categories')),
];
This looks like an issue with the way data is returned from the Collection.
The easiest solution is:
return response()->json([
'category' => new CategoryResource($category),
'products' => ProductResource::collection($products)->response()->getData(true),
]);
You can try as below
$category = Category::where('slug', $slug)
->with('products', function($query) {
$query->paginate(20);
})
->first();
return response()->json([
'category' => new CategoryResource($category),
'products' => ProductResource::collection($category->products),
]);
Hope this is what you are looking for.

Filter values in select fields

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

mapWithKeys in laravel ,i dont understand how do it work?

I saw the example of laravel, but i dont understand how do it work.
for this example:
$collection = collect([
[
'name' => 'John',
'department' => 'Sales',
'email' => 'john#example.com'
],
[
'name' => 'Jane',
'department' => 'Marketing',
'email' => 'jane#example.com'
]
]);
$keyed = $collection->mapWithKeys(function ($item) {
return [$item['email'] => $item['name']];
});
$keyed->all();
someone can explain detail of it?
$collection = collect([
[
'name' => 'John',
'department' => 'Sales',
'email' => 'john#example.com'
],
[
'name' => 'Jane',
'department' => 'Marketing',
'email' => 'jane#example.com'
]
]);
$keyed = $collection->mapWithKeys(function ($item) {
//this line takes one array of collection object in item array and make a key of its email and store name on that email key
return [$item['email'] => $item['name']];
});
$keyed->all();

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