Extensiones e Integraciones
Vamos ahora, en este último punto, a intentar ver brevemente los puntos del desarrollo de Magento mas orientados al desarrollo.
Magento Connect
Durante el curso ya hemos visto como trabajar con Magento Connect, como buscar, y como instalar las extensiones que necesitemos. Vale la pena, cuando necesitemos añadir alguna función a nuestra tienda, que primero realicemos una visita a Magento Connect.
Versiones y compatibilidades
Hay que tener en cuenta que no todas las extensiones son aplicables a todas las instalaciones de Magento. Cambios en el API pueden hacer que las extensiones no funcionen en absoluto, o no lo hagan correctamente. Como norma instalaremos extensiones que estén indicada para nuestra versión de Magento.
Introducción al desarrollo de extensiones Magento
La creación de extensiones para Magento es un proceso bastante más complejo que la creación de temas. Afortunadamente podemos instalar, vía Magento Connect, la extensión Module Creator de Daniel Nitz. Esta extensión crea la base necesaria para generar nuestros modulos de Magento.
Una vez instalada la extensión podemos acceder a ella a través de la URL:
http://www.localhost.com/proyecto-mg/moduleCreator/
Y utilizando nuestro usuario y contraseña, los mismos del panel de administración, veremos una pantalla similar a la siguiente:
De momento solo tenemos un esqueleto de plantilla, Blank News Module, el Namespace que queramos utilizar, el nombre del modulo, el interface y el tema que hay en uso. Haciendo clic en el botón create se generarán los ficheros base del modulo:
app/etc/modules/CURSO_Noticias.xml
app/code/local/CURSO/Noticias/Block/Noticias.php
app/code/local/CURSO/Noticias/controllers/IndexController.php
app/code/local/CURSO/Noticias/etc/config.xml
app/code/local/CURSO/Noticias/Model/Noticias.php
app/code/local/CURSO/Noticias/Model/Mysql4/Noticias.php
app/code/local/CURSO/Noticias/Model/Mysql4/Noticias/Collection.php
app/code/local/CURSO/Noticias/Model/Status.php
app/code/local/CURSO/Noticias/sql/noticias_setup/mysql4-install-0.1.0.php
app/design/frontend/default/blank_seo/layout/noticias.xml
app/design/frontend/default/blank_seo/template/noticias/noticias.phtml
app/code/local/CURSO/Noticias/Block/Adminhtml/Noticias.php
app/code/local/CURSO/Noticias/Block/Adminhtml/Noticias/Edit.php
app/code/local/CURSO/Noticias/Block/Adminhtml/Noticias/Grid.php
app/code/local/CURSO/Noticias/Block/Adminhtml/Noticias/Edit/Form.php
app/code/local/CURSO/Noticias/Block/Adminhtml/Noticias/Edit/Tabs.php
app/code/local/CURSO/Noticias/Block/Adminhtml/Noticias/Edit/Tab/Form.php
app/code/local/CURSO/Noticias/controllers/Adminhtml/NoticiasController.php
app/code/local/CURSO/Noticias/Helper/Data.php
app/design/adminhtml/default/blank_seo/layout/noticias.xml
Funciones importantes a la hora de crear extensiones
Vamos ahora a ver un poco por encima los diferentes métodos que nos ayudarán a trabajar con las extensiones.
getModel
Este método creará una instancia del modelo que le pasemos como parámetro, por ejemplo:
$noticia = Mage::getModel(‘noticias/noticias’);
Esto cargará el modelo noticias, y luego podemos trabajar con el, por ejemplo cargando el elemento cuyo id es 1:
$noticia->load(1);
Y luego mostrando sus contenidos:
echo ‘Title: ‘. $noticia->getTitle();
echo ‘Content: ‘ . $noticia->getContent();
Esto podemos hacerlo directamente en el template, app → design → frontend → default → f002 → template → noticias → noticias.phtml:
$noticia = Mage::getModel(‘noticias/noticias’);
$noticia->load(1);
echo ‘Title: ‘. $noticia->getTitle();
echo ‘Content: ‘ . $noticia->getContent();
O en caso de que lo hicieramos desde el controlador app → code → local → Curso → Noticias → controllers → IndexController.php:
$noticia = Mage::getModel(‘noticias/noticias’);
$noticia->load(1);
Mage::register(‘noticia_1′, $noticia);
Podemos ver como usamos Mage::register para “registrar” una variable, y que esté disponible posteriormente, por ejemplo en noticias.phtml:
$noticia = Mage::registry(‘noticia_1′);
echo $noticia->getTitle();
La variable la cogemos del registro con Mage::registry, y la podemos utilizar con normalidad, cada campo de la tabla accesible desde su método getter, en este caso getTitle().
Para hacerlo todo aún más correcto podríamos incluso utilizar nuestro modelo app → code → local → curso → noticias → model → noticias.php, ahí podemos añadir un nuevo método:
public function getNoticia($id = 0)
{
$noticia = $this->load($id);
return $noticia;
}
Hay que notar que dentro del modelo usamos $this para hacer referencia al propio modelo. El modelo está directamente relacionado con la tabla que lleve su propio nombre. Después en el controlador haríamos lo siguiente:
$noticiam = Mage::getModel(‘noticias/noticias’);
Mage::register(‘noticia_3′, $noticiam->getNoticia(1));
Y en el template:
$noticia = Mage::registry(‘noticia_3′);
echo $noticia->getTitle();
Repaso por los ficheros más importantes
Una vez tenemos todos los ficheros creados, vamos a examinarlos más en detalle. Empezaremos en app → etc → modules, ahí veremos un fichero llamado CURSO_Noticias.xml, desde este fichero podemos activar, o desactivar nuestro modulo:
<config>
<modules>
<CURSO_Noticias>
<active>true</active>
<codePool>local</codePool>
</CURSO_Noticias>
</modules>
</config>
Modificando la etiqueta active, a false, desactivará nuestro modulo y no se utilizará. El siguiente paso será examinar el controlador de nuestro modulo. El controlador es donde está situada toda la lógica de programación de nuestro modulo. Este fichero está situado en app → code → local → CURSO → Noticias → controllers, lo veremos bajo el nombre de IndexController.php
Por defecto el modulo viene rellenado con datos de ejemplo, comentados, lo descomentaremos de manera que tenga el siguiente aspecto:
<?php
class CURSO_Noticias_IndexController extends Mage_Core_Controller_Front_Action
{
public function indexAction()
{
/*
* Load an object by id
* Request looking like:
* http://site.com/noticias?id=15
* or
* http://site.com/noticias/id/15
*/
$noticias_id = $this->getRequest()->getParam(‘id’);
if($noticias_id != null && $noticias_id != ”) {
$noticias = Mage::getModel(‘noticias/noticias’)->load($noticias_id)->getData();
} else {
$noticias = null;
}
/*
* If no param we load a the last created item
*/
if($noticias == null) {
$resource = Mage::getSingleton(‘core/resource’);
$read= $resource->getConnection(‘core_read’);
$noticiasTable = $resource->getTableName(‘noticias’);
$select = $read->select()
->from($noticiasTable,array(‘noticias_id’,'title’,'content’,'status’))
->where(‘status’,1)
->order(‘created_time DESC’) ;
$noticias = $read->fetchRow($select);
}
Mage::register(‘noticias’, $noticias);
$this->loadLayout();
$this->renderLayout();
}
}
Este controlador extiende a Mage_Core_Controller_Front_Action, y, en definitiva, al controlador de Zend Framework. De hecho, podemos ver métodos propios del Zend Framework:
$this->getRequest()->getParam(‘id’);
Así como métodos propios de Magento:
Mage::getModel(‘noticias/noticias’)->load($noticias_id)->getData();
Este controlador funcionará como controlador del frontend, pero también necesitaremos un controlador para la zona de administración, app → code → local → CURSO → Noticias → controllers → Adminhtml será el fichero llamado NoticiasController.php Este controlador permitirá gestionar las acciones de creación, edición, y borrado de noticias.
El siguiente archivo importante es config.xml, donde se guarda la configuración general de nuestro modulo, lo podemos encontrar en app → code → local → CURSO → Noticias → etc
Además del fichero de configuración, tambien podemos utilizar helpers, para modificar la presentación del modulo. Los helpers se situan en app → code → local → CURSO → Noticias → Helper, y de momento tendremos uno, vacío, llamado Data.php
Ahora que hemos visto el controlador, ficheros de configuración etc el siguiente paso es el modelo, los modelos realizan el acceso a datos, es decir, trabajan entre el controlador y nuestra base de datos. Se generan en app → code → local → CURSO → Noticias → Model, por ejemplo Noticias.php
El modelo, sin embargo, solo realiza el acceso a datos, para crear nuestra tabla en base de datos, existe un fichero llamado mysql4-install-0.1.0.php situado en app → code → local → CURSO → Noticias → sql → noticias_setup, en ese fichero podemos ver la tabla que se generará, así como sus campos.
Por último necesitamos una plantilla para mostrar los contenidos, lo crearemos en app → design -> frontend → default → blank_seo → template → noticias , por ejemplo noticias.phtml Hay que notar la relación de nuestro modulo, con nuestra plantilla. Junto con la plantilla necesitaremos crear el bloque, en app → code → local → CURSO → Noticias → Block y llamado Noticias.php
En última instancia podremos acceder a nuestro modulo en esta URL:
http://www.localhost.com/proyecto-mg/noticias
Así como desde el panel de administración:
En caso de que el panel de administración no funcione
Dependiendo de la versión del module creator que estemos utilizando puede ser que al intentar acceder a la gestión de noticias desde el panel de administración, solo veamos una pantalla en blanco. Si esto sucede, para corregirlo iríamos a app → code → local → Curso → noticias → controllers → Adminhtml → NoticiasController.php y modificaremos el siguiente método:
public function indexAction() {
$this->_initAction()
->renderLayout();
}
Para que quede tal que así:
public function indexAction() {
$this->_initAction()
->_addContent($this->getLayout()->createBlock(‘noticias/adminhtml_noticias’))
->renderLayout();
}
Creación de un widget
Los widgets se añadieron en la versión 1.4 de Magento, y nos posibilitan añadir pequeños bloques en las páginas CMS sin necesidad de tener conocimientos de programación, en este ejemplo vamos a crear un widget básico. El widget, como el resto de módulos necesita de una estructurá de carpetas determinada. Vamos a crear esta carpeta en app → code → local → Curso → Cursowidget y dentro crearemos las siguientes carpetas:
-
Block
-
etc
-
Helper
-
Model
El siguiente paso es crear un fichero xml dentro de app → etc → modules, CURSO_Cursowidget.xml, con el siguiente contenido:
<config>
<modules>
<Curso_Cursowidget>
<active>true</active>
<codePool>local</codePool>
<depends>
<Mage_Cms />
</depends>
</Curso_Cursowidget>
</modules>
</config>
Este el fichero que le indicará a Magento que nuestra instalación cuenta con un modulo más, es igual que los que hemos utilizado hasta ahora excepto por:
<depends>
<Mage_Cms />
</depends>
Que indica su dependencia con Mage/Cms. Después dentro de app → code → local → Curso → Cursowidget → etc crearemos el fichero config.xml:
<?xml version=”1.0″?>
<config>
<modules>
<Curso_Cursowidget>
<version>0.0.1</version>
</Curso_Cursowidget>
</modules>
<global>
<helpers>
<cursowidget>
<class>Curso_Cursowidget_Helper</class>
</cursowidget>
</helpers>
<blocks>
<cursowidget>
<class>Curso_Cursowidget_Block</class>
</cursowidget>
</blocks>
<models>
<cursowidget>
<class>Curso_Cursowidget_Model</class>
</cursowidget>
</models>
</global>
</config>
El siguiente fichero que crearemos será app → code → local → Curso → Cursowidget → etc → widget.xml:
<?xml version=”1.0″?>
<widgets>
<cursowidget_list type=”cursowidget/list” translate=”name description” module=”cursowidget”>
<name>Widget de prueba</name>
<description>Añade un texto</description>
<parameters>
<enabled_services>
<label>Banners</label>
<visible>1</visible>
<required>1</required>
<type>multiselect</type>
<source_model>cursowidget/services</source_model>
</enabled_services>
<template translate=”label”>
<label>Plantilla a utilizar</label>
<visible>1</visible>
<required>1</required>
<type>select</type>
<values>
<text translate=”label”>
<value>cursowidget/list.phtml</value>
<label>Una opcion</label>
</text>
<icons translate=”label”>
<value>cursowidget/list.phtml</value>
<label>Otra opcion</label>
</icons>
</values>
</template>
</parameters>
</cursowidget_list>
</widgets>
Crearemos tambien el fichero app → code → local → Curso → Cursowidget → Helper → Data.php:
<?php
class Curso_Cursowidget_Helper_Data extends Mage_Core_Helper_Abstract
{
}
Despues crearemos el fichero app → code → local → curso → cursowidget → model → Services.php:
<?php
class Curso_Cursowidget_Model_Services
{
public function toOptionArray()
{
return array(
array(‘value’ => ’1′, ‘label’ => ‘Banner 1′),
array(‘value’ => ’2′, ‘label’ => ‘Banner 2′)
);
}
}
Despues app → code → local → curso → cursowidget → block → List.php:
<?php
class Curso_Cursowidget_Block_List extends Mage_Core_Block_Template implements Mage_Widget_Block_Interface
{
/**
* A model to serialize attributes
*
* @var Varien_Object
*/
protected $_serializer = null;
/**
* Constructor
*/
protected function _construct()
{
$this->_serializer = new Varien_Object();
parent::_construct();
}
/**
* Produce links list and render it as html
*
* @return string
*/
protected function _toHtml()
{
$html = ”;
$config = $this->getData(‘enabled_services’);
if (empty($config)) {
return $html;
}
$services = explode(‘,’, $config);
$list = array();
foreach ($services as $service) {
$item = $this->_generateServiceLink($service);
if ($item) {
$list[] = $item;
}
}
$this->assign(‘list’, $list);
return parent::_toHtml();
}
protected function _generateServiceLink($service)
{
switch ($service) {
case ’1′:
$item = “Banner 1″;
break;
case ’2′:
$item = “Banner 2″;
break;
default:
return array();
break;
}
return $item;
}
}
Y por ultimo app → design → frontend → default → f002 → template → cursowidget → list.phtml:
<?php
foreach($list as $item){
echo $item;
}
?>
Creación de un modulo de envio (Shipping module)
En el siguiente ejemplo vamos a ver los pasos básicos para crear un modulo de envio propio. El primer paso será crear una carpeta dentro de app → code → local → Curso que se llame Enviosm, con lo cual la ruta completa quedará app → code → local → Curso → Enviosm
Dentro de esta carpeta tendremos dos más, etc y model, y dentro de model, carrier:
app → code → local → Curso → Enviosm
-
-
etc
-
Model
-
Carrier
-
-
Dentro de la carpeta etc crearemos un fichero llamado config.xml, con el siguiente contenido:
<?xml version=”1.0″?>
<config>
<modules>
<Curso_Enviosm>
<version>1.0.0</version>
<depends>
<Mage_Shipping />
</depends>
</Curso_Enviosm>
</modules>
<global>
<models>
<Enviosm>
<class>Curso_Enviosm_Model</class>
</Enviosm>
</models>
<resources>
<Enviosm_setup>
<setup>
<module>Curso_Enviosm</module>
</setup>
<connection>
<use>core_setup</use>
</connection>
</Enviosm_setup>
</resources>
<sales>
<shipping>
<carriers>
<enviosm>
<class>Curso_Enviosm_Model_Carrier_ShippingMethod</class>
</enviosm>
</carriers>
</shipping>
</sales>
</global>
<default>
<carriers>
<enviosm>
<active>1</active>
<sallowspecific>1</sallowspecific>
<cutoff_cost>50</cutoff_cost>
<model>curso_enviosm_model_carrier_shippingmethod</model>
<name>Envios Magento</name>
<name>Envios Magento</name>
<specificerrmsg>This shipping method is currently unavailable. If you would like to ship using this shipping method, please contact us.</specificerrmsg>
</enviosm>
</carriers>
</default>
</config>
El siguiente fichero que crearemos será system.xml, también dentro de la carpeta etc:
<?xml version=”1.0″?>
<config>
<sections>
<carriers>
<groups>
<enviosm translate=”label” module=”shipping”>
<label>Envios Magento</label>
<frontend_type>text</frontend_type>
<sort_order>13</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<fields>
<active translate=”label”>
<label>Enabled</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_yesno</source_model>
<sort_order>1</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</active>
<handling_type translate=”label”>
<label>Calculate Handling Fee</label>
<frontend_type>select</frontend_type>
<source_model>shipping/source_handlingType</source_model>
<sort_order>10</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</handling_type>
<handling_action translate=”label”>
<label>Handling Applied</label>
<frontend_type>select</frontend_type>
<source_model>shipping/source_handlingAction</source_model>
<sort_order>11</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</handling_action>
<handling_fee translate=”label”>
<label>Handling fee</label>
<frontend_type>text</frontend_type>
<sort_order>12</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</handling_fee>
<sort_order translate=”label”>
<label>Sort order</label>
<frontend_type>text</frontend_type>
<sort_order>100</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</sort_order>
<title translate=”label”>
<label>Title</label>
<frontend_type>text</frontend_type>
<sort_order>2</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</title>
<sallowspecific translate=”label”>
<label>Ship to applicable countries</label>
<frontend_type>select</frontend_type>
<sort_order>90</sort_order>
<frontend_class>shipping-applicable-country</frontend_class>
<source_model>adminhtml/system_config_source_shipping_allspecificcountries</source_model>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</sallowspecific>
<specificcountry translate=”label”>
<label>Ship to Specific countries</label>
<frontend_type>multiselect</frontend_type>
<sort_order>91</sort_order>
<source_model>adminhtml/system_config_source_country</source_model>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</specificcountry>
<showmethod translate=”label”>
<label>Show method if not applicable</label>
<frontend_type>select</frontend_type>
<sort_order>92</sort_order>
<source_model>adminhtml/system_config_source_yesno</source_model>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</showmethod>
<specificerrmsg translate=”label”>
<label>Displayed Error Message</label>
<frontend_type>textarea</frontend_type>
<sort_order>80</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</specificerrmsg>
</fields>
</enviosm>
</groups>
</carriers>
</sections>
</config>
Y por último crearemos el fichero Model -> Carrier -> ShippingMethod.php, dentro de la carpeta Model -> Carrier, será este fichero el que gestione la lógica de nuestro modulo de envio:
<?php
class Curso_Enviosm_Model_Carrier_ShippingMethod extends Mage_Shipping_Model_Carrier_Abstract
{
protected $_code = ‘enviosm’;
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
if (!$this->getConfigData(‘active’)) {
Mage::log(‘The ‘ . $this->_code . ‘my shipping module is not active.’);
return false;
}
$handling = $this->getConfigData(‘handling’);
$result = Mage::getModel(‘shipping/rate_result’);
foreach ($response as $method) {
$rMethod = Mage::getModel(‘shipping/rate_result_method’);
$method->setCarrier($this->_code);
$method->setCarrierTitle($this->getConfigData(‘title’));
$method->setMethod($method['code']);
$method->setMethodTitle($method['title']);
$method->setCost($method['amount']);
$method->setPrice($method['amount'] + $handling);
$result->append($method);
}
return $result;
}
}
Una vez que tenemos todo esto, nos queda generar el fichero app -> etc -> modules -> CURSO_Enviosm.xml con el siguiente contenido:
<config>
<modules>
<Curso_Enviosm>
<active>true</active>
<codePool>local</codePool>
</Curso_Enviosm>
</modules>
</config>
Nos quedará activar el modulo en Sistema -> configuración -> avanzado -> avanzado
Y despues configurar sus opciones en Sistema -> configuración -> ventas -> metodos de envio
API de Magento
El desarrollo de extensiones de Magento involucra el uso de funciones ya existentes, que Magento nos proporciona a través de su API, para saber más sobre el API podemos visitar esta página, que realmente es una de las mejor documentadas de Magento:
http://www.magentocommerce.com/support/magento_core_api
Para poder trabajar con el api primero tendremos que permitir el acceso a los scripts al api, para ello iremos a Sistema → Servicios web → roles. Haremos clic en añadir nuevo rol. Lo llamaremos Acceso por ejemplo. Y en la pestaña de Recursos del rol elegiremos Acceso de recursos → Todos. Guardaremos el rol.
Luego iremos a Sistema → Servicios web → usuarios y haremos clic en Añadir nuevo usuario. En la pestaña info del usuario escribiremos los siguientes valores:
-
nombre del usuario → usu
-
nombre → usu
-
apellido → usu
- correo electronico → usu@gmail.com
-
api key → usu123
-
api key confirmation → usu123
-
la cuenta es → activo
Y en la pestaña rol del usuario elegiremos Acceso. Guardamos.
Para trabajar con el API de magento podemos utilizar dos protocolos:
-
SOAP
-
XML RPC
En este ejemplo vamos a usar SOAP, y para comprobar que esta activo, crearemos un fichero php que incluya el siguiente codigo:
<?php
phpinfo();
?>
Deberemos ver una imagen similar a la siguiente:
Y crearemos por ejemplo, en una carpeta separada de la de magento un fichero api.php:
<?php
$client = new SoapClient(‘http://www.localhost.com/proyecto-mg/api/soap/?wsdl’);
$session = $client->login(‘usu’, ‘usu123′);
/*Crear un usuario*/
/*
$customerInfo = array(
‘firstname’ => ‘First’,
‘lastname’ => ‘Last’,
‘email’ => ‘test@example.com’,
‘password_hash’ => md5(‘password’),
‘store_id’ => 0,
‘website_id’ => 0
);
$newCustomerId = $client->call($session, ‘customer.create’, array($customerInfo));
*/
/*Mostrar un cliente*/
/*
$customerId = 2;
$customerInfo = $client->call($session, ‘customer.info’, $customerId);
print var_dump($customerInfo);
*/
$customerId = 4;
$newCustomerInfo = array(
‘firstname’ => ‘Updated’,
‘lastname’ => ‘Customer’
);
$client->call($session,
‘customer.update’,
array($customerId, $newCustomerInfo)
);
$client->endSession($session);
?>
Herramientas
A la hora de trabajar con Magento, podemos hacer uso de un gran número de herramientas que nos faciliten el desarrollo. Ahora vamos a nombrar algunas de ellas.
XHTML / CSS
Todos los temas de Magento se crean utilizando una mezcla de XHTML, CSS, JavaScript y pequeñas llamadas a funciones de Magento. Realmente cualquier editor nos serviría para crear nuestras plantillas, desde editores simples como notepad++ ( http://notepad-plus-plus.org/ ), a grandes editores como Dreamweaver.
En cuanto a navegadores, Firefox ofrece un gran número de extensiones, como:
-
Firebug: https://addons.mozilla.org/es-es/firefox/addon/1843/
-
Barras de desarrollo
Y mucho más, con todo lo cual, nuestro desarrollo será más sencillo.
Magento y Zend Studio
El uso de un IDE como Zend Studio, con Magento, puede realmente ayudarnos con el desarrollo. Si bien para trabajar con temas no sería necesario, para desarrollar extensiones si sería de gran utilidad, aunque no cuenta con automatizaciones que generen extensiones, o su base, de forma automática.
Otra opción a tener en cuenta sería utilizar un IDE como NetBeans.
Magento y Zend Application Server
Si necesitamos que nuestra instalación de Magento funcione mejor y de forma más confiable, podemos instalar Magento sobre el Zend Application Server ( http://www.zend.com/en/solutions/packaged-php-applications/zend-server-magento ), esto nos permitirá mejorar el rendimiento de nuestra instalación de Magento, así como realizar diagnosticos de cuellos de botella y errores.
Categorías:


