Laravel "Skip" WhereIn when request not Filled or null? - php

I have controller with request like below
$product = $request->product; //array
$product_category = $request->product;
if($request->filled('product')){
$product = product()::whereIn('product',$product)
->where('product_category',$product_category)
->get();
}else {
$product = product()::where('product_category',$product_category)
->get();
}
how do i skip or make the eloquent still worked if $product request was not filled or null?
Currently i used the if for that query is remove where on product, but that will make me create alot of eloquent with more request
But I think this is not the best or right think to do, what is my better option for doing that where without writing a lot of if-elseing?

Use when function provided by laravel:
Product::when($request->product, function($query, $product) {
$query->whereIn($product);
})->where("product_category", $product_category)->get();

Related

Running where() more more than one time

Question: How can I run the where query for all rows in $cart, instead for just $cart[0], or [1] or [2].
I am trying to manually code a Shopping Cart in Laravel. Since I am a novice, I am stuck at a point. Please take a look at the code below:
public function showCart()
{
$user = Auth::user();
$cart = Cart::where('user_id', $user->id)->get();
$product = Products::where('id', $cart[0]->product_id)->get();
return view('showCart')
->with('cart', $cart)
->with('user', $user)
->with('product', $product);
}
This is my function to show a user's cart. Here, I am trying to show all the products that a user has in his cart, and also send a variable with the product details.
However, while I am trying to send all the products in the user's cart as a $product array, I am only getting the first product. That is because the rows returned in $cart is more than one, but I am unable to write a query for getting all the products in this line:
$product = Products::where('id', $cart[0]->product_id)->get();
. . . because, quite clearly, I am writing a query to match only the first row returned in $cart.
Thanks in Advance.
You can use the whereIn and the data_get helper function:
$product = Products::whereIn('id', data_get($cart, '*.product_id'))->get();
data_get works with both arrays and objects. Alternatively, you can use Arr::get for arrays only.

BadMethodCallException Method Illuminate\Database\Eloquent\Collection::paginate does not exist

After adding Paginate function I'm getting this error
$sub_categories = SubCategory::where('id', $id)->first();
$products = Products::where('subcategory_id', $sub_categories->id)->get()->paginate(10);
$sub_categories = SubCategory::where('id', $id)->first(), this will only give you null or one record, not a collection, so you can not use ->paginate(10); chain it. You will only get one record at the most, why you need to paginate?
Update
so first for the sub_categories you do not need to paginate, as you just want one record. so the code should be like this.
$sub_categories = SubCategory::where('id', $id)->first();
second, if you want to paginate $products you should do this,
if ($sub_categories)
{
$products = Products::where('subcategory_id', $sub_categories->id)->paginate(10);
}

Duplicating data in Controller Laravel

I am trying to duplicate data with a click of a button, in better terms, trying to reorder a previous order. This is my code
$order = Order::find($id);
$order_details = OrderDetail::where('order_id', $id)->get();
$reorder = $order->replicate();
$reorder_details = $order_details->replicate();
$reorder->save();
$reorder_details->save();
The $order data replicates fine, however the $order_details data doesnt, as I get this error Method Illuminate\Database\Eloquent\Collection::replicate does not exist.
Is there a way to duplicate without using replicate()?
It's because $order = Order::find($id); returns the first instance (a model) and $order_details = OrderDetail::where('order_id', $id)->get(); returns a collection. Just have to change it to $order_details = OrderDetail::where('order_id', $id)->first(); and it will work fine.
To handle multiple order details:
$order_details = OrderDetail::where('order_id', $id)->get()->each(function($item) use($reorder){
$newItem = $item->replicate();
$newItem->order_id = $reorder->id; //If needed, be sure to pass $order if you do
$newItem->save();
});
You can use the __clone() method which you can implement inside the order class,
Then you can use it like this
$order = Order::find($id);
$newOrder = clone $order;
$newOrder->save();

Foreach with eloquent in laravel

I'm trying to loop through the items using eloquent in laravel but I'm getting 0. Please see my code below.
Model
Class Store{
public function products(){
return $this->hasMany('App\Product');
}
}
Controller
$products_count = 0;
foreach($store->products() as $product)
{
if($product->status == 1)
{
$products_count++;
}
}
dd($products_count);
Note: I have data in my database.
You can also use withCount method something like that
Controller
$stores = Store::withCount('products')->get();
or
$store = Store::where('id', 1)->withCount('products')->first();
WithCount on the particular status
$stores = Store::withCount(['products' => function ($query) {
$query->where('status', 1);
}
])
->get();
ref: withcount on relationship
That's because $store->products() returns an eloquent collection which doesn't contain the data from the database yet. You need to do $store->products instead.
If you need to get the count from the database then use
$store->products()->where('status', 1)->count()
With the function-annotation (i.e. products()) you are retrieving the \Illuminate\Database\Eloquent\Builder-instance, not the actual Eloquent-collection.
Instead, you would have to use $store->products – then you will get retrieve the related collection.
In Laravel $store->products() makes you access the QueryBuilder instance, instead there is the Laravel way of doing $store->products, which loads the QueryBuilder and retrieves the collection automatically and down the line is easy to optimise.

I have a problem with foreach understanding laravel 5.6

I have a persistent problem with all my project and I need help understanding how to make it work.
In my view =
URL = mysite.com/product/40 so here the product ID is 40
On the view I am doing a foreach loop to show all merchants that have this product. we have many merchants having many products so it is a many to many relationship.
Now on my controller
$product = Product::find($id); // to find the product
$users = $product->users; // here the user is the merchant that have the product
$store = Store::where('user_id', $user->id)->value('social');
Here i get the error :
Trying to get property of non-object
So I do want to access the store of each of the merchants in the controller how do I do this ? Because now $user is a collection.
Please first verify if the store is giving object or not by using var_dump. After that you can have a look into https://laravel.com/docs/5.6/queries for more details.
1) Firstly you can use Injection to avoid this line: $product = Product::find($id);
public function your_controller_methon(Product $product) {}
Laravel will automatically do the trick for you and $product will already contain Product object.
2) If you have relationship, you should do something similar to this:
$product->stores - to retrieve all stores which contains particular product in product_id column. And you could do: $product->stores()->pluck('social'); to retrieve list of socials from all merchants which have particular product.
About relationships you could read here: https://laravel.com/docs/5.7/eloquent-relationships
You can refactor your code to use the whereIn() query builder method since you have many users to a product. You will have something like:
$product = Product::find($id); // to find the product
$users = $product->users->pluck('id');
$stores = Store::whereIn('user_id', $users->all())->value('social');
This mean your $stores variable will contain those stores owned by the users.
PS: Be sure to check if $users is not empty or null so you don't encounter unexpected errors
According to you code, Here $user is a single value, not a collection.
Change:
$store = Store::where('user_id', $user->id)->value('social');
To
$store = Store::where('user_id', $user);
It will works.
To make the $user as a collection, execute such query so that it will return array such as:
$product = Product::find($id);
$user = Product::where('user', $product->user)->get();
This will return the collection of users of this product.
Then execute foreach loop:
foreach($user as $rowdata){
$store = Store::where('user_id', $rowdata->id)->get();
}
You should try this:
$product = Product::find($id);
$user = Product::where('user', $product->user)->get();
foreach($user as $rowdata){
$store = Store::where('user_id', $rowdata->id)->get();
}

Categories