原理:
magento是基于Zend Framework的,所以底层用的还是zend的zend db
在文件app/code/core/Mage/Catalog/model/Resource/Eav /Mysql4/Config.php 中追踪到下面的函数 getAttributesUsedInListing()
- /**
- * Retrieve Product Attributes Used in Catalog Product listing
- *
- * @return array
- */
- public function getAttributesUsedInListing() {
- $select = $this->_getReadAdapter()->select()
- ->from(array(’main_table’ => $this->getTable(’eav/attribute’)))
- ->join(
- array(’additional_table’ => $this->getTable(’catalog/eav_attribute’)),
- ‘main_table.attribute_id = additional_table.attribute_id’,
- array()
- )
- ->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’ => new Zend_Db_Expr(’IFNULL(al.value, main_table.frontend_label)’))
- )
- ->where(’main_table.entity_type_id=?’, $this->getEntityTypeId())
- ->where(’additional_table.used_in_product_listing=?’, 1);
- – $sql = $select->assemble();
- – echo $sql;
- return $this->_getReadAdapter()->fetchAll($select);
- }
Magento操作数据库是在 Zend DB(Zend Framework)的基础上简单的做了下封装了。Zend DB 有自己的一套规则,来组合生成最终的SQL查询语句,可以看到上面的代码中有 from() join() joinLeft() where() 等函数,乱七八糟的一大堆东西,需要对 Zend DB的规则非常熟悉,才能知道实际执行的SQL语句,有没有办法直接打印出SQL语句?找了下,还真有,就是assemble()函数。在上面代码中最后 部分可以看到。顺被把SQL也附上来
- SELECT `main_table`.*,
- IFNULL(al.value, main_table.frontend_label) AS `store_label`
- FROM `eav_attribute` AS `main_table`
- INNER JOIN `catalog_eav_attribute` AS `additional_table`
- ON main_table.attribute_id = additional_table.attribute_id
- LEFT JOIN `eav_attribute_label` AS `al`
- ON al.attribute_id = main_table.attribute_id AND al.store_id = 1
- WHERE (main_table.entity_type_id=’4′)
- AND (additional_table.used_in_product_listing=1)
Magento中打印SQL语句来调试
有时为了调试magento商城系统,需要获取当前的查询sql语句,magento中获取SQL语句,这里我们通过
$collection->getSelectSql(true)来调试sql
- $collection=Mage::getResourceModel('reports/product_collection');
- $query=$collection->getSelectSql(true);
- echo $query;
magento获取SQL语句的另外一种方法是设置打印SQL为true
- $collection=Mage::getResourceModel('reports/product_collection');
- $collection->printlogquery(true);
得到的SQL语句:
- SELECT `e`.* FROM `catalog_product_entity` AS `e`
这里只是打印查询产品的SQL,如果要获取其他地方的SQL语句,道理也是一样的,我们根据上面的sql语句可以看到,其实magento的性能很差,"select *",magetno又是基于EAV架构的,可以想象下这速度
操作:
Magento的Models 和Collection 很强大,使用它们可以很方便的查询和操作数据库。但是有些场合,因为一些特殊需求或对Magento的了解不够深,可能会需要自己手写SQL语句来查询和操作数据库。以下分别是读写数据库的代码。
- // For Read
- // fetch read database connection that is used in Mage_Core module
- $read= Mage::getSingleton('core/resource')->getConnection('core_read');
- // first way
- $query = $read->query("select name from core_website");
- while ($row = $query->fetch())
- {
- $row = new Varien_Object($row);
- echo "<strong>" . $row->getName() . "</strong><br/>";
- }
- // second way
- $results = $read->fetchAll("SELECT * FROM core_website;");
- foreach ($results as $row)
- {
- echo $row['name'] . "<br/>";
- }
- // For Write
- // fetch write database connection that is used in Mage_Core module
- $write = Mage::getSingleton('core/resource')->getConnection('core_write');
- // now $write is an instance of Zend_Db_Adapter_Abstract
- $write->query("insert into tablename values ('aaa','bbb','ccc')");
注意上面的getConnection()方法中的参数 "core_read",表明了Magento将要使用的资源。与之相对应,当我们修改数据库的时候使用参数"core_write".一般情况下getConnection方法的参数应设成"core_read" 或 "core_write"(应该不指定也是可以的,但是如果Magento有多个数据库就必须指定了)。
作为新的entension module,在config.xml对"core_read" "core_write" 进行定义是个好的习惯。定义如下:
- <config>
- <global>
- <resources>
- <extension_setup>
- <connection>
- <use>core_setup</use>
- </connection>
- </extension_setup>
- <extension_read>
- <connection>
- <use>core_read</use>
- </connection>
- </extension_read>
- <extension_write>
- <connection>
- <use>core_write</use>
- </connection>
- </extension_write>
- </resources>
- </global>
- </config>
对应上面新增的module的名字.使用下面相对应的语句在read或write Database:
- $conn = Mage::getSingleton('core/resource')->getConnection('extension_read');
- $conn = Mage::getSingleton('core/resource')->getConnection('extension_write');
一般情况是绝大多数的module都定义成"core_read" "core_write"方便且节省资源。当然特殊情况除外:
- 给每个module不同的读写权限
- 需要用多个Database