banner-magento-categoria

Magento – Executando Queries SQL

O uso de models no Magento é uma ótima maneira de acessar e modificar dados. Usando métodos bem conhecidos e abstração inteligente, o Varien esconde o complexo SQL necessário para executar operações de dados. Embora isso facilite a aprendizagem, ele geralmente impacta a velocidade da operação. Consequentemente na capacidade de resposta do seu site. Você pode perceber isto ao salvar models que utilizam a arquitetura EAV.

Frequentemente isso não pode ser evitado. Porém existem algumas situações em que a execução de consultas SQL diretas seria mais simples e muito mais rápido levando a uma instalação mais otimizada. Um exemplo disso é atualizar os preços dos produtos globalmente. Seria fácil escrever algum código Magento que acompanhava todos os produtos e modificasse o preço.

Em um grande conjunto de dados, salvar cada produto individual pode levar um longo tempo. Portanto poderia tornar o sistema inutilizável. Para combater isso, é possível emitir uma consulta SQL direta. Ela poderia atualizar 1000 de produtos em 1 ou 2 segundos.

Magento: Conexão com o Banco de Dados

Por padrão, o Magento se conectará automaticamente ao seu banco de dados. Ele fornecerá dois recursos separados que você pode usar para acessar dados. O core_read e core_write. Como você provavelmente pode adivinhar, core_read é para leitura do banco de dados. O core_write é para escrever no banco de dados. É importante garantir que você use o recurso correto quando lê ou escreve dados no banco de dados. Especialmente quando escreve extensões personalizadas do Magento que serão lançadas na natureza.

<?php	
	/**
	 * Get the resource model
	 */
	$resource = Mage::getSingleton('core/resource');
 
	/**
	 * Retrieve the read connection
	 */
	$readConnection = $resource->getConnection('core_read');
 
	/**
	 * Retrieve the write connection
	 */
	$writeConnection = $resource->getConnection('core_write');

Nomes e Prefixos de Tabelas no Magento

Ao instalar o Magento, você tem a opção de usar um prefixo da tabela. Um prefixo de tabela é uma seqüência de caracteres que é adicionado ao início de cada nome de tabela em seu banco de dados. Estes são úteis se você estiver instalando vários sistemas em 1 banco de dados. O prefixo irá ajudar a distinguir os dados de cada aplicativo de outro. Felizmente, o Magento possui uma função incorporada simples que permite adicionar o prefixo a um nome de tabela determinado.

Obter Nome da Tabela a partir de uma String

<?php
 
	/**
	 * Get the resource model
	 */
	$resource = Mage::getSingleton('core/resource');
 
	/**
	 * Get the table name
	 */
	$tableName = $resource->getTableName('catalog_product_entity');
 
	/**
	 * if prefix was 'mage_' then the below statement
	 * would print out mage_catalog_product_entity
	 */
	echo $tableName;

Obter Nome da Tabela a partir do Entity Name

<?php
 
	/**
	 * Get the resource model
	 */
	$resource = Mage::getSingleton('core/resource');
 
	/**
	 * Get the table name
	 */
	$tableName = $resource->getTableName('catalog/product');
 
	/**
	 * if prefix was 'mage_' then the below statement
	 * would print out mage_catalog_product_entity
	 */
	echo $tableName;

Lendo o Banco de Dados

Varien_Db_Select::fetchOneEnquanto os modelos Magento escondem a complexidade do sistema EAV, eles às vezes exigem muito mais dados do que é necessário. Se, por exemplo, você tiver uma ID de produto e quiser que seja SKU. Seria muito mais rápido executar uma única consulta para obter esse valor do que carregar em um modelo de produto inteiro. O inverso desta operação está disponível na classe de recurso do produto.

Varien_Db_Select::fetchAll

Este método leva uma consulta como parâmetro, executa-a e retorna todos os resultados como uma matriz. No exemplo de código abaixo, usamos Varien_Db_Select :: fetchAll para retornar todos os registros na tabela catalog_product_entity.

<?php
 
	/**
	 * Get the resource model
	 */
	$resource = Mage::getSingleton('core/resource');
 
	/**
	 * Retrieve the read connection
	 */
	$readConnection = $resource->getConnection('core_read');
 
	$query = 'SELECT * FROM ' . $resource->getTableName('catalog/product');
 
	/**
	 * Execute the query and store the results in $results
	 */
	$results = $readConnection->fetchAll($query);
 
	/**
	 * Print out the results
	 */
	 var_dump($results);

Varien_Db_Select::fetchCol

Esse método é semelhante ao fetchAll, exceto que em vez de retornar todos os resultados, ele retorna a primeira coluna de cada linha de resultados. No exemplo de código abaixo, usamos Varien_Db_Select :: fetchCol para recuperar todos os SKUs em nosso banco de dados em uma matriz.

<?php
	/**
	  * Get the resource model
	  */
	$resource = Mage::getSingleton('core/resource');
 
	/**
	 * Retrieve the read connection
	 */
	$readConnection = $resource->getConnection('core_read');
 
	/**
	 * Retrieve our table name
	 */
	$table = $resource->getTableName('catalog/product');
 
	/**
	 * Execute the query and store the results in $results
	 */
	$sku = $readConnection->fetchCol('SELECT sku FROM ' . $table . ');
 
	/**
	 * Print out the results
	 */
	 var_dump($results);

Experimente este código e veja os resultados. Observe como todos os SKU estão em uma única matriz, em vez de cada linha ter sua própria matriz? Se você não entende isso, tente alterar fetchCol para fetchAll e compare as diferenças.

Varien_Db_Select::fetchOne

Ao contrário dos dois métodos anteriores, Varien_Db_Select :: fetchOne retorna apenas um valor da primeira linha. Esse valor é retornado por conta própria e não está envolvido em uma matriz. No exemplo de código abaixo, tomamos um ID de produto de 44 e devolvemos o SKU.

<?php
 
	/**
	 * Get the resource model
	 */
	$resource = Mage::getSingleton('core/resource');
 
	/**
	 * Retrieve the read connection
	 */
	$readConnection = $resource->getConnection('core_read');
 
	/**
	 * Retrieve our table name
	 */
	$table = $resource->getTableName('catalog/product');
 
	/**
	 * Set the product ID
	 */
	$productId = 44;
 
	$query = 'SELECT sku FROM ' . $table . ' WHERE entity_id = '
			 . (int)$productId . ' LIMIT 1';
 
	/**
	 * Execute the query and store the result in $sku
	 */
	$sku = $readConnection->fetchOne($query);
 
	/**
	 * Print the SKU to the screen
	 */
	echo 'SKU: ' . $sku . '<br/>';

Ao tentar este exemplo, certifique-se de alterar a ID do produto para uma ID que existe no seu banco de dados!
Você pode pensar que fetchOne funciona da mesma forma que fetchCol ou fetchAll. Se você adicionasse apenas 1 coluna à consulta SELECT e adicionasse um ‘LIMIT 1’, no entanto, você estaria errado. A principal diferença com esta função é que o valor retornado é o valor real. No caso o Varien_Db_Select :: fetchCol e Varien_Db_Select :: fetchAll envolveria o valor em uma matriz. Para entender isso um pouco, tente trocar o método e comparar os resultados.

Escrevendo no Banco de Dados

Ao salvar um modelo Magento, pode haver muitos dados de fundo que estão sendo salvos, que você nem sabia. Por exemplo, salvar um modelo de produto pode demorar vários segundos. Isto é devido à quantidade de salvamento e indexação de dados relacionados que precisa ocorrer. Isso está certo se você precisar salvar todos os dados. Porém se você quiser apenas atualizar o SKU de um produto é disperdício.
O código de exemplo abaixo mostra-lhe como, quando dado um ID de produto, você pode alterar o SKU. Este é um exemplo trivial, mas deve ilustrar como executar consultas de escrita em seu banco de dados Magento.

<?php
 
	/**
	 * Get the resource model
	 */
	$resource = Mage::getSingleton('core/resource');
 
	/**
	 * Retrieve the write connection
	 */
	$writeConnection = $resource->getConnection('core_write');
 
	/**
	 * Retrieve our table name
	 */
	$table = $resource->getTableName('catalog/product');
 
	/**
	 * Set the product ID
	 */
	$productId = 44;
 
	/**
	 * Set the new SKU
	 * It is assumed that you are hard coding the new SKU in
	 * If the input is not dynamic, consider using the
	 * Varien_Db_Select object to insert data
	 */
	$newSku = 'new-sku';
 
	$query = "UPDATE {$table} SET sku = '{$sku}' WHERE entity_id = "
			 . (int)$productId;
 
	/**
	 * Execute the query
	 */
	$writeConnection->query($query);

 

Para testar isso funcionou, use o conhecimento adquirido na primeira parte deste tutorial para escrever uma consulta para extrair o SKU que acaba de ser alterado.

Varien_Db_Select

O Varien_Db_Select, que foi abordado neste artigo, é uma opção muito melhor para extrair / fornecer informações. Não só é fácil de usar, mas também fornece uma camada de segurança que, se usada corretamente, é impenetrável. 

Conclusão

Às vezes, é necessário executar consultas SQL diretas no Magento, no entanto, tenha cuidado! Os models estão lá por um motivo e fornecem uma camada de segurança. No caso de consultas SQL diretas você terá que adicionar manualmente.

Certifique-se de escapar de qualquer entrada do usuário e, quando possível, fique atento aos métodos do model! Se você não consegue manipular os models, considere usar Varien_Db_Select. Não vai impedir que você cometa erros. Mas irá adicionar uma camada de segurança quase impenetrável às suas consultas de banco de dados.

No meu caso acabei usando esta forma para atualizar a tabela de sales/orders. Precisava executar o código fora do magento pois era uma correção para um novo módulo. Este módulo conectava com outro banco, portanto o meio mais fácil foi executando o código de fora do Magento. Foi feito esta operação e rodou perfeitamente, os dados foram atualizados.

Referencias

Magento developers

Fishpig Magento

Posts Relacionados