Add new values to a attribute option in Magento - php

I am trying to add new values to an attribute option in Magento using a script to speed up the process since I have over 2,000 manufacturers.

Here is a piece of code that I used to perform exactly this task. Create a custom module (using ModuleCreator as a tool) and then create a mysql4-install-0.1.0.php under the sql/modulename_setup folder. It should contain the following (adapted to your own data, of course!).
$installer = new Mage_Eav_Model_Entity_Setup('core_setup');
$installer->startSetup();
$aManufacturers = array('Sony','Philips','Samsung','LG','Panasonic','Fujitsu','Daewoo','Grundig','Hitachi','JVC','Pioneer','Teac','Bose','Toshiba','Denon','Onkyo','Sharp','Yamaha','Jamo');
$iProductEntityTypeId = Mage::getModel('catalog/product')->getResource()->getTypeId();
$aOption = array();
$aOption['attribute_id'] = $installer->getAttributeId($iProductEntityTypeId, 'manufacturer');
for($iCount=0;$iCount<sizeof($aManufacturers);$iCount++){
$aOption['value']['option'.$iCount][0] = $aManufacturers[$iCount];
}
$installer->addAttributeOption($aOption);
$installer->endSetup();
More documentation on the Magento wiki if you want.
If you don't want to do it in a custom module, you could just create a php file that starts with:
require_once 'app/Mage.php';
umask(0);
Mage::app('default');

Answer of Jonathan is correct. But if you want to perform it without installer i.e in any other code, then you might find this helpful:
$arg_attribute = 'manufacturer';
$manufacturers = array('Sony','Philips','Samsung','LG','Panasonic','Fujitsu','Daewoo','Grundig','Hitachi','JVC','Pioneer','Teac','Bose','Toshiba','Denon','Onkyo','Sharp','Yamaha','Jamo');
$attr_model = Mage::getModel('catalog/resource_eav_attribute');
$attr = $attr_model->loadByCode('catalog_product', $arg_attribute);
$attr_id = $attr->getAttributeId();
$option['attribute_id'] = $attr_id;
foreach ($manufacturers as $key=>$manufacturer) {
$option['value'][$key.'_'.$manufacturer][0] = $manufacturer;
}
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->addAttributeOption($option);
More information can be found here.

I have created a function to dynamically add option to attribute
public function addAttributeOptions($attributeCode, $argValue)
{
$attribute = Mage::getModel('eav/config')
->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attributeCode);
if ($attribute->usesSource()) {
$id = $attribute->getSource()->getOptionId($argValue);
if ($id)
return $id;
}
$value = array('value' => array(
'option' => array(
ucfirst($argValue),
ucfirst($argValue)
)
)
);
$attribute->setData('option', $value);
$attribute->save();
//return newly created option id
$attribute = Mage::getModel('eav/config')
->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attributeCode);
if ($attribute->usesSource()) {
return $attribute->getSource()->getOptionId($argValue);
}
}
You can add an option to your attribute by providing code and option value
$this->addAttributeOptions('unfiorm_type', 'leotartd')

Important! (Hopefully this helps somebody, cause I was stuck like 2h with this issue)
If you are using special characters (such as ä, ö, ü, ß, ×, ...) make sure to encode them properly!
array_walk($manufacturers , create_function('&$val', '$val = utf8_encode($val);'));

Here a simple and very fast way....
Delete an option
/* My option value */
$value = 'A value';
/* Delete an option */
$options = array();
$entity_type_id = Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId(); // Product Entity Type ID
$attribute = Mage::getModel('eav/entity_attribute')->loadByCode($entity_type_id, $attribute_code); // Load attribute by code
if ($attribute && $attribute->usesSource()) {
$option_id = $attribute->getSource()->getOptionId($value); // Check Option ID from value...
if ($option_id) {
$options['delete'][$option_id] = true;
$attribute->setOption($options)->save();
}
}
/* END ! */
Add or update an option
/* Add/Update an option */
$options = array();
$entity_type_id = Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId(); // Product Entity Type ID
$attribute = Mage::getModel('eav/entity_attribute')->loadByCode($entity_type_id, $attribute_code); // Load attribute by code
if ($attribute && $attribute->usesSource()) {
$option_id = $attribute->getSource()->getOptionId($value); // Check Option ID...
$options['order'][$option_id] = 10; // Can be removed... Set option order...
$options['value'][$option_id] = array(
0 => $value, // Admin Store - Required !
1 => $value, // Store id 1 - If U want ! Can be removed
);
$attribute->setDefault(array($option_id)); /* If you want set option as default value */
$attribute->setOption($options)->save(); /* That's all */
}
/* END ! */

In my tutorial I am explaining how to read the options from the CSV and create the options pro grammatically.
http://www.pearlbells.co.uk/add-attribute-options-magento-scripts/
please click the tutorial for further explanation
function createAttribute($options) {
$option = array('attribute_id' =>
Mage::getModel('eav/entity_attribute')->getIdByCode(
Mage_Catalog_Model_Product::ENTITY,
'color'
)
);
for ($i = 0; $i < count($options); $i++) {
$option['value']['option'.$i][0] = $options[ $i ]; // Store View
$option['value']['option'.$i][1] = $options[ $i ]; // Default store view
$option['order']['option'.$i] = $i; // Sort Order
}
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->addAttributeOption($option);
}

Answer of Arvind Bhardwaj enter code here is correct. But if you want to perform it without installer i.e in any other code, then you might find this helpful:
Agree with Arvind but it's only works for insert the single option value and if you want to perform insert multiple option value then you just needs to replace the code from "$option['value'][$key.''.$manufacturer] = $manufacturer;" to "$option['values'][$key.''.$manufacturer] = $manufacturer;" to this.
below is the final code
require_once 'app/Mage.php';
umask(0);
Mage::app('default');
$arg_attribute = 'manufacturer';
$manufacturers = array('Sony', 'Philips', 'Samsung', 'LG', 'Panasonic', 'Fujitsu', 'Daewoo', 'Grundig', 'Hitachi', 'JVC', 'Pioneer', 'Teac', 'Bose', 'Toshiba', 'Denon', 'Onkyo', 'Sharp', 'Yamaha', 'Jamo');
$attr_model = Mage::getModel('catalog/resource_eav_attribute');
$attr = $attr_model->loadByCode('catalog_product', $arg_attribute);
$attr_id = $attr->getAttributeId();
$option['attribute_id'] = $attr_id;
foreach ($manufacturers as $key => $manufacturer) {
$option['values'][$key . '_' . $manufacturer] = $manufacturer;
}
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->addAttributeOption($option);
I hope its works for insertion multiple option.

Related

Magento 2 URL rewrite Issue : URL key already exists for specified store

I am facing this issue while saving a product programmatically on Magento 2.2.5
In any module, if I do $product->save(); OR $this->productRepository->save($product); inside a loop for multiple products. I get:
PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'the-lipstick.html-1' for key 'URL_REWRITE_REQUEST_PATH_STORE_ID' in /home/dev3/www/vendor/magento/zendframework1/library/Zend/Db/Statement/Pdo.php:228
The error is similar to the one described here : https://www.human-element.com/url-key-specified-store-already-exists-magento-2/
Products save fine with admin area login.
Any suggested fixes so far including the ones modifying the core files (DBStorage.php) do not work on 2.2.5.
What I tried so far:
1. Fix from https://www.human-element.com/url-key-specified-store-already-exists-magento-2/
2. Fix from https://magento.stackexchange.com/questions/210359/magento-2-product-url-rewrite-issue
Please suggest a solution/fix for M 2.2.5
My Fix :
In di.xml -
<preference for="Magento\UrlRewrite\Model\Storage\DbStorage" type="MyCompany\FixUrls\Model\ProductUrlFix" />
In ProductFixUrl write these two functions :
protected function doReplace(array $urls){
$this->deleteOld($urls);
$data = [];
$storeId_requestPaths = [];
foreach ($urls as $url) {
$storeId = $url->getStoreId();
$requestPath = $url->getRequestPath();
// Skip if is exist in the database
$sql = "SELECT * FROM url_rewrite where store_id = $storeId and request_path = '$requestPath'";
$exists = $this->connection->fetchOne($sql);
if ($exists) {
continue;
}
$storeId_requestPaths[] = $storeId . '-' . $requestPath;
$data[] = $url->toArray();
}
try {
$n = count($storeId_requestPaths);
for ($i = 0; $i < $n - 1; $i++) {
for ($j = $i + 1; $j < $n; $j++) {
if ($storeId_requestPaths[$i] == $storeId_requestPaths[$j]) {
unset($data[$j]);
}
}
}
parent::insertMultiple($data);
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
/** #var \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[] $urlConflicted */
$urlConflicted = [];
foreach ($urls as $url) {
$urlFound = parent::doFindOneByData(
[
UrlRewriteData::REQUEST_PATH => $url->getRequestPath(),
UrlRewriteData::STORE_ID => $url->getStoreId(),
]
);
if (isset($urlFound[UrlRewriteData::URL_REWRITE_ID])) {
$urlConflicted[$urlFound[UrlRewriteData::URL_REWRITE_ID]] = $url->toArray();
}
}
if ($urlConflicted) {
throw new \Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException(
__('URL key for specified store already exists.'),
$e,
$e->getCode(),
$urlConflicted
);
} else {
throw $e->getPrevious() ?: $e;
}
}
return $urls;
}
/**
* #param UrlRewrite[] $urls
*
* #return void
*/
public function deleteOld(array $urls)
{
$oldUrlsSelect = $this->connection->select();
$oldUrlsSelect->from(
$this->resource->getTableName(self::TABLE_NAME)
);
/** #var UrlRewrite $url */
foreach ($urls as $url) {
$oldUrlsSelect->orWhere(
$this->connection->quoteIdentifier(
UrlRewrite::ENTITY_TYPE
) . ' = ?',
$url->getEntityType()
);
$oldUrlsSelect->where(
$this->connection->quoteIdentifier(
UrlRewrite::ENTITY_ID
) . ' = ?',
$url->getEntityId()
);
$oldUrlsSelect->where(
$this->connection->quoteIdentifier(
UrlRewrite::STORE_ID
) . ' = ?',
$url->getStoreId()
);
}
// prevent query locking in a case when nothing to delete
$checkOldUrlsSelect = clone $oldUrlsSelect;
$checkOldUrlsSelect->reset(Select::COLUMNS);
$checkOldUrlsSelect->columns('count(*)');
$hasOldUrls = (bool) $this->connection->fetchOne($checkOldUrlsSelect);
if ($hasOldUrls) {
$this->connection->query(
$oldUrlsSelect->deleteFromSelect(
$this->resource->getTableName(self::TABLE_NAME)
)
);
}
}
After a migration and a week digging into the problem the only thing that worked for me was https://www.safemage.com/url-optimization-after-migration-magento-2.html
I had to downgrade to 2.2.7 to use it. It says it works on 2.3 but it does not.
After looking on internet for days i can't find exact solution of this.
Then i found if we change the URLKEY of the category it will not show this error so i have done this.
$category->setPath($parentCategory->getPath())
->setParentId($parentId)
->setName('test1')
->setIsActive(true)
->setUrlKey(rand(1,1000000000));
$category->save();
I use random function to add category in database with random no using ->setUrlKey(rand(1,1000000000)); you can add any thing in this like duplicate category name with some random no etc.
and errors gone if it helps you give an UP. thanks

How to copy an existing order (core, php) with Prestashop 1.6.1

I'm making a script that should make a copy of an existing order.
I can create the overall order, with this code:
$order = new Order($_GET["id_order"]);
$order->add();
But there's no products in the order - I tried with this:
$order_detail = new OrderDetail($_GET["id_order"]);
$order_detail->add();
What am I doing wrong, how can I copy an existing order?
You can duplicate an order using the duplicateObject() method from the ObjectModel class.
Here is a function that should do the trick :
function duplicateOrder($id_order)
{
$order = new Order($id_order);
$duplicatedOrder = $order->duplicateObject();
$orderDetailList = $order->getOrderDetailList();
foreach ($orderDetailList as $detail) {
$orderDetail = new orderDetail($detail['id_order_detail']);
$duplicatedOrderDetail = $orderDetail->duplicateObject();
$duplicatedOrderDetail->id_order = $duplicatedOrder->id;
$duplicatedOrderDetail->save();
}
$orderHistoryList = $order->getHistory(Configuration::get('PS_LANG_DEFAULT'));
foreach ($orderHistoryList as $history) {
$orderHistory = new OrderHistory($history['id_order']);
$duplicatedOrderHistory = $orderHistory->duplicateObject();
$duplicatedOrderHistory->id_order = $duplicatedOrder->id;
$duplicatedOrderHistory->save();
}
}

Showing bestseller of each category in navigation in Magento 1.7

I'm looking for a possibility to get the most sold product by category to show it in a specific part of the navigation. To show the product(s) isn't the problem but getting them.
I already did a intensive search through Google with different keywords but all I got were outdated plugins, modifications for bestseller.phtml (which doesn't exit in Magento 1.7 anymore) and setting filters on the resource model but I haven't found anymore which got me any result.
So I tried to get the products by myself (so far, it just should get the sales of any product, not the best one):
$category->getId();
$children = $category->getChildren();
foreach($children as $child)
{
$childCategoryIdString = $child->getId();
$childCategoryId = substr($childCategoryIdString, 14);
$childCategory = Mage::getModel('catalog/category')
->load($childCategoryId);
$productCollection = Mage::getModel('catalog/product')
->getCollection()
->addCategoryFilter($childCategory)
->load();
$allIds = $productCollection->getAllIds();
for($i = 0; $i < count($allIds); $i++)
{
$product = Mage::getModel('catalog/product')->load($allIds[$i]);
echo $product->getOrderedQty() . '_';
}
}
This has two issues: First it's making Magento yet slower. Second $product->getOrderedQty(), a method I have found in various results of my search, doesn't work. Now I don't really know what else I could try and looking for some help which is highly appreciated. Thanks!
$visibility = array(
Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG
);
$category = new Mage_Catalog_Model_Category();
$category->load(2); //My cat id is 10
$prodCollection = $category->getProductCollection()->addAttributeToFilter('visibility', $visibility)->setOrder('ordered_qty', 'desc');
<?php foreach($_productCollection as $_product): ?>
//whatever you want
<?php endforeach; ?>
hope this helps
You're using a lot of objects wrappers in your sample script. Methods like load encapsulated into multiple loops will produce huge delays and possibly huge memory usage (base on your product collection size).
When I addressed this issue the other day I decided to use straight ORM methods instead of objects for better performance.
There are two possible ways to show bestsellers. The less resources-consuming is to use aggregated bestsellers tables (like sales_bestsellers_aggregated_daily), but it has huge drawback - the data inside those tables is not updating authomatically. It's used in Admin Reports section, and will be updates only when you choose to refresh your statistics.
The other but much more reliable method is to join sales_flat_order_item table to retrieve sales_qty for each product. Obviously it's more resource consuming, since you have to count it yourself.
In my script I've chosen the latter path. I've modified it to meet your logic requirements. Also I've added a couple of joins to get Category name, you might not need that. But enough talking :) here's the code of my test.php shell script:
<?php
require_once 'abstract.php';
/**
* Magento Test Bestsellers script
*
* #category Mage
* #package Mage_Shell
*/
class Mage_Shell_Test extends Mage_Shell_Abstract
{
/**
* Run script
*
*/
public function run()
{
// benchmarking
$memory = memory_get_usage();
$time = microtime();
echo "Starting mem usage: $memory\n";
$catId = $this->getArg('category');
/** #var $collection Mage_Catalog_Model_Resource_Product_Collection */
$collection = Mage::getResourceModel('catalog/product_collection');
// join sales order items column and count sold products
$expression = new Zend_Db_Expr("SUM(oi.qty_ordered)");
$condition = new Zend_Db_Expr("e.entity_id = oi.product_id AND oi.parent_item_id IS NULL");
$collection->addAttributeToSelect('name')->getSelect()
->join(array('oi' => $collection->getTable('sales/order_item')),
$condition,
array('sales_count' => $expression))
->group('e.entity_id')
->order('sales_count' . ' ' . 'desc');
// join category
$condition = new Zend_Db_Expr("e.entity_id = ccp.product_id");
$condition2 = new Zend_Db_Expr("c.entity_id = ccp.category_id");
$collection->getSelect()->join(array('ccp' => $collection->getTable('catalog/category_product')),
$condition,
array())->join(array('c' => $collection->getTable('catalog/category')),
$condition2,
array('cat_id' => 'c.entity_id'));
$condition = new Zend_Db_Expr("c.entity_id = cv.entity_id AND ea.attribute_id = cv.attribute_id");
// cutting corners here by hardcoding 3 as Category Entiry_type_id
$condition2 = new Zend_Db_Expr("ea.entity_type_id = 3 AND ea.attribute_code = 'name'");
$collection->getSelect()->join(array('ea' => $collection->getTable('eav/attribute')),
$condition2,
array())->join(array('cv' => $collection->getTable('catalog/category') . '_varchar'),
$condition,
array('cat_name' => 'cv.value'));
// if Category filter is on
if ($catId) {
$collection->getSelect()->where('c.entity_id = ?', $catId)->limit(1);
}
// unfortunately I cound not come up with the sql query that could grab only 1 bestseller for each category
// so all sorting work lays on php
$result = array();
foreach ($collection as $product) {
/** #var $product Mage_Catalog_Model_Product */
if (isset($result[$product->getCatId()])) {
continue;
}
$result[$product->getCatId()] = 'Category:' . $product->getCatName() . '; Product:' . $product->getName() . '; Sold Times:'. $product->getSalesCount();
}
print_r($result);
// benchmarking
$memory2 = memory_get_usage();
$time2 = microtime();
$memDiff = ($memory2 - $memory)/1000000;
$timeDiff = $time2 - $time;
echo 'Time spent:' . $timeDiff . "s\n";
echo "Ending mem usage: $memory2\n";
echo "Mem used : {$memDiff}M\n";
}
/**
* Retrieve Usage Help Message
*
*/
public function usageHelp()
{
return <<<USAGE
Usage: php -f test.php -- [options]
php -f test.php -- --category 1
--categories <category> Filter by Category, if not specified, all categories are outputted
help This help
USAGE;
}
}
$shell = new Mage_Shell_Test();
$shell->run();
To use it just create a file test.php in your shell folder and insert the code I've provided into the file. See usageHelp if you're not familiar with command line php calls.
P.S. Added some benchmarking there to track your mem_usage and time.
UPDATE Upon reviewing the issue further I've found more elegant way to get the Bestsellers for each category using only Zend_Db adapter. The result will contain only category_id => product_id connection (not Magento Objects), but it's much easier and overall better. This code should go between the benchmarking blocks into the run function:
$catId = $this->getArg('category');
/** #var $resource Mage_Core_Model_Resource */
$resource = Mage::getModel('core/resource');
/** #var $adapter Zend_Db_Adapter_Abstract */
$adapter = $resource->getConnection('core_read');
$select = $adapter->select()
->from(array('c' => $resource->getTableName('catalog/category')), array('cat_id'=>'entity_id'))
->join(array('ccp' => $resource->getTableName('catalog/category_product')), 'c.entity_id = ccp.category_id', array())
->join(array('oi' => $resource->getTableName('sales/order_item')), 'ccp.product_id = oi.product_id', array('max_qty' => new Zend_Db_Expr('SUM(oi.qty_ordered - oi.qty_canceled)'), 'product_id' => 'product_id'))
->where('oi.parent_item_id is null')
->group('c.entity_id')
->group('oi.product_id')
->order('entity_id ASC')
->order('max_qty DESC');
if ($catId) {
$select->where('c.entity_id = ?', $catId);
}
$res = $adapter->fetchAll($select);
$result = array();
foreach ($res as $oneRes) {
if (isset($result[$oneRes['cat_id']])) {
continue;
}
$result[$oneRes['cat_id']] = $oneRes;
}
array_walk($result, function($var, $key) {
echo 'Category Id:' . $key . ' | Product Id:' . $var['product_id'] . ' | Sales Count:' . $var['max_qty'] . "\n";
});

Magento Configurable Product working but not showing until re-saved

I am currently learning how to create configurable product for Magento. Its all working fine, the product was successfully imported using my codes including its associated products. The problem is the product does not show up in front-end. I have to manually go to the back-end, edit the product and save it. Take note I do not have to change anything, I just need to open it, and save. Only then it will show up in front-end. Any idea why is that?
define('MAGENTO', dirname(dirname(__FILE__)));
require_once MAGENTO . '/app/Mage.php';
require_once 'FeedMag.php';
$myFeed = new FeedMag();
Mage::app();
// test data
$sku = "TESTSKU2";
$inventory = "10";
$stockData['qty'] = $inventory;
$stockData['is_in_stock'] = 1;
$simple['Description'] = 'Configurable Product 1';
$simple['ShortDescription'] = 'Short Description';
$simple['LongDescription'] = 'Long Description';
$simple['BrandCode'] = 'Nike';
$attr['color'] = 'Blue';
$attr['size'] = 1;
$price = 11;
// get attribute id
foreach($attr AS $key=>$value) {
$attr_ids[] = $myFeed->attributeValueExists($key, $value);
}
$new = false;
echo "<pre>";
try {
// get product id from SKU
$id = Mage::getModel('catalog/product')->getIdBySku($sku);
// load product if id exist or create a new one
if($id && $id > 0) {
$product = Mage::getModel('catalog/product')->load($id);
}
else {
$product = Mage::getModel('catalog/product')->setSku($sku);
$new = true;
}
// set it to configurable
$product->setTypeId('configurable');
// get attributes' id
$usingAttributeIds = $new_array = array();
foreach( $attr as $key=>$value ) {
$attribute = $product -> getResource() -> getAttribute( $key );
if ( $product -> getTypeInstance() -> canUseAttribute( $attribute ) ) {
if ( $new ) { // fix for duplicating attributes error
$usingAttributeIds[] = $attribute -> getAttributeId();
}
}
}
// if we have attributes' ID, set it to the product
if ( !empty( $usingAttributeIds ) ) {
$product -> getTypeInstance() -> setUsedProductAttributeIds( $usingAttributeIds );
$attributes_array = $product->getTypeInstance()->getConfigurableAttributesAsArray();
foreach($attributes_array as $key => $attribute_value) {
$attributes_array[$key]['label'] = $attribute_value['frontend_label'];
}
$product -> setConfigurableAttributesData($attributes_array);
$product -> setCanSaveConfigurableAttributes( true );
$product -> setCanSaveCustomOptions( true );
}
// set product data
$product->setStoreId(0)
->setAttributeSetId(4)
->setStockData($stockData)
->setPrice($price)
->setName($simple['Description'])
->setShortDescription($simple['ShortDescription'])
->setDescription($simple['LongDescription'])
->setCategoryIds(array(3))
->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH)
->setBrand($simple['BrandCode'])
->setStatus(1)
->setTaxClassId(2) //Taxable goods
->save();
// get previous children if any
$associated = Mage::getModel('catalog/product_type_configurable')
->getChildrenIds($product->getId());
// add new simple product to configurable product
$associated[0][] = Mage::getModel('catalog/product')->getIdBySku('SIMPLE1');
// add all simple product to configurable product
Mage::getResourceModel('catalog/product_type_configurable')
->saveProducts($product->getId(), array_unique($associated[0]));
}
catch (Mage_Core_Exception $e) {
echo $e->getMessage();
}
catch (Exception $e) {
echo $e;
}
echo "</pre>";
FeedMag is a custom class made by my colleague. There's a lot of method in there but for this purpose I'll be using just one; attributeValueExists to check if said attribute exists and if it does, its ID will be returned.
Simple product already exists so I just need to use it (SIMPLE1).
Its an issue with the indices when importing. You must be missing a field in the export sheet that is required to associate the items and the store. The reason it works when you save is because its rebuilding the table indices which is filling in that missing data.

Cakephp update or add new record

I have an image upload that adds the filename to a table called attachments. If the id already exists then I want it to update and if not then create a new record. At the moment it creates a new record so I have multiple records forthe one id. The id's are from a table called Addon's.
I am not sure how to do this in cakephp.
if (!empty($this->data)) {
$this->layout = null;
//if(empty($this->data['AddOn']['id'])){unset($this->data['AddOn']);}
// restructure data for uploader plugin // NEED TO GET RID OF THIS ? MOVE IT
$tmp_file = $this->data['Attachment'][0]['file'];
$tmp_file['extension'] = array_reverse(explode('.', $tmp_file['name']));
$tmp_file['extension'] = $tmp_file['extension'][0];
$tmp_file['title'] = strtolower(substr($tmp_file['name'],0,(0-strlen('.'.$tmp_file['extension']))));
$this->data['Attachment'][0]['alternative'] = ucwords(str_replace('_',' ', $tmp_file['title']));
$previous = $this->AddOn->Attachment->find('first', array('conditions'=> array('model'=>'AddOn', 'foreign_key'=>$id)));
if( !empty( $previous ) ) {
$this->AddOn->Attachment->id = $previous[ 'Attachment' ][ 'id' ];
}
if ($this->AddOn->save($this->data, array('validate' => 'first'))) {
$id = $this->AddOn->Attachment->getLastInsertID();
$att = $this->AddOn->Attachment->query("SELECT * from attachments WHERE id = ".$id);
$this->set('attachment',$att[0]['attachments']);
} else {
$tmp_file['name'] = 'INVALID FILE TYPE';
}
//debug($this->data);
$this->set('file', $tmp_file);
$this->RequestHandler->renderAs($this, 'ajax');
$this->render('../elements/ajax');
}
save() and saveAll() automatically update an existing row if the id has been set. You can do something like:
$previous = $this->AddOn->Attachment->find( /* whatever conditions you need */ );
if( !empty( $previous ) ) {
$this->AddOn->Attachment->id = $previous[ 'Attachment' ][ 'id' ];
}
Now the old record will be updated if it exists.
As a side note, the code after a successful saveAll() doesn't make much sense: first you're saving data to the database, then immediately retrieving it again. You can just keep using $this->data that already has the same content.
And another side note: you should use query() only as a last resort when you can't use Cake's other methods. query("SELECT * from attachments WHERE id = ".$id) is a trivial case that can be rewritten as $this->Model->id = $id; $this->Model->read(); or using a simple $this->Model->find() query.

Categories