Laravel 5.2 Eloquent foreach loop - php

I'm in a controller for Laravel 5.2 and am trying to iterate through an eloquent collection of invoice_items, which would translate to something like order items. So, the invoice would act as the order, have it's ordered items (invoice_item), and the invoice_items would list all of the products ordered (product).
Here's what I have:
$id = $value; //from param
$invoice = Invoice::where('id', $id)->get();
$invoice_items = Invoice_item::all()->where('invoice_id', $invoice[0]->id);
$contact = Contact::where('id', $invoice[0]->contact_id)->get();
foreach($invoice_items as $item) {
$products = Product::all()->where('id', $item->product_id);
}
I'm attempting to pull all of the products from that specific invoice (via invoice items), which in this specific case should be two, different products.
What's happening, is when I iterate through using that loop, it's adding the same product twice, whereas it should be adding each product once. Is my logic just wrong here? Or do I need to look at my relationships again or something?

Change your queries to:
$invoice = Invoice::where('id', $id)->get();
$invoice_items = Invoice_item::where('invoice_id', $invoice[0]->id)->get();
$contact = Contact::where('id', $invoice[0]->contact_id)->get();
foreach($invoice_items as $item) {
$products = Product::where('id', $item->product_id)->get();
}
An easier way may be to add a items relation to the InvoiceItems model. E.g.:
public function items()
{
$this->hasOne('Items');
}
Then you can get all the Items from Invoice_item using:
return $invoice_items->items;
You can also try:
$invoice = Invoice::where('id', $id)->get();
$invoice_items = Invoice_item::where('invoice_id', $invoice[0]->id)->get()->lists('product_id');
$contact = Contact::where('id', $invoice[0]->contact_id)->get();
$products = Product::whereIn('id', $invoice_items)->get();
Hopefully, $products will then contain a collection of products for that invoice. No need for a foreach loop.

Related

Fetch all the brands from the product array on the sub category page

An array of Products is fetched on the subcategory page but, how to get a distinct brand from such array?
$product_sub_categories = ProductsSubCategory::where('product_sub_category_slug', $slug)->first();
$products = Products::all()->where('subcategory_id', $product_sub_categories->id);
$brands = Brand::all()->where('id', $products->brand_id)->distinct(); //help here
Use where() before the get() will improve the performance.
And you can use pluck('brand_id') on $products collection to get the brand_ids:
$product_sub_categories = ProductsSubCategory::where('product_sub_category_slug', $slug)->first();
$products = Products::where('subcategory_id', $product_sub_categories->id)->get();
$brands = Brand::whereIn('id', $products->pluck('brand_id')->all())->get();

Laravel | retrieving collection with relationship and except specific Ids

i'm working for a car rental booking system
so my plan is when a customer search if there is a available car in chosen Car Model,
first : get the cars id's already taken for the date chosen by customer
second : get all the cars except the not availavle cars,
$collection = Booking::whereDate('dropoffday', '>' ,$date1)
->whereDate('pickupday' ,'<', $date2)
->get(['car_id'])
;
if ($collection->isEmpty()) {
$cars = Car::with('marques.images')->get();
return Response::json($cars);
}
$taken = [];
foreach ($collection as $car) {
$id = $car->car_id;
array_push($taken,$id);
}
$cars = Car::with('marque.images')->except($taken);
return Response::json($cars);
}
how must i rewrite this line
$cars = Car::with('marque.images')->except($available);
to get all cars with relationship except not available cars
If your relations are set up correctly you can probably use the whereDoesntHave method like this:
$cars = Car::with('marque.images')->whereDoesntHave('bookings', function ($query) use ($date1, $date2) {
$query->whereDate('dropoffday', '>' ,$date1)
->whereDate('pickupday' ,'<', $date2);
})->get();
return Response::json($cars);

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

Exclude or remove sub list from original list in Laravel

I have a many-to-many relation between Order and Item table.
This relationship is defined in Order model:
public function items()
{
return $this->belongsToMany('Item', 'order_item', 'order_id', 'item_id' );
}
If customer is adding an item to the order, he choose one item from a list
$items = Item::all();
and this chosen item is add in intermediate (pivot) table (order_id, item_id).
The problem is that, I need my items list to contains only these items which have NOT been chosen for this order before. i.e. pivot table does NOT contains these items combined to this specific order.
Pseudo code:
$all_Items = Item::all();
$previously_Selected_Items = select_From_Pivot_Table::where('order_id', '=', $id);
$required_Items_List = $all_items->exclude($previously_Selected_Items);
I'm using Laravel 4.2.
Any suggestions??
Thanks in advance.
You can use whereDoesntHave and filter the items using the relationship:
$items = Item::whereDoesntHave('orders', function($q) use ($id){
$q->where('order_id', $id);
})->get();
After some time of searching and trying some suggested ideas, I came up with easy, but not professional, solution:
$order = Order::where('id', '=', $id)->with('items')->first();
$allitems= Item::all();
then array_diff, a php function, did the trick:
$items = array_diff($allitems->lists('name','id'), $order->items->lists('name','id'));
but the $items is just a list of id and name, not the whole objects, which I need. So I need a better solution.

Module that edits existing product names in magento?

Please I am trying to create a module in magento that edits the products' name by concatenating the existing product names with randomly generated numbers.
$model = Mage::getModel('catalog/product') ->load(1111) //getting
product model
$collection = $model->getCollection(); //products collection
foreach ($collection as $product) //loop for getting products
{
$model->load($product->getId());
$pname = $product->getName(); 
$this->model = Mage::getModel('catalog/product');
$new_name = $pname.' '.rand(1000,5000);
$this->model->setName($new_name);
}
This is my code, I am trying to create a module to achieve this functionality without editing the core files or using the admin panel.
Sorry but your code is ugly.
If you want to use collection (that is a good way to access data from a list of object) you must not use a ->load() (very expensive and should be used only when accessing data for a single object, like a product page)
Try this code instead :
$collection = Mage::getModel('catalog/product')->getCollection(); //products collection
$collection->addAttributeToSelect('name'); //retrieve only product name (optimising SQL)
foreach ($collection as $product) //loop for getting products
{
$pname = $product->getName();
$new_name = $pname.' '.rand(1000,5000);
$product->setName($new_name);
$product->save(); // you missed that
}
If you have a high number or product, you could also make a single SQL query with the SQL CONCAT() function ...
class Digital_GoogleMpn_Model_Observer {
public function googleMpn(Varien_Event_Observer $observer)
{
$product = $observer->getEvent()->getProduct();
$pname = $product->getName();
$google_mpn = rand(1000,5000);
$new_name = "{$pname}.' '.{$google_mpn}";
$product->setName($new_name);
$product->save();
} }

Categories