add new element in laravel collection object - php

I want to add new element in $items array, I don't want to use joins for certain reasons.
$items = DB::select(DB::raw('SELECT * FROM items WHERE items.id = '.$id.' ;'));
foreach($items as $item){
$product = DB::select(DB::raw(' select * from product
where product_id = '. $id.';' ));
$item->push($product);
}
What should I do?

It looks like you have everything correct according to Laravel docs, but you have a typo
$item->push($product);
Should be
$items->push($product);
push method appends an item to the end of the collection:
I also want to think the actual method you're looking for is put
$items->put('products', $product);
put method sets the given key and value in the collection

As mentioned above if you wish to add as a new element your queried collection you can use:
$items = DB::select(DB::raw('SELECT * FROM items WHERE items.id = '.$id.' ;'));
foreach($items as $item){
$product = DB::select(DB::raw(' select * from product
where product_id = '. $id.';' ));
$items->push($product);
// or
// $items->put('products', $product);
}
but if you wish to add new element to each queried element you need to do like:
$items = DB::select(DB::raw('SELECT * FROM items WHERE items.id = '.$id.' ;'));
foreach($items as $item){
$product = DB::select(DB::raw(' select * from product
where product_id = '. $id.';' ));
$item->add_whatever_element_you_want = $product;
}
add_whatever_element_you_want can be whatever you wish that your element is named (like product for example).

If you want to add item to the beginning of the collection you can use prepend:
$item->prepend($product, 'key');

If you want to add a product into the array you can use:
$item['product'] = $product;

I have solved this if you are using array called for 2 tables. Example you have,
$tableA['yellow'] and $tableA['blue'] . You are getting these 2 values and you want to add another element inside them to separate them by their type.
foreach ($tableA['yellow'] as $value) {
$value->type = 'YELLOW'; //you are adding new element named 'type'
}
foreach ($tableA['blue'] as $value) {
$value->type = 'BLUE'; //you are adding new element named 'type'
}
So, both of the tables value will have new element called type.

This is what i would do...
$items = Item::find($id);
foreach($items as $item){
$product = Product::find($id);
$item->product = $product;
}
This would assign $product to each $item

Related

Laravel 5.2 Eloquent foreach loop

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.

Showing Category and sub category when admin browse orders

When customer submit his order it is stored in database table orders in array. The array looks like:
{
"15": // product_id
{
"title":"Test of title", // product_title
"description":"Test of description", // product_description
"quantity":1,
"price":132
},
"shipping": // selected shipping information
{
"title":"Normal Delivery" - $10.00",
"price":10
}
}
Then in my Order Model I have this
public function getOrderData($data) {
return json_decode($data);
}
In the controller
public function orders() {
$orders = Order::select('*')->paginate(10);
return View::make('admin.orders', [
'orders' => $orders
]);
}
On the view I've made one foreach and displaying information for the order from this array like
#foreach($order->getOrderData($order->data) as $itemId => $item)
Title of product
Description of product
Price of product
#endforeach
What I want to make is same view but in front of the Title of product to show also Category name and sub-category name, like
#foreach($order->getOrderData($order->data) as $itemId => $item)
Category 1 -> Sub_category 1 -> Title of product
.... // other info
#endforeach
Problem: I don't have anything for category and sub-category in that array and in orders table at all. Tried to join tables Category and Sub-Category but they doesn't have columns in order table only in product table I store category_id and sub_category_id.
How can I show them?
Update 2: Changed getOrderData in Order Model like this
public function getOrderData($data) {
$dataArray = json_decode($data, true);
$data = json_decode($data);
$arrayKeys = array_keys($dataArray);
$arrayKeys = array_filter($arrayKeys, function($value) {
return ($value !== 'shipping');
});
$productIds = implode(',', $arrayKeys);
$products =
DB::table('products')
->join('category', 'products.product_id', '=', 'category.category_id')
->join('sub_category', 'products.sub_cat_id', '=', 'sub_category.sub_cat_id')
->whereIn('product_id',$productIds) ;
foreach ($products as $item) {
if(!in_array($item['product_id'], $arrayKeys)) continue;
$dataArray[$item['product_id']]['category'] = $item['category']; // depending on the implementation $item may be array or an object! so this code may vary
$dataArray[$item['product_id']]['subcategory'] = $item['subcategory'];
}
return (object) $dataArray;
//return json_decode(json_encode($dataArray));
}
Got error:
array_keys() expects parameter 1 to be array, object given
Update: This query in phpmyadmin is returning me all the information for product with id=9 + all information for category and sub-category
SELECT *
FROM products AS p
LEFT JOIN category AS c ON p.category_id =1
LEFT JOIN sub_category AS sc ON p.sub_cat_id =1
WHERE p.product_id =9
I can give you this solution:
After getting the result for the order from the table you can iterate over the order to get productIDs. Then do select query like this one:
SELECT fields FROM products AS p
JOIN categories AS c ON ...
JOIN sub_categories AS sc ON ...
WHERE p.id IN (productIDs)
And the code to get product ids is something like this:
public function getOrderData($data) {
$dataArray = json_decode($data, true);
$data = json_decode($data);
$arrayKeys = array_keys($dataArray);
$arrayKeys = array_filter($arrayKeys, function($value) {
return ($value !== 'shipping');
});
$productIds = implode(',', $arrayKeys);
// QUERY FOR selecting product categories, so when this query return results you can merge them with order data.
$productsInfo = ....
foreach ($productsInfo as $item) {
if(!in_array($item['productId'], $arrayKeys)) continue;
$dataArray[$item['product_id']]['category'] = $item['category_name']; // depending on the implementation $item may be array or an object! so this code may vary
$dataArray[$item['product_id']]['subcategory'] = $item['sub_cat_name '];
}
// If products is array of objects use this code
//foreach ($productsInfo as $item) {
// if(!in_array($item->productId, $arrayKeys)) continue;
// $dataArray[$item->product_id]['category'] = $item->category_name; // depending on the implementation $item may be array or an object! so this code may vary
// $dataArray[$item->product_id]['subcategory'] = $item->sub_cat_name ;
//}
return (object) $dataArray;
}
If return (object) $dataArray; doesn't give you the same response structure as in the response in your question then:
return json_decode(json_encode($dataArray)); // for example
If you add additional info about table structure I can give you better answer.
Try this ;)
When you do json_decode it converts associative array to objects that's why you are getting this error when passing this decoded json data; So before using this decoded data cast it to array;
$data = (array) json_decode($data);

Append an array element to begining of a sorted Eloquent ::list array

I have a list of items in database table of a structure:
id, name.
I need to populate a select box with items sorted by their names along with "All" element with an id = 0 as the first one. What is wrong is that the element doesn't appear in a list box at all.
Controller method:
public function getItems(){
$items = Item::orderBy('name', 'ASC')->lists('name', 'id');
$items_all = array(0 => 'All');
array_merge($items_all, $items);
return View::make('items')->with('items', $items);
}
and a view:
{{ Form::select('item_id', $items, Input::Get('item_id'), array('class'=>'form-control')) }}
array_merge returns the new array, so you have to assign the return value to $items:
$items = array_merge($items_all, $items);
Or you can bring it down to this syntax if you want to:
$items = array_merge(['0' => 'All'], $items);
To preseve the order of your array items you can use this:
$items = $items_all + $items;
After updating
array_merge($items_all, $items)
to
$items = array_merge($items_all, $items)
all select box elements got displayed, including 'All', but array_merge renumbers elements, so I used:
$items = $items_all + $items;
as #lukasgeiter suggested at the same time, so I chose his answer as final.

create a new object inside of a loop in php

I have an array of Product IDs and want to get the product information by calling the Product class. I have tried adding it in a foreach loop and get a fatal error saying Object of class Product could not be converted to string. This is what I have tried.
$productIDs = Db::getInstance()->executeS("SELECT id_product FROM wtop_product ORDER BY position ASC");
$products = '';
foreach($productIDs as $productID)
{
$products .= new Product($productID['id_product'], false, '1');
}
Since this ouputs an error obviously it is not the correct way to handle this situation. What i'm not sure of is how to pass the array of product IDs to the new Product call and get an output of each of those products.
Store objects in array:
$products = array();
foreach($productIDs as $productID) {
$products[$productID['id_product']] = new Product($productID['id_product'], false, '1');
}
print_r($products);

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