I have create module for testing in Magento and i call change action url from browser and there SQL query for catalog/product is printed.
I user this code
<?php
class Test_Demo_IndexController extends Mage_Core_Controller_Front_Action
{
public function indexAction()
{
$this->loadLayout();
$block = $this->getLayout()->createBlock('capacityweb/Test','Test',array('template' => 'capacity/web/test.phtml'));
$this->getLayout()->getBlock('content')->append($block);
$this->renderLayout();
}
public function changeAction()
{
$this->loadLayout();
$this->renderLayout();
$action=$this->getRequest()->getParam('action');
$id=$this->getRequest()->getParam('id');
if($action!=null && $id!=null)
{
$relContact = Mage::getModel('catalog/product')->getCollection()->load($id);
}
}
}
if i use
$relContact = Mage::getModel('catalog/product')->getCollection()->load($id);
then magento display SQL query but instead of this
i use
$relContact = Mage::getModel('catalog/product')->getCollection();
then magento not display anything.
So how to fix issue with
$relContact = Mage::getModel('catalog/product')->getCollection()->load($id);
After reading your code, I think what you are trying to do is load one product, in this case you have the $id.
In this case you should use:
$product = Mage::getModel('catalog/product')->load($id)
And then you can access the desire data through:
$product->getName();
$product->getDescription()
... and so on.
Greetings
This is not an issue.
Magento uses the Lazy Loading design pattern for collections.
The sql for a collection is not executed until the collection is loaded or until you iterate through the results.
So Mage::getModel('catalog/product')->getCollection() will return an object that is an instance of Mage_Catalog_Model_Resource_Product_Collection that you can use how you need, but you don't have the products yet.
When calling Mage::getModel('catalog/product')->getCollection()->load() (by the way...the $id parameter is useless), then the query SELECT FROM catalog_product_entity..... is exectuted and in $collection->getIterator() you will have the records from the database as instances of Mage_Catalog_Model_Product.
[EDIT]
If you want a single product skip the getCollection call. You can get the instance of a product like this
$product = Mage::getModel('catalog/product')->load($id);
//changes some attributes
$product->setData('description', $description);
//or
//$product->setDescription($description);
$product->save().
See more details about it here.
Related
I have the following situation, Im trying to modify the price of products displayed in a platform.
Everything works ok for only 1 product (eg: product view) but I dont know what I have to do in order to modify the price of each product in an eloquent collection.
this is the code in my app:
ProductRepository.php:
public function CalcPrice($product){
$x = $product->price; //eg 5
$y = 4;
$amount= $x + $y;
return $amount;
}
For the details view of each product inside ProductController I have the following code and everything works perfect:
public function details($id){
$product = $this->product->getProductById($id);
$productprice = $this->product->getCalcPrice($product = $product);
return view('products.view',compact('product','productprice'))
}
On the other hand, my idea is to use the code contained in ProductRepository.php function CalcPrice in a collection.
My main doubt is what do I have to do, because in a collection probably I can have a variable $category in order to retrieve all products in a category, but I will not have a variable for each $product (for eg: a $productid like in details).
What can I do in order to eg:
modify each product price contained in a collection of a category
using CalcPrice function code?
eg: of code:
productrepository.php
public function AllProductsInCategory($catid)
{
return App\Product::where('categoryid', $catid)
->get();
}
but each product displaying their ($product->price + 4) as CalcPrice performs. thanks!.
You can achieve this by defining an attribute accessor on model and append it to model. This way it would be available for you on each instance like its other attributes.
As Taylor Otwell mentioned here, "This is intentional and for performance reasons." However there is an easy way to achieve this, say you have model named Product;
class Product extends Eloquent {
protected $appends = array('calc_price');
public function getCalcPriceAttribute()
{
//if you want to call your method for some reason
return $this->getCalcPrice($this);
// Otherwise more clean way would be something like this
// return $this->price + 4 // un-comment if you don't want to call getCalcPrice() method
}
}
Now you can access calculated price on each $product by simply calling $product->calc_price.
i'm taking over a project and saw that the previous developer added a custom related products association. So he implemented a function to get the associated collection looking like this
/**
* Retrieve collection CustomRelated product
*
* #return Mage_Catalog_Model_Resource_Product_Link_Product_Collection
*/
public function getCustomRelatedProductCollection()
{
$collection = $this->getLinkInstance()->useCustomRelatedLinks()
->getProductCollection()
->setIsStrongMode();
$collection->setProduct($this);
return $collection;
}
Then in phtml file, he's calling it out like this
$upsell_products = $_product->getCustomRelatedProductCollection();
And then he uses that collection in a foreach, and each element in the collection is using model 'catalog/product', but somehow it's not loading enough attributes like prices and name
It will load all of the attributes only when i call load function again like this
Mage::getModel('catalog/product')->load($p->getId())
Which i don't want to do because it's pointless to reload the model, i'm still new to Magento so i'm not sure how to make the get collection above to fully load the product model, any ideas?
You can load require attributes (name, price) like below.
public function getCustomRelatedProductCollection()
{
$collection = $this->getLinkInstance()->useCustomRelatedLinks()
->getProductCollection()
->addAttributeToSelect(array("name", "price"))
->setIsStrongMode();
$collection->setProduct($this);
return $collection;
}
//I have added new line in your code. please check now.
public function getCustomRelatedProductCollection()
{
$collection = $this->getLinkInstance()->useCustomRelatedLinks()
->getProductCollection()
->setIsStrongMode();
$collection->setProduct($this);
$collection->addAttributeToSelect('*'); //New line added by me.
return $collection;
}
I am new to MVC, I am porting a project written in non-MVC style to MVC, but I am stuck on a problem where it is necessary to call Model function in View.
Scenario:
Table1 - Products:
contains product_id, product_name etc. and for each product there can be multiple versions.
Table2 - Versions:
contains version_id, version_name, ... , product_id etc.
Now in the View I am displaying products and under each product heading I have to display version list of that product, in non-MVC style it was pretty simple, I can use the following code snippet in View:
foreach ($product as $row)
{
echo $row['product_name'];
if ($main->getVersionList($vresult,$row["product_id"]))
{
foreach ($vresult as $vrow)
{
echo $vrow['version_name'];
}
}
}
Now, I can pass Product array from controller to view but what about each Version array which needs to be generated corresponding to each product?
Update:
This is my final working solution (used a map), in controller:
$this->load->model ( 'product_mod' );
$data ['products'] = $this->product_mod->getProductList ();
$data ['versions'] = array ();
foreach ( $data ['products'] as $product )
{
$data ['versions'] [$product['product_id']] = $this->product_mod->getVersionList ( $product['product_id'] );
}
MVC or not to MVC
The first thing I should note is that It is impossible to write classical MVC in PHP. In fact the MVC-like PHP frameworks such as CodeIgniter or Yii implements sort of MVP in which:
view is passive and unaware of model
presenter (controller) changes state of model, reads information and passes it to view
Credits to tereško
CodeIgniter Approach
However, particularly in CodeIgniter, you have 3 steps:
Create a Model to query through the database and return the data (as an array or object)
Create a Controller to load and fetch the result from the Model (a method of the Model), and pass the returned data to the view
Create a View and use PHP loops to echo the result out, build the HTML.
Getting all together
Considering the above approach, you need to fetch the result from the database in your Model:
application/models/product.php
class Product extends CI_Model
{
public function get_product($product_id)
{
$this->db->select('*')->from('products');
$this->db->where('product_id', $product_id);
$this->db->join('versions', 'versions.product_id = products.product_id');
$query=$this->db->get();
return $query->first_row('array');
}
}
Then fetch and pass the result within the Controller:
application/controllers/products.php
class Products extends CI_Controller
{
public function view($product_id)
{
$this->load->model('product');
// Fetch the result from the database
$data['product'] = $this->product->get_product($product_id);
// Pass the result to the view
$this->load->view('product_view', $data);
}
}
Finally, use the returned data in the view, to generate the list:
application/views/product_view.php
// Use $product to display the product.
print_r($product);
You should do mysql query in your model, for example products_model (don't forget to load it)
Example Query : This is just select * from products
public function All_Products()
{
$this->db->select('');
$result = $this->db->get('products')->result_array();
return $result;
}
So as I see , you are foreach guy like me, rather than using mass queries.
In your controller you could load $products my your model.
$products = $this->products_model->All_Products();
My solution is creating a new array then putting new values in it.Also you need to getVersionList function in your model.
$newArray = array ();
foreach ( $products as $values ) {
$version = $this->products_model->getVersionList($values['product_id']);
$tmp = array (
'product_id' => $values ['product_id'],
'product_name' => $values ['product_name'],
'version' => $version
);
array_push ( $newArray, $tmp );
}
So add your new array to $data you could have them in your view file.
$data ['products'] = $newArray;
Sorry I didnt figure out all your queries but I think its better to teach how to catch fish than giving a fish.
Using the below code you can call the model's method in the view file. It's worked for me and is so simple also.
$CI =& get_instance();
$CI->model_name->method_name();
As I am required to pirnt the ratings of products in JSON format, i have made a module with controller and rating.php file in model folder. We I run the controller it shows all the data from that table, But I required only a single row. So through the url i am passing a parameter, but it wont works. I am attaching my indexcontroller.php here. suggest me upon this.
<?php
class Modulename_CustomRating_IndexController extends Mage_Core_Controller_Front_Action
{
public function indexAction ()
{
$arrParams = $this->getRequest()->getParams();
var_dump($arrParams);
$collection = Mage::getModel('Modulename_CustomRating_Model_CustomRating')->getCollection();
}
print_r (json_encode($collection ->getData()));
}
}
?>
As I am passing url as:localhost/magento/customrating?vote_id=1 , it is taking the parameter to it but returns whole table's data. I know this is due to getData(); but how to make to get the required row?
You have to use setEntityPkFilter method. Check Mage_Rating_Model_Resource_Rating_Option_Vote_Collection class for other methods.
$product_id = $this->getRequest()->getParam('product_id'); // or 'vote_id'
$collection = Mage::getModel('Modulename_CustomRating_Model_CustomRating')
->getResourceCollection()
->setEntityPkFilter($product_id);
If you want only 1 column you can try some Zend stuff because you can't use addAttributeToSelect. getSelect() returns Zend like query:
$adapter = $this->getConnection(); // $this->getConnection();
$collection->getSelect()
->reset(Zend_Db_Select::COLUMNS) // remove all columns
->columns('attribute_name'); // add only needed one
$result = $adapter->fetchAll($select);
Not sure whether this would work. It's not tested, just an idea.
I'm looking for the most effective way to get configurable product attribute values on product listing pages, for example color values for a product (from assigned simple products)
Currently looking into utilising catalog_product_flat_n table for this purpose, but perhaps there is an easier or more correct approach to do this? I'm trying to avoid using
$product->getTypeInstance()->getConfigurableAttributesAsArray()
on every product, as this will be very slow
Thanks
I had the same issue, so I created my own resource model for getting data from flat tables, look into code below
<?php
class NameSpace_ModuleName_Model_Resource_Colors extends
Mage_Core_Model_Resource_Db_Abstract
{
protected $_storeId;
protected function _construct()
{
$this->_init('catalog/product_flat', 'entity_id');
$this->_storeId = (int)Mage::app()->getStore()->getId();
}
public function getData($entityId)
{
$resource = Mage::getSingleton('core/resource');
$select = $resource->getConnection('core_read')->select();
$select
->from($this->getTable(array('catalog/product_flat', $this->_storeId)), '*')
->where('entity_id = :entity_id');
$result = $resource->getConnection('core_read')->fetchAll($select, array('entity_id' => $entityId));
return $result;
}
}
Hope it will be helpful for you