Icono del sitio Daniel Ruiz

Prestashop: Web service: aprende a crear una nueva función 3

Hola!

Sois varios los que me habéis preguntado sobre mis antiguos artículos (el primero y el segundo).

Vamos sobre el tema de los servicios web de Prestashop.

Recordemos que la estructura de ficheros que tenemos después de los otros artículos es esta:

 

 

Antes de empezar

Una aclaración: la api de Prestashop ya nos devuelve el objeto producto con las combinaciones pero con el identificador de la combinación:

http://url_tienda/api/products/1

            <combinations nodeType="combination" api="combinations">
                <combination xlink:href="http://localhost/PS16/api/combinations/1">
                    <id>
                        <![CDATA[1]]>
                    </id>
                </combination>
                <combination xlink:href="http://localhost/PS16/api/combinations/2">
                    <id>
                        <![CDATA[2]]>
                    </id>
                </combination>
                <combination xlink:href="http://localhost/PS16/api/combinations/3">
                    <id>
                        <![CDATA[3]]>
                    </id>
                </combination>
                <combination xlink:href="http://localhost/PS16/api/combinations/4">
                    <id>
                        <![CDATA[4]]>
                    </id>
                </combination>
                <combination xlink:href="http://localhost/PS16/api/combinations/5">
                    <id>
                        <![CDATA[5]]>
                    </id>
                </combination>
                <combination xlink:href="http://localhost/PS16/api/combinations/6">
                    <id>
                        <![CDATA[6]]>
                    </id>
                </combination>
            </combinations>

Esta vez crearemos una función para que nos devuelva datos de los productos de nuestra tienda: devolveremos todos los productos de nuestra tienda con sus combinaciones completas.

Manos a la obra

Parar este artículo vamos a crear clases nuevas que nos ayuden a conseguir el objetivo y, además, ayudarnos a entender los servicios web de Prestashop.

Llamaremos a esta funcionalidad extensión de la funcionalidad de un producto: ProductExtension (¿original no? :))

Queremos que nuestra URL sea así: http://url_tienda/api/productextension/funcion1 y nos devuelva un xml (formato por defecto ya que podemos hacer que nos devuelva los datos en JSON) con todos los productos de nuestra tienda con las combinaciones completas.

Queremos que nuestra clase solamente esté disponible para los servicios web y no haya ningún problema con ningún módulo ni con el sitio en general. Esto significa que no sobreescribimos la clase original Product sino que creamos otra clase totalmente distinta. Es decir no creamos la clase con el fichero /overrides/classes/Product.php.

class Product extends ProductCore
{

Si tenéis alguna duda de lo que estoy hablando leeros mis antiguos posts donde hablo sobre los overrides en Prestashop.

Creando nuestra clase ProductExtension

Ahí va todo el código de la clase. La explicaré a continuación.

class ProductExtension extends ProductCore
{
	public function __construct(
		$id_product = null,
		$full = false,
		$id_lang = null,
		$id_shop = null,
		Context $context = null
	) {

		$this->webserviceParameters['associations']['combinations']['fields'] = array_merge(
			$this->webserviceParameters['associations']['combinations']['fields'],
			array(
				'id_product' =>        array('required' => true),
				'location' =>            array('required' => true),
				'ean13' =>                array('required' => true),
				'upc' =>                array('required' => true),
				'quantity' =>            array('required' => true),
				'reference' =>            array('required' => true),
				'supplier_reference' => array('required' => true),
				'wholesale_price' =>    array('required' => true),
				'price' =>                array('required' => true),
				'ecotax' =>            array('required' => true),
				'weight' =>            array('required' => true),
				'unit_price_impact' =>    array('required' => true),
				'minimal_quantity' =>    array('required' => true),
				'default_on' =>        array('required' => true),
				'available_date' =>    array('required' => true)
			)
		);

		parent::__construct( $id_product, $full, $id_lang, $id_shop, $context );
	}

	public function getWsCombinations()
	{
		$result = Db::getInstance()->executeS(
			'SELECT pa.`id_product_attribute` as id, pa.*
			FROM `'._DB_PREFIX_.'product_attribute` pa
			'.Shop::addSqlAssociation('product_attribute', 'pa').'
			WHERE pa.`id_product` = '.(int)$this->id
		);

		return $result;
	}
}

 

Lo primero que sorprende es que extendemos esta clase de ProductCore y esto es porque queremos todo lo que ya tiene la clase producto con nuestras modificaciones:

Declarar nuestra clase de servicio web manejada

Acordaos que hay que añadir la declaración de este objeto en los servicios web de Prestashop. Esto se hace a través de la clase WebServiceRequest. La deberemos sobrecargar (como ya aprendimos)  y modificar la función getResources():

$resources['productextension'] = array('description' => 'Mis funciones de producto', 'specific_management' => true);

Creando nuestra clase WebserviceSpecificManagementProductextension

Esta clase es necesaria para poder manejar toda nuestra llamada, entrada y salida, comprobación de parámetros, errores, etc. Aquí la tenemos (si tenéis dudas de esto revisar el anterior artículo):

<?php

class WebserviceSpecificManagementProductextensionCore implements WebserviceSpecificManagementInterface
{

	/** @var WebserviceOutputBuilder */
	protected $objOutput;
	protected $output;

	/** @var WebserviceRequest */
	protected $wsObject;

	protected $validateFunctions = array( 'funcion1' );

	public function setObjectOutput(WebserviceOutputBuilderCore $obj)
	{
		$this->objOutput = $obj;
		return $this;
	}

	public function setWsObject(WebserviceRequestCore $obj)
	{
		$this->wsObject = $obj;
		return $this;
	}

	public function getWsObject()
	{
		return $this->wsObject;
	}
	public function getObjectOutput()
	{
		return $this->objOutput;
	}

	public function manage()
	{

		if (count($this->wsObject->urlSegment) < 2)
			throw new WebserviceException('Error', array(100, 400));

		if ( ! in_array( $this->wsObject->urlSegment[1], $this->validateFunctions ) )
			throw new WebserviceException('Error', array(100, 400));


		$funcion = $this->wsObject->urlSegment[1];
		$params = array_slice( $this->wsObject->urlSegment, 2);

		$this->objects = $this->{$funcion} ( $params );
	}

	public function getContent()
	{
		$type_of_view = WebserviceOutputBuilder::VIEW_DETAILS;
		$this->fieldsToDisplay = 'full';
		$this->schemaToDisplay = null;
		$this->depth = 0;
		$this->objects['empty'] = new ProductExtension();
		return $this->objOutput->getContent($this->objects, $this->schemaToDisplay, $this->fieldsToDisplay, $this->depth, $type_of_view);
	}

	private function funcion1 ( $params ) {
		/** @var ProductExtension $tmp */
		$tmp = new ProductExtension();

		$sqlObjects = $tmp->getWebserviceObjectList();
		$objects = array();

		if ($sqlObjects) {
			foreach ($sqlObjects as $sqlObject) {
				$objects[] = new ProductExtension((int)$sqlObject['id_product']);
			}

			return $objects;
		}
	}
}

Lo primero el nombre de esta clase: WebserviceSpecificManagementProductextensionCore debe llamarse con la siguiente estructura: WebserviceSpecificManagementKKKKKCore (donde KKKKK = nombre de nuestro servicio web con la primera letra en mayúscula). El nombre de nuestro servicio web es el que hemos usado para declararlo en getResources(), concretamente, 'productextension'

Las funciones interesantes aquí son la getContent() y la funcion1.

 

Resumen

Y eso es todo. Al llamar a la api (recordad activarla desde el backend de prestashop) nos devolverá todos los productos pero la parte de combinaciones en vez de darnos solamente los identificadores de estos, tendremos todos los campos de las combinaciones.

¿Qué os parece?

Si tenéis alguna duda no olvidéis que tenéis una caja de comentarios para ello xD

Un saludo!

Salir de la versión móvil