Symfony2 creating objects with session keys and values - php

BACKGROUND
I have two tables in my database, CampaignList and CampaignProduct. The logic is simple, if the user successfuly purchases products I have to create one new CampaignList and CampaignProducts based for the number of products bought. These two tables will be mapped together in the future, right now I am just trying to insert them correctly.
So for example if a user successfuly buys 3 products one new table is inserted in CampaignList and 3 new tables is CampaignProduct.
Now the products are storred in session like this:
11 => 2
29 => 1
The key is the id of the product and the value is the quantity. So this session has 3 products, two products with the id of 11 and one products with the id of 29. Now for the problem and the code.
THE PROBLEM
The inserts are working correctly, except one. I need to save the quantity of the product too in the database. But this way that I am creating I dont think i can? Because I am creating tables in a different loop where the quantity is never iterated? Here is the code
THE CODE
if ($session->has('cart') && count($session->get('cart')) > 0) {
// if the session is good create the new campaign
$campaign = New CampaignList();
$campaign->setUserId($user->getId());
$campaign->setName('Karpedeal');
$campaign->setState(1);
$em->persist($campaign);
$em->flush();
foreach ($cart as $id => $quantity) {
// store the product ids in an array
$productIds[] = $id;
//get all the products based on the id array
$product = $em->getRepository('MpShopBundle:Product')->findById($productIds);
}
// for each new product create new CampaignProduct
foreach($product as $item){
$campaignProduct = New CampaignProduct();
$campaignProduct->setCampaignId($campaign->getId());
$campaignProduct->setProductId($item->getId());
$campaignProduct->setSellingPrice($item->getPrice());
$campaignProduct->setStock($item->getStockAvailable());
$campaignProduct->setReserved($quantity); // PROBLEM how to get the quantity from the session??
$em->persist($campaignProduct);
$em->flush();
}
THE OTHER WAY
The only way I think I can do is do everything in the first foreach loop, however that way I am getting an error when I try to get the ids of the products, because they are not objects, but arrays...
if ($session->has('cart') && count($session->get('cart')) > 0) {
// if the session is good create the new campaign
$campaign = New CampaignList();
$campaign->setUserId($user->getId());
$campaign->setName('Karpedeal');
$campaign->setState(1);
$em->persist($campaign);
$em->flush();
foreach ($cart as $id => $quantity) {
// store the product ids in an array
$productIds[] = $id;
//get all the products based on the id array
$product = $em->getRepository('MpShopBundle:Product')->findById($productIds);
$campaignProduct = New CampaignProduct();
$campaignProduct->setCampaignId($campaign->getId());
$campaignProduct->setProductId($product->getId()); // the error here because $product is an array not object
$campaignProduct->setSellingPrice($item->getPrice());
$campaignProduct->setStock($product->getStockAvailable());
$campaignProduct->setReserved($quantity); // PROBLEM how to get the quantity from the session??
$em->persist($campaignProduct);
$em->flush();
}
Any ideas?

By looking at your code I guess your second answer is best, but instead of getting all products with an array of product ids, just get one product every run which results in your product to be an instance of MpShopBundle:Product.
tl;dr
changing this
$product = $em->getRepository('MpShopBundle:Product')->findById($productIds);
into this
$product = $em->getRepository('MpShopBundle:Product')->find($id);
Should work

Related

laravel slow query issue optimization

I want to optimize my query as it is taking long to run with current eloquents. I have two table, toys and product.
From each product one is reserved as sample of toy if not than it has to be updated as sample by the query so what i'm doing right now is below.
$toywithsample=product::select('toyid')->groupBy('toyid')->where('sample','yes')->get();
Above code is to get id of all the product with which have their one sample from in its product
$toywithoutsamples=toy::select('id')->whereNotIn('id',$toywithsample)->get();
Above code is to get id of all product which have no sample toy in
foreach($toywithoutsamples as $toywithoutsample){
$product=product::where('toyid',$toywithoutsample->id)
->where('sample','sale')->limit(1)
->update(['sample'=>'yes']);
}
Below is table structure
toy table
id,name,
product
id, toyid,sample
$toys_ids_with_sample = Product::where('sample', 'yes')->get()->pluck('toyId');
// get the products grouped by toyId.
$products = Product::whereNotIn('toyId', $toys_ids_with_sample)->where('sample', 'sale')->get()->groupBy('toyId');
// get the product ids whose sample field you want to change to
// yes.
$update_product_ids = [];
foreach($products as $toyId => $products){
// We will only pick the first one, as we have to change just 1.
array_push($update_product_ids, $products->first()->id);
}
Product::whereIn('id', $update_product_ids)->update(['sample' => 'yes']);
This reduces the total number of queries.

How can I "temporary" store some values from a decoded JSON table?

I am constructing a function that is making a call with API to db and returns me JSON data. The json contains orders and I have already decoded them in php array. Every order has properties such as "product_id" and "quantity". I want to temporarily store the "quantity" property somewhere because I need to sum all the products with the same product_id. Any suggestion how to do this?
I'm in a bit of a hurry, but wanted to see if I could help you out.
$quantities = [];
//Loop through all the orders
foreach ($orders as $order) {
//Loop through the orderrows
foreach ($order->getOrderRows() as $orderRow) {
if (array_key_exists($orderRow->getProductName(), $quantities)) {
//The product is already in the quantities array, so the quantity of this orderrow is added to the total
$quantities[$orderRow->getProductName()] =
($quantities[$orderRow->getProductName()] + (int) $orderRow->getItemQuantity());
} else {
//If this is the first time the product is encountered add the product and its quantity to the quantities array
$quantities[$orderRow->getProductName()] = (int) $orderRow->getItemQuantity();
}
}
}
This is going to have the following result, showing you the product names along with their quantities:
$quantities = [
'foo' => 12,
'bar' => 3,
];
You may use the session variable to store these values.

Want to store view detail page product id into session

I want to make a recent visited product section. In view detail when user enter the product id will be $_GET['pid']; Now wanted to store it into $_SESSION['views']; Now it will be store into session. Then it need to be display as an array because it need to be put in Select query of product then it will be display in while loop.
$_SESSION['views']=$_GET['pid'];
Now when I enter into another product view detail page. The session will have 1,
Then in Query:
SELECT * FROM `property` WHERE id=$_SESSION['views']
But it needs to be while and display in loop.
After 7 products visit The first one will be removed and latest one should be insert into the last of session which will display new record.
$_SESSION['views'] = array();
Then add new product
function addProduct($product)
{
$_SESSION['views'][] = $product;
if (count($_SESSION['views']) > 7) {
$removedElement = array_shift($_SESSION['views']);
}
}
Query
SELECT * FROM `property` WHERE id in <?= implode($_SESSION['views']) ?>
If you need more Object oriented approach, look at SPL.
If you want show all 7 products, you should make query like this:
SELECT * FROM `property` WHERE id IN ($productList)
and $productList should be ID's of products, separated by comma, like this:
$productList = join(',', $_SESSION['views']);
now you need $_SESSION['views'] to be ab array:
if (isset($_SESSION['views'])) {
// add new element
$_SESSION['views'][] = $_GET['pid'];
// remove old elements
if (count($_SESSION['views'] > 7)) array_shift($_SESSION['views']);
} else {
// initialize an array
$SESSION['views'] = array($_GET['pid']);
}

Netsuite - get custom record with php toolkit

I've been handed a project to complete and the clients have asked for a field from a customrecord attached to each customer to appear on their website. We're integrating with Netsuite on login, and saving their data in our database so we don't have to keep accessing Netsuite (very slow).
On login, we access Netsuite to do a SearchMultiSelectCustomField and find the customer's company, and then do a CustomRecordSearchBasic and use their company ID to get a list of items they have access to.
We loop over each of those items, and then loop over their custom fields. One of the fields has a typeId of -10, which means we do an ItemSearchBasic to get this item's record and the item's custom fields, saving the internalId of this item.
At the end of this loop, we have an array of item IDs that a company is linked to. We also have the company ID (custrecord_nn_item_customer) and the Item ID (custrecord_nn_item_customer_list).
I need to perform a get request on a custom record to check if that customer has been approved for that item.
The customrecord's ID is 'customrecord_custitem', and internal Id is '1'.
The record has 3 fields (although only 2 show up for the customer's Netsuite Record page):
custrecord_lookup_item - this is the Item record code (custrecord_nn_item_customer_list from above)
custrecord_custitem_code is the code I need
My question (after all that) is does anyone have any examples or can point me in the right direction on how I can access a customrecord attached to a customer? I think all of the necessary information is provided, but I've never used Netsuite before or the PHP toolkit.
$this->depends('netsuite');
$this->netsuite->start();
// get the "customer" (aka company) that the user's contact record belongs to
$companySearch = $this->netsuite->complexObject('SearchMultiSelectCustomField')
->setFields(array(
'searchValue' => new nsListOrRecordRef(array('internalId' => $companyId)),
'internalId' => 'custrecord_nn_item_customer',
'operator' => 'anyOf'
));
// Fetch items that the user's company has access to
$search = $this->netsuite->complexObject('CustomRecordSearchBasic')
->setFields(array(
'recType' => new nsCustomRecordRef(array(
'internalId' => 260,
'type' => 'customRecord')
),
'customFieldList' => array($companySearch)
));
$response = $this->netsuite->client->search($search);
// loop over the items
foreach($this->netsuite->complexToSimple($response->recordList) as $record){
//var_dump($record);
$processor = null;
$this_item = '';
$this_person = '';
// foreach custom field (all the fields we're interested in, common name etc. are custom)
foreach($record['customFieldList']['customField'] as $customField){
$processor = $customField['value'];
$id = $processor['internalId'];
$typeId = $processor['typeId'];
if($customField['internalId']=='custrecord_nn_item_customer'){
$this_person = $id;
}elseif($customField['internalId']=='custrecord_nn_item_customer_list'){
$this_item = $id;
}
// a typeId of -10 = an Inventory Item
if($typeId == -10){
// do an ItemSearchBasic to fetch the item with it's custom fields
$itemSearch = $this->netsuite->complexObject('ItemSearchBasic')
->setFields(array(
'internalId' => array(
'operator' => 'anyOf',
'searchValue' => array('type' => 'inventoryItem', 'internalId' => $id)
)
));
$itemSearch = $this->netsuite->client->search($itemSearch);
// foreach custom item field
if($v=#$this->netsuite->complexToSimple($itemSearch->recordList)){
foreach($v as $itemRecord){
//var_dump($itemRecord);
$item = array('id' => $itemRecord['internalId']);
$items[] = $item;
}
}
}
}
}
It is inside the foreach loop that I need to get the customrecord field for the company ID and the current iteration of the item ID.
Set up a saved search with the results columns you need. Don't worry about filtering by customer.
Call the search from your code, and dynamically filter for the current customer.
Your code should be about 5-10 lines long to get that done, and should be super quick.

Magento: paginate filtered product collection

i want to filter and paginate a product collection. everything is fine - except pagination. im just getting the whole collection back, instead of 3 items for the first page.
//fetch all visible products
$product_collection = Mage::getModel('catalog/product')->getCollection();
//set wanted fields (nescessary for filter)
$product_collection->addAttributeToSelect('name');
$product_collection->addAttributeToSelect('description');
$product_collection->addAttributeToSelect('price');
$product_collection->addAttributeToFilter('visibility', array('neq' => 1));
//filter by name or description
$product_collection->addFieldToFilter(array(
array('attribute'=>'name','like'=>$sTerm),
array('attribute'=>'description','like'=>$sTerm)
));
//filter for max price
foreach ($product_collection as $key => $item) {
if($item->getPrice() >= $priceTo){
$product_collection->removeItemByKey($key);
}
}
//pagination (THIS DOESNT WORK!)
$product_collection->setPageSize(3)->setCurPage(1);
//TEST OUTPUT
foreach ($product_collection as $product) {
echo $product->getName().'<br />';
}
thanks for your support!
You are so close! Try moving that $product_collection->setPageSize(3)->setCurPage(1); line before the first foreach() iteration over the collection.
Magento collections are lazy-loaded. Until you directly load() them (or implicitly load them via a call to count() or foreach()) you can modify the collection properties which affect the underlying query (EDIT: see note below). Once the collection has been loaded explicitly or implicitly though you will only get the members of the _items property that have been set.
FYI you can call clear() to leave the original query-affecting properties (filters, sorters, limits, joins, etc) in place and then add further properties.
HTH
EDIT: Actually, adjusting query properties is always possible regardless of _items load state, but the effect won't be visible until the collection is regenerated.
Thanks #Ben! You gave me the right hint. Now it does work! Basically I'm creating another collection and filter this one by the ids of the already filtered items. Afterwards its easy to add pagination to that new collection. That's the working code:
//fetch all visible products
$product_collection = Mage::getModel('catalog/product')->getCollection();
//set wanted fields (nescessary for filter)
$product_collection->addAttributeToSelect('name');
$product_collection->addAttributeToSelect('description');
$product_collection->addAttributeToSelect('price');
$product_collection->addAttributeToFilter('visibility', array('neq' => 1));
//filter by name or description
$product_collection->addFieldToFilter(array(
array('attribute'=>'name','like'=>$sTerm),
array('attribute'=>'description','like'=>$sTerm)
));
//filter for max price
foreach ($product_collection as $key => $item) {
if($item->getPrice() >= $priceTo){
$product_collection->removeItemByKey($key);
}
}
//build id array out of filtered items (NEW!)
foreach($product_collection as $item){
$arrProductIds[]=$item->getId();
}
//recreate collection out of product ids (NEW)
$product_filtered_collection = Mage::getModel('catalog/product')->getCollection();
$product_filtered_collection->addAttributeToFilter('entity_id', array('in'=>$arrProductIds));
//add pagination (on new collection) (NEW)
$product_filtered_collection->setPageSize(3)->setCurPage(1);
//TEST OUTPUT
foreach ($product_filtered_collection as $product) {
echo $product->getName().'<br />';
}

Categories