I'm trying to read the list of products from Magento over the SOAP API (V2) and try to do some/any type of pagination.
Simple scenario:
var filters = new filters();
var products = catalogProductList(out pe, Connection.Session, filters, null);
This crashes Magento with: "Allowed memory size of 1073741824 bytes exhausted (tried to allocate 72 bytes."
I've tried to add pagination by specifying two complex filters on the product_id:
filters.complex_filter = new complexFilter[]
{
new complexFilter()
{
key = "product_id",
value = new associativeEntity()
{
key = "gt",
value = "400"
}
},
new complexFilter()
{
key = "product_id",
value = new associativeEntity()
{
key = "lt",
value = "1000"
}
}
};
However in this scenario only the second filter is applied, the first one is ignored.
I was thinking of reading the category tree and then the assigned products but there are lots of products that are not assigned to any category or to multiple categories so I'll either miss them or get them multiple times.
Is there a way to read the products list using some type of pagination so I don't read the complete list at once?
(Note: Requesting to increase memory is not really an option)
I've come up with a pretty good solution for this. Hope this helps someone.
$in = array();
for ($i = ($page * $size) - $size; $i < ($page * $size); $i++) {
$in[] = $i + 1;
}
$complexFilter = array('complex_filter' =>
array(
array(
'key' => 'product_id',
'value' => array(
'key' => 'in',
'value' => join(",", $in)
)
)
)
);
It looks like the answer you need is described at https://stackoverflow.com/a/22874035/2741137
Apparently, you can capitalize PRODUCT_ID in one of the two filter conditions to work around Magento's limitation that prevents two filter conditions on the same key.
I've successfully done the following in PHP:
$filters = new StdClass();
$filters->complexFilter = array(
array( 'key' =>'sku', 'value' => array('lt'=>'03969999')),
array( 'key' => 'sku', 'value' => array('gt'=>'03969000')),
);
Although, according to
<complexType name="filters"><all><element name="filter" type="typens:associativeArray" minOccurs="0"/><element name="complex_filter" type="typens:complexFilterArray" minOccurs="0"/></all></complexType>
Maybe it needs to be "$filters->complex_filter = array();"? The first code appeared to have worked for me.
Ugly as hell, but works for me :
public catalogProductEntity[] GetProducts()
{
int storeId;
catalogProductEntity[] catalogEntity;
List<catalogProductEntity> res = new List<catalogProductEntity>();
Client.catalogProductCurrentStore(out storeId, SessionId, null);
var filters = new filters();
filters.complex_filter = new complexFilter[1];
filters.complex_filter[0] = new complexFilter();
complexFilter filter = filters.complex_filter[0];
filter.key = "name";
filter.value = new associativeEntity();
associativeEntity assoc = filter.value;
assoc.key = "like";
//A to Z.
for (char i = 'A'; i <= 'Z'; i++)
{
assoc.value = i + "%";
Client.catalogProductList(out catalogEntity, SessionId, filters, null);
res.AddRange(catalogEntity);
}
//Starts with #.
assoc.value = "#%";
Client.catalogProductList(out catalogEntity, SessionId, filters, null);
res.AddRange(catalogEntity);
//0 to 9
for (int i = 0; i <= 9; i++)
{
assoc.value = i + "%";
Client.catalogProductList(out catalogEntity, SessionId, filters, null);
res.AddRange(catalogEntity);
}
return res.ToArray();
}
Related
ErrorException
Array to string conversion
$presocio = new Presocio;
$presocio->prestamo_id = $request->prestamo_id;
$presocio->ncuota = $request->ncuota;
$presocio->montopag = $request->montopag;
$presocio->fechapag = $request->fechapag;
$presocio->save();
In the end I managed to make it work like this, it works perfectly.
it can be done in different ways, example with ::create ::insert
$prestamo = new Prestamo;
$prestamo->socio_id = $request->socio_id;
$prestamo->monto = $request->monto;
$prestamo->cuotas = $request->cuotas;
$prestamo->alias = $request->alias;
$prestamo->save();
$idprestamo = $prestamo->id;
if (count($request->ncuota) > 0) {
foreach ($request->ncuota as $item => $v) {
$presocio = new Presocio;
$presocio->fill(
array(
'prestamo_id' => $idprestamo,
'ncuota' => $request->ncuota[$item],
'montopag' => $request->montopag[$item],
'fechapag' => $request->fechapag[$item],
)
);
$presocio->save();
}
}
toast('Pago Programados Registrado', 'success');
return redirect('prestamo');
Update since we now have the form supplied. You are using form names such as ncuota[] instead of ncuota which makes it an array. Are you able to make more than 1 Preseocio? if this is the case you want to loop over the items in the controller.
for ($i = 0; $i < count($request->ncuota); $i++)
{
Presocio::create([
'prestamo_id' => $request->prestamo_id[$i],
'ncuota' => $request->ncuota[$i],
'montopag' => $request->montopag[$i],
'fechapag' => $request->fechapag[$i],
]);
}
Otherwise just remove the [] off the end of the form names.
class Presocio
{
...
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'prestamo_id',
'ncuota',
'montopag',
'fechapag',
];
...
}
Presocio::create($request->all());
Now, Thats not the issue. That is just a bit of house keeping.
Your issue is that one of your request fields is an Array. Which ever one it is you will need to convert it to a JSON object or find a better way of storing it.
If you dont care and want to keep it as an array, modify the database field to be a jsonb field.
Try This create method
remove your all code and write only this code in your store method
$input = $request->all();
Presocio::create($input);
You can do that like:
for($i=0; $i < count($request->input('prestamo_id', 'ncuota', 'montopag', 'fechapag')); $i++) {
$presocio = new Presocio;
$presocio->prestamo_id = $request->prestamo_id[$i];
$presocio->ncuota = $request->ncuota[$i];
$presocio->montopag = $request->montopag[$i];
$presocio->fechapag = $request->fechapag[$i];
$presocio->save();
}
https://imgur.com/a/TokTAsq
Why doesn't forget() remove the created_at from collection. tried with except() doesn't work too
$descRequest = request()->descTable;
$wherePage = request()->onPage ?? 1;
$rowsPerPageRequest = request()->rowPerPage ?? 2;
$sortedByRequest = request()->sortBy ?? 'generatednumber_id';
$makeData = Generatenumberid::withCount([
'generateNumberIdGeneratedNumber as total_generated_number'
])
->orderBy($sortedByRequest, $descRequest)
->paginate($rowsPerPageRequest, ['*'], 'page', $wherePage);
$mapMakeData = $makeData->map(function ($item, $key) {
$carbonDateString = $item->created_at->format('d F Y');
$carbonForHuman = $item->created_at->diffForHumans();
$item->id = $item->id;
$item->generatednumber_id = $item->generatednumber_id;
$item->total_generated_number = $item->total_generated_number;
$item->time_generated = "{$carbonDateString} - {$carbonForHuman}";
return $item;
});
$collectMap = collect($mapMakeData->all());
$collectMap->forget('created_at');
dd($collectMap->all());
Expected result
The given column removed from the collection
"id" => 39
"generatednumber_id" => "CELLNUMBS-|2019-02-03|-0023"
"updated_at" => "2019-02-03 13:25:01"
"total_generated_number" => 0
"time_generated" => "03 February 2019 - 1 day ago"
I think this is because you are working with a collection of arrays. forget() or except() works with Collections only.
So, this should work.
//
//
//
$collectMap = collect($mapMakeData->all());
$collectMap->map(function($item) {
return array_except($item, 'created_at');
});
dd($collectMap->all());
i am not sure why the sorting of a product attribute on compare page is not working same as on product page. Like on product page the atribute sort is
on product page
1 name
2 new attribute
3 new attribute1
4 color
but on comapre page when i am comp[aring the 2 products has same attributes the attribute sort order becomes
on compare page
1 name
2 color
3 new attribute
4 new attribute1
I have googled a lot to find answer but unable to find. Please help me to fix this issue.
Below are the functions which i find
public function getComparableAttributes()
{
if (is_null($this->_comparableAttributes)) {
$this->_comparableAttributes = array();
$setIds = $this->_getAttributeSetIds();
if ($setIds) {
$attributeIds = $this->_getAttributeIdsBySetIds($setIds);
$select = $this->getConnection()->select()
->from(array('main_table' => $this->getTable('eav/attribute')))
->join(
array('additional_table' => $this->getTable('catalog/eav_attribute')),
'additional_table.attribute_id=main_table.attribute_id'
)
->joinLeft(
array('al' => $this->getTable('eav/attribute_label')),
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . (int) $this->getStoreId(),
array('store_label' => $this->getConnection()->getCheckSql('al.value IS NULL', 'main_table.frontend_label', 'al.value'))
)
->where('additional_table.is_comparable=?', 1)
->where('main_table.attribute_id IN(?)', $attributeIds);
$attributesData = $this->getConnection()->fetchAll($select);
if ($attributesData) {
$entityType = Mage_Catalog_Model_Product::ENTITY;
Mage::getSingleton('eav/config')
->importAttributesData($entityType, $attributesData);
foreach ($attributesData as $data) {
$attribute = Mage::getSingleton('eav/config')
->getAttribute($entityType, $data['attribute_code']);
$this->_comparableAttributes[$attribute->getAttributeCode()] = $attribute;
}
unset($attributesData);
}
}
}
return $this->_comparableAttributes;
}
/**
* Load Comparable attributes
*
* #return Mage_Catalog_Model_Resource_Product_Compare_Item_Collection
*/
public function loadComparableAttributes()
{
$comparableAttributes = $this->getComparableAttributes();
$attributes = array();
foreach ($comparableAttributes as $attribute) {
$attributes[] = $attribute->getAttributeCode();
}
$this->addAttributeToSelect($attributes);
return $this;
}
bUt i cant understand how to filter it by sort order .Please suggest
check the modifications in function below:
the file used is vendor/magento/module-catalog/Model/ResourceModel/Product/Compare/Item/Collection.php
But this is not the best way to do it. you need to override it as per Magento Standards.
I am working on it, will update shortly.
public function getComparableAttributes()
{
if ($this->_comparableAttributes === null) {
$this->_comparableAttributes = [];
$setIds = $this->_getAttributeSetIds();
if ($setIds) {
$attributeIds = $this->_getAttributeIdsBySetIds($setIds);
$select = $this->getConnection()->select()->from(
['main_table' => $this->getTable('eav_attribute')]
)->join(
['additional_table' => $this->getTable('catalog_eav_attribute')],
'additional_table.attribute_id=main_table.attribute_id'
)->joinLeft(
['al' => $this->getTable('eav_attribute_label')],
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . (int)$this->getStoreId(),
[
'store_label' => $this->getConnection()->getCheckSql(
'al.value IS NULL',
'main_table.frontend_label',
'al.value'
)
]
)
->joinLeft( //add sort order to sort the attributes as per backend sort. -- Abid
['as' => $this->getTable('eav_entity_attribute')],
'as.attribute_id = main_table.attribute_id'
)
->where(
'additional_table.is_comparable=?',
1
)->where(
'main_table.attribute_id IN(?)',
$attributeIds
)
->order('as.sort_order') //sort by sort_order -- Abid
;
$attributesData = $this->getConnection()->fetchAll($select);
if ($attributesData) {
$entityType = \Magento\Catalog\Model\Product::ENTITY;
$this->_eavConfig->importAttributesData($entityType, $attributesData);
foreach ($attributesData as $data) {
$attribute = $this->_eavConfig->getAttribute($entityType, $data['attribute_code']);
$this->_comparableAttributes[$attribute->getAttributeCode()] = $attribute;
}
unset($attributesData);
}
}
}
return $this->_comparableAttributes;
}
On product page attributes are sorted like in attribute set.
On compare page attributes are not sorted at all.
You can rewrite function getComparableAttributes in class Mage_Catalog_Model_Resource_Product_Compare_Item_Collection and implement your own sort logic.
But note, that this function differs in different Magento versions. You can try to use free extension ET Advanced Compare or take part of code from this extension (code is available on bitbucket.org. link i on extension page)
When a new simple product is added (via CSV or manually) we need to check if the appropriate configurable product has been added (where SKU = "item_number-item_colour_code" e.g. BLEA2606B-BK001). If the configurable product exists then associate the simple product. If the configurable product does not exist then create using the data in the simple product AND then associate the simple product.
I found some help from HERE but don't know how check if configurable product already exists, and if not how to create one.
Here is the script file that I downloaded. Can anybody advice if this will work with my scenario?
EDITED
I have scraped the idea of creating configurable product in import. I am doing it by capturing the catalog_product_save_after event now. Hopefully that will get me somewhere.
EDITED 2
OK, Finally, I have it working. I'm doing it in the observer. I know it slows down the product save process but couldn't think of any other way. Thats what I'm doing:
public function productSave($observer)
{
$p = $observer->getProduct();
$pr = Mage::getModel('catalog/product')->load($p->getId());
$attributeValue = Mage::getResourceModel('catalog/product')->getAttributeRawValue($pr->getId(), 'size'); //loads attribute option value
$qtyStock = Mage::getModel('cataloginventory/stock_item')->loadByProduct($pr)->getQty();
Mage::log('Qty: '.$qtyStock.$pr->getId(), null, 'test.txt');
if ($pr->getTaxClassId() == '0' || !isset($pr->getTaxClassId)) {
$taxClass = 'None';
} elseif ($pr->getTaxClassId() == '2') {
$taxClass = 'Taxable Goods';
} elseif ($pr->getTaxClassId() == '4') {
$taxClass = 'Shipping (not used by AvaTax)';
} elseif ($pr->getTaxClassId() == '5') {
$taxClass = 'General';
}
$_configSku = $pr->getItemNumber().'-'.$pr->getItemColourCode();
$category = array();
$categoryCollection = $pr->getCategoryCollection();
foreach ($categoryCollection as $cat) {
$category[] = $cat->getId();
}
$_configExist = Mage::getModel('catalog/product')->loadByAttribute('sku',$_configSku);
if($_configExist && $_configSku != '-') {
//Mage::log($_configExist, null, 'test.txt');
//Mage::log($_configSku, null, 'test.txt');
$new_ids = array();
$current_ids = $_configExist->getTypeInstance()->getUsedProductIds();
foreach($current_ids as $temp_id)
{
$new_ids[] = $temp_id;
}
}
if(!$_configExist && $_configSku != '-') {
$att_size = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product','size');
$att_sizes = $this->__getAttList('size');
$confProduct = Mage::getModel('catalog/product');
$confProduct->setAttributeSetId('10');
$confProduct->setSku($_configSku);
$confProduct->setTypeId('configurable');
$confProduct->setName($pr->getName());
$confProduct->setDescription($pr->getDescription());
$confProduct->setShortDescription($pr->getShortDescription());
$confProduct->setCreatedAt(strtotime('now'));
$confProduct->setPrice($pr->getPrice());
$confProduct->setStatus(1);
$confProduct->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
$confProduct->setWebsiteIDs(array(1));
$confProduct->setStockData(array(
'is_in_stock' => 1,
'qty' => 9999
));
$confProduct->setTaxClassId( $taxClass );
$confProduct->setCategoryIds( $category );
/* Set Configurable Attributes */
$confProduct->setConfigurableAttributesData($tmp = array(
array_merge($att_size->getData(), array('label' => '', 'values' => $size_values))
));
$simpleProducts = array(
$pr->getId()=>array( 'attribute_id'=>'145', 'label'=>'size', 'value_index'=>$attributeValue, 'is_percent'=>0, 'pricing_value'=>'' )
);
/* Set Associated Products */
$confProduct->setConfigurableProductsData( $simpleProducts );
//print_r( get_class_methods( $confProduct ) );
$confProduct->save();
}
elseif ($_configExist && !in_array($pr->getId(), $new_ids)) {
$new_ids = array();
$current_ids = $_configExist->getTypeInstance()->getUsedProductIds();
$current_ids[] = $pr->getId();
$current_ids = array_unique($current_ids);
foreach($current_ids as $temp_id)
{
parse_str("position=", $new_ids[$temp_id]);
}
Mage::log('inside', null, 'test.txt');
Mage::log($current_ids, null, 'test.txt');
$_configExist->setConfigurableProductsData($new_ids)->save();
}
All works fine with manual product save/update and import csv (it is slow but works). The only thing is, in configurable product, the Attribute Name field is empty. How to set attribute name there?
with magmi you can easily create configurable products, and more awesome stuff
I have found the way. See EDITED 2 section in the question for the solution.
I'm manually creating reviews in Magento and I'm trying to find out how I add the rating information in? I can add the reviews no problem but I'm struggling with the rating values (star values).
I have an array that looks like this:
array("Price"=>80, "Value"=>60, "Quality"=>60);
How can I add that to the star system and the Summary Rating?
Thanks.
Ok, so this is what I have so far:
This adds a review:
$review->setEntityPkValue(23);//product id
$review->setStatusId(1);
$review->setTitle("title");
$review->setDetail("detail");
$review->setEntityId($review->getEntityIdByCode(Mage_Review_Model_Review::ENTITY_PRODUCT_CODE));
$review->setStoreId(Mage::app()->getStore()->getId());
$review->setStatusId(1); //approved
$review->setNickname("Me");
$review->setReviewId($review->getId());
$review->setStores(array(Mage::app()->getStore()->getId()));
$review->save();
$review->aggregate();
This adds a rating for a review <-I'm stuck here!
// this is some test code to add the rating review
$rating[0]['Price'] = 80;
$rating[0]['Value'] = 100;
$rating[0]['Quality'] = 80;
$product_id = 23;
$review_id = 631;
foreach ($rating as $ratingId => $optionId) {
// This is the bit where it all seems to go wrong!:
Mage::getModel('rating/rating')
->setRatingId(1)
->setReviewId($review_id)
->addOptionVote($val, $product_id);
}
Thanks!
This worked for me:
public function addReview($ratingarray)
{
$product_id = $ratingarray['product_id'];
$storeid = $ratingarray['store_id'];
$title = $ratingarray['title'];
$customerid = $ratingarray['customer_id'];
$nickname = $ratingarray['nickname'];
$detail = $ratingarray['detail'];
$review = Mage::getModel('review/review');
$review->setEntityPkValue($product_id);
$review->setStatusId(1);
$review->setTitle($title);
$review->setDetail($detail );
$review->setEntityId($review->getEntityIdByCode(Mage_Review_Model_Review::ENTITY_PRODUCT_CODE));
$review->setStoreId($storeid);
$review->setStatusId(1); //approved
$review->setCustomerId($customerid);
$review->setNickname($nickname);
$review->setReviewId($review->getId());
$review->setStores(array($storeid));
$review->save();
$review->aggregate();
//return "success";
$rating_options = $ratingarray['options'];
/*array(
array(1,2,3,4),
array(6,7,8),
array(11,12)
);*/
$row = count($rating_options);
$rating_id = 1;
foreach($rating_options as $key1=>$val1)
{
foreach($val1 as $key2=>$val2)
{
$_rating = Mage::getModel('rating/rating')
->setRatingId($key1)
->setReviewId($review->getId())
->addOptionVote($val2,$product_id );
}
}
return "Success";
}
I am calling this like =>
$options = array(1=>array(1,2,3,4),2=>array(6,7,8),3=>array(11,12));
$reviewarray = array('customer_id'=>'21','product_id'=>'176','store_id'=>'4','title'=>'Review','nickname'=>'XYZ','detail'=>'Nice Product with Life time warrenty', 'options'=>$options);