Jump to content

Forma mas rápida de subir productos e imágenes a prestashop.


Recommended Posts

Lo más rápido es un CSV. Si quieres hacer un script también puedes, pero no es tarea sencilla, y al final igualmente vas a necesitar un archivo con la fuente de datos, sea CSV, sea XML o el formato que quieras. Muchas veces lo más sencillo es crear un script que adapte la fuente la datos a un formato importable directamente por Prestashop.

 No te aconsejo tampoco crear un script que "ataque" directamente a la base de datos de Prestashop, porque insertar productos puede tener más complicaciones de lo que parece a simple vista viendo las tablas (especialmente si tienen combinaciones). Si vas a hacerlo con un script, lo mejor es usar las clases propias de Prestashop para que funcione como debe y no tengas problemas luego.

Un buen punto de partida si decides crear tu propio script es mirar en /src/Core/Import, ahí puedes estudiar cómo se realiza la importación de los archivos CSV para hacer algo similar.

  • Like 1
Link to comment
Share on other sites

Muchas gracias por responder, ahora mismo lo tengo de esa manera (atacando las clases de prestashop), pero es muy lento, tengo subir muchos productos y agota el tiempo de ejecución de php de mi servidor. Alguna sugerencia.

Edited by jvlucas
Mayuscula al inicio. (see edit history)
Link to comment
Share on other sites

17 minutes ago, jvlucas said:

Muchas gracias por responder, ahora mismo lo tengo de esa manera (atacando las clases de prestashop), pero es muy lento, tengo subir muchos productos y agota el tiempo de ejecución de php de mi servidor. Alguna sugerencia.

Yo cuando he hecho algo parecido lo que he hecho para evitar los timeouts ha sido procesar solo un número determinado de productos en cada ejecución (por ejemplo, 50), y luego que el script se llame a sí mismo usando curl, pasando el número de último producto procesado, para que continúe a partir de ahí. Te pongo un ejemplo:

private function callNextStep($file, $continuePos)
{
    $key = sha1(_COOKIE_KEY_.'nombre_modulo');
    $url = $this->context->link->getModuleLink('nombre_modulo', 'nombre_controlador');
    $url.= '?action='.Tools::getValue('action').'&token='.$key.'&continue='.$continuePos.'&file='.urlencode($file);
    $cmd = 'curl -ssl -k -X GET "'.$url.'"';
    $cmd .= ' >/dev/null 2>&1 &'; //descartamos la respuesta

    exec($cmd, $output, $exit);
    return true;
}

Esto lo hacía dentro de un módulo que tenía un controlador para procesar las llamadas, pero si lo haces directamente con un simple script externo puedes adaptarlo igualmente.

Otra versión un poco más "elegante" (pero que al final acaba haciendo lo mismo):

protected function callNextStep($nextProductToProcess)
{
    $url = Tools::getHttpHost(true).__PS_BASE_URI__.'module/'.$this->module->name.'/xml?action=processProducts&key='.$this->module->secret_key;
    $url.= '&continue='.$nextProductToProcess;
    $this->curlCall($url);
}

public function curlCall($url)
{
    $curl = curl_init();                
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_USERAGENT, 'api');
    curl_setopt($curl, CURLOPT_TIMEOUT, 2); 
    curl_setopt($curl, CURLOPT_HEADER, 0);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
    curl_setopt($curl, CURLOPT_FORBID_REUSE, true);
    curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 2);
    curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT, 10); 
    curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    
    curl_exec($curl);
    $result = curl_getinfo($curl);
    curl_close($curl);
}

 

Edited by Prestafan33 (see edit history)
  • Thanks 1
Link to comment
Share on other sites

En 3/7/2020 a las 1:08 PM, Prestafan33 dijo:

Yo cuando he hecho algo parecido lo que he hecho para evitar los timeouts ha sido procesar solo un número determinado de productos en cada ejecución (por ejemplo, 50), y luego que el script se llame a sí mismo usando curl, pasando el número de último producto procesado, para que continúe a partir de ahí. Te pongo un ejemplo:


private function callNextStep($file, $continuePos)
{
    $key = sha1(_COOKIE_KEY_.'nombre_modulo');
    $url = $this->context->link->getModuleLink('nombre_modulo', 'nombre_controlador');
    $url.= '?action='.Tools::getValue('action').'&token='.$key.'&continue='.$continuePos.'&file='.urlencode($file);
    $cmd = 'curl -ssl -k -X GET "'.$url.'"';
    $cmd .= ' >/dev/null 2>&1 &'; //descartamos la respuesta

    exec($cmd, $output, $exit);
    return true;
}

Esto lo hacía dentro de un módulo que tenía un controlador para procesar las llamadas, pero si lo haces directamente con un simple script externo puedes adaptarlo igualmente.

Otra versión un poco más "elegante" (pero que al final acaba haciendo lo mismo):


protected function callNextStep($nextProductToProcess)
{
    $url = Tools::getHttpHost(true).__PS_BASE_URI__.'module/'.$this->module->name.'/xml?action=processProducts&key='.$this->module->secret_key;
    $url.= '&continue='.$nextProductToProcess;
    $this->curlCall($url);
}

public function curlCall($url)
{
    $curl = curl_init();                
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_USERAGENT, 'api');
    curl_setopt($curl, CURLOPT_TIMEOUT, 2); 
    curl_setopt($curl, CURLOPT_HEADER, 0);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
    curl_setopt($curl, CURLOPT_FORBID_REUSE, true);
    curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 2);
    curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT, 10); 
    curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    
    curl_exec($curl);
    $result = curl_getinfo($curl);
    curl_close($curl);
}

 

Interesante que haga una llamada CURL cuando termine. gracias

Yo suelo añadirlo a un cron y verifico el tiempo de ejecución configurado en el PHP y lo paro 5 segundos antes,

Al principio compruebo si el ultimo producto tiene imagen (en mi código siempre añado las imágenes al final) y si no tiene, elimino ese producto, ya que no se ha añadido correctamente y continuo añadiendo.

Lo de ultima posición, seria interesante si fuera siempre el mismo fichero, yo compruebo si existe el producto del CSV con la referencia o añadiendo en una tabla especial el dato del CSV y cual es el ID de prestashop, ya que el fichero CSV puede cambiar entre un dia y otro

 

 

Edited by gusman126 (see edit history)
Link to comment
Share on other sites

30 minutes ago, gusman126 said:

Lo de ultima posición, seria interesante si fuera siempre el mismo fichero, yo compruebo si existe el producto del CSV con la referencia o añadiendo en una tabla especial el dato del CSV y cual es el ID de prestashop, ya que el fichero CSV puede cambiar entre un dia y otro

Sí, el código del ejemplo que he puesto lo utilizo para importar ficheros grandes de productos y poder dividir el procesamiento de cada fichero (el mismo) en lotes. Lo que hace mi controlador cuando es llamado es comprobar si se le ha pasado la variable "continue" en la URL, y si es así, "saltarse" líneas de producto del fichero hasta llegar al número que se le ha pasado, que es el último procesado en la llamada anterior. Y luego continuar importando desde ahí.

Claro, al principio tienes que probar un poco cuánto se tarda en procesar cada producto, el timeout que tienes en el servidor y calcular cuántos productos puedes procesar antes de tener que dar el salto a la siguiente llamada. Y ser siempre bastante conservador, porque dependiendo de la carga del servidor puede que en unos momentos te pueda importar 50 productos en un minuto y en otros 30 solamente.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...