PHP

PHP: usando CURL para visitar servidores web

2018-05-23 - Categorías: General / GNU/Linux / PHP
Websites

Continuando con el post anterior, traigo otro code-kata, o HOWTO, para hacer ping a una web, para empezar. Digo para empezar, porque esto no es más que el comienzo de una serie de acciones muy potentes sobre servidores web. Así podemos interactuar con un sitio web automática y remotamente. Este es uno de los mecanismos básicos de comunicación entre sistemas informáticos. Es decir, esto se puede reutilizar para que una web se comunique con otra web, con otro sistema informático, leyendo información o enviándola.

Para esto vamos a usar el gran CURL, que va muy bien para trabajar con el protocolo de las webs. Aunque como reza en su web, es compatible con muchos otros protocolos:

DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, Telnet and TFTP. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, HTTP/2, cookies, user+password authentication (Basic, Plain, Digest, CRAM-MD5, NTLM, Negotiate and Kerberos), file transfer resume, proxy tunneling and more..

Esta forma de hacer un simple ping web se puede escalar todo lo que quieras. Es decir, de esta forma es como trabajan internamente los módulos de métodos de pago, envío/lectura de feeds, las APIs de los CMSs, por ejemplo. Las acciones que se ejecutan mediante la comunicación con APIs sobre HTTP/HTTPS. Y claro, cómo no, para las archiconocidas y tan queridas API REST sobre HTTP. Todas estas acciones tienen un origen (cliente) y un destino (servidor).

Así pues, vamos a complicar el ejemplo anterior..

Instalando CURL

Vamos a usar en este caso CURL, que es una herramienta del sistema operativo que podemos usar desde PHP. Si estás en GNU/Linux, puedes instalar tanto CURL como el módulo de PHP que lo usa así:

sudo apt-get install curl php7.2-curl

Si estás en Windows, Mac, o cualquier otro sistema operativo tendrás que ir a:

https://curl.haxx.se/download.html

..y seguir las instrucciones.

Primera petición web

Así un ping sencillo queda de la siguiente forma:

<?php

$curlHandler = curl_init('jnjsite.com');
curl_exec($curlHandler);

Si ejecutamos esto desde línea de comandos veremos algo tal que así:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://jnjsite.com/">here</a>.</p>
</body></html>

El contenido de la web se está pintando por pantalla: jnjsite.com te invita a redirigirte a https://jnjsite.com que es la versión segura de la web.

Viendo información de la respuesta

Para esto podemos modificar el script anterior y sacamos mucha información de la respuesta:

<?php

$curlHandler = curl_init('jnjsite.com');
$response = curl_exec($curlHandler);

var_dump(curl_getinfo($curlHandler));

curl_close($curlHandler);

Ejecutando esto desde línea de comandos veremos por pantalla mucha más información. En concreto el siguiente array:

array(26) {
‘url’ =>
string(19) «https://jnjsite.com/»
‘content_type’ =>
string(29) «text/html; charset=iso-8859-1»
‘http_code’ =>
int(301)
‘header_size’ =>
int(254)
‘request_size’ =>
int(50)
‘filetime’ =>
int(-1)
‘ssl_verify_result’ =>
int(0)
‘redirect_count’ =>
int(0)
‘total_time’ =>
double(0.131197)
‘namelookup_time’ =>
double(0.004185)
‘connect_time’ =>
double(0.067574)
‘pretransfer_time’ =>
double(0.067664)
‘size_upload’ =>
double(0)
‘size_download’ =>
double(228)
‘speed_download’ =>
double(1740)
‘speed_upload’ =>
double(0)
‘download_content_length’ =>
double(228)
‘upload_content_length’ =>
double(-1)
‘starttransfer_time’ =>
double(0.131118)
‘redirect_time’ =>
double(0)
‘redirect_url’ =>
string(20) «https://jnjsite.com/»
‘primary_ip’ =>
string(12) «52.31.12.158»
‘crtinfo’ =>
array(0) {}
‘primary_port’ =>
int(80)
‘local_ip’ =>
string(13) «192.168.0.221»
‘local_port’ =>
int(48976)
}

En este caso nos está pidiendo hacer una redirección 301 a la web con HTTPS. En teoría deberíamos de seguir esta redirección. Así que..

Siguiendo redirecciones

Modificando el script anterior, tenemos haciendo las redirecciones lo siguiente:

<?php

$curlHandler = curl_init('jnjsite.com');
$response = curl_exec($curlHandler);

while(curl_getinfo($curlHandler)['http_code'] >= 300
and curl_getinfo($curlHandler)['http_code'] < 400){
    // new URL to be redirected
    curl_setopt($curlHandler, CURLOPT_URL, curl_getinfo($curlHandler)['redirect_url']);
    $response = curl_exec($curlHandler);
}
var_dump(curl_getinfo($curlHandler));

curl_close($curlHandler);

Ejecutamos, y revisando por pantalla el resultado tendremos que finalmente se paran las redirecciones en https://jnjsite.com/ con un código de respuesta 200. He marcado en negrita lo nuevo con respecto al script anterior para redirigir hasta la página de destino.

Terminando

Para dejarlo limpio el script, sólo quedaría comprobar finalmente si la página ha dado un código OK de respuesta. Marco en negrita lo nuevo:

<?php

$curlHandler = curl_init('jnjsite.com');
curl_setopt($curlHandler, CURLOPT_RETURNTRANSFER, true);
curl_exec($curlHandler);

while (curl_getinfo($curlHandler)['http_code'] >= 300
and curl_getinfo($curlHandler)['http_code'] < 400) {
    // new URL to be redirected
    curl_setopt($curlHandler, CURLOPT_URL, curl_getinfo($curlHandler)['redirect_url']);
    curl_exec($curlHandler);
}

if (curl_getinfo($curlHandler)['http_code'] >= 200
and curl_getinfo($curlHandler)['http_code'] < 300) {
    echo 'OK'.PHP_EOL;
} else {
    echo 'KO'.PHP_EOL;
}

curl_close($curlHandler);

A partir de aquí sólo queda hacer las acciones que consideres si tienes un OK o un KO.


PHP: cómo hacer un web ping

2018-05-18 - Categorías: General / GNU/Linux / PHP
Websites

Una tarea bastante importante a la hora de posicionar una página web es asegurarte de que sigues online. Si has contratado el alojamiento a una empresa no tendrás que preocuparte mucho por el estado del sistema operativo del servidor. Pero hay otros aspectos aparte del servidor que necesitan de tu atención. Puedes pensar que una página web basta con montarla con un buen CMS, que puedes dejarla online y ahí seguirá porque no hay razón para que deje de funcionar. Pues nada más lejos de la realidad, cuantas más cosas tenga tu web, más cosas pueden fallar.

Es decir, si tienes una página artesanal de un único fichero estático es difícil que deje de funcionar. Pero si tienes un CMS, quizá un WordPress, Prestashop, Drupal o Magento.. ya empiezas a tener más elementos que mantener. Los módulos pueden ser inestables, pueden engancharse las arañas de los buscadores, usuarios que llegan a bugs involuntariamente, etcétera.. No digamos ya si tienes muchas visitas que generan contenido dinámicamente.

Las páginas web son como los coches, necesitan un mantenimiento, unas revisiones. Sino, tarde o temprano, dejarán de funcionar. Así que si quieres curarte en salud, puedes tener un sencillo script que compruebe si sigue online una web.

Continuar leyendo..

Magento 1: obteniendo el margen de beneficio de las ventas

2018-05-10 - Categorías: Magento / PHP
Magento margen de beneficios

Estos últimos días me han pedido sacar informes de un Magento. Ha sido muy interesante porque no me esperaba tener esta información en el CMS, pero sí, ahí estaba.

Resulta que Magento viene con un atributo de coste de los productos, que es de sistema. Dicho atributo de producto tiene el código cost. Además, en la información que se guarda en cada pedido tenemos el precio original, este coste del sistema en el momento de la venta, y más información. Con esto podremos saber el margen de beneficio que hubo en el momento de la venta.

Es importante notar que supongo que ya usas el atributo de coste del sistema, o que tienes un ERP enganchado a Magento que te lo está manteniendo actualizado con cada pedido de compra.

Continuar leyendo..

Symfony: creando landings con formularios, segunda parte

2018-05-08 - Categorías: PHP / Symfony
Landing pages con Symfony

En el post anterior escribí sobre cómo crear una landing page rápido con Symfony 4, y se me quedó pendiente el enviar por email los mensajes del formulario. Es decir, ya tenemos en un rato una rudimentaria ‘landing page’ donde un maquetador o el equipo de marketing disfrutará poniendo cualquier cosa. Será como maquetar con HTML, CSS y Javascript sin tener ningún engorroso CMS por debajo limitándonos lo que podemos hacer. Además tendremos la base de un buen Symfony para después añadir lo que queramos.

Ya tenemos la captación de contactos (o capture leads para los entendidos), que se guardan en una base de datos embebida en la propia web. Sin complicadas instalaciones ni configuraciones SQL, directamente con una base de datos SQLite embebida.

Sólo queda entonces hacer 3 cosas:

  • Instalar el módulo de Swiftmailer.
  • Configurarlo.
  • Y poner la acción de enviar el email.

Vamos al grano..

1. Instalando Swiftmailer

Para esto basta con poner en el terminal lo siguiente:

composer require symfony/swiftmailer-bundle

..esperamos, y si todo ha ido bien tenemos que ver en el terminal algo como lo siguente:

Using version ^3.2 for symfony/swiftmailer-bundle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
 - Installing egulias/email-validator (2.1.4): Loading from cache
 - Installing swiftmailer/swiftmailer (v6.0.2): Loading from cache
 - Installing symfony/swiftmailer-bundle (v3.2.2): Loading from cache
Writing lock file
Generating autoload files
ocramius/package-versions: Generating version class...
ocramius/package-versions: ...done generating version class
Symfony operations: 1 recipe (8c3c4103f30ebcc7579093a6f39dc028)
 - Configuring symfony/swiftmailer-bundle (>=2.5): From github.com/symfony/recipes:master
Executing script cache:clear [OK]
Executing script assets:install --symlink --relative public [OK]

Some files may have been created or updated to configure your new packages.
Please review, edit and commit them: these files are yours.

2. Configurar swiftmailer

Ahora las principales variables de configuración son variables de entorno. Esto es mucho más seguro ya que se pueden incluso no guardar en ningún fichero, pero la forma más sencilla es usar el fichero .env que debemos tener en el directorio raiz del proyecto. Si lo abrimos veremos que tenemos añadida la configuración de Swiftmailer:

###> symfony/swiftmailer-bundle ###
# For Gmail as a transport, use: "gmail://username:password@localhost"
# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
# Delivery is disabled by default via "null://localhost"
MAILER_URL=null://localhost
###< symfony/swiftmailer-bundle ###

Como bien explica en los comentarios, así hacemos. Pero para evitarte problemas te recomiendo usar siempre SMTP con un buen servidor de correo electrónico. Por Internet hay muchos ejemplos, uno puede ser este:

MAILER_URL=smtp://tudominio.com:587?encryption=tls&auth_mode=login&username=tuusuario&password=tucontraseña

Estas configuraciones usando SMTP son compatibles con la mayoría de los servidores de correo electrónico, sino todos. Tales como Mandrill, Amazon SES, Gmail, etcétera.. podrás configurarlos así, sólo tienes que encontrar las configuraciones que le pondrías a tu Outlook o Thunderbird y ponerlas en el proyecto de Symfony.

3. Enviar el email

Remitiéndome al post anterior, sólo nos queda en el controlador donde recibimos el contenido del formulario el enviarnos un email informándonos de que alguien nos ha dejado un mensaje. Para esto ponemos algo como esto en el controlador, marco en negrita lo nuevo:

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use App\Form\ContactType;
use App\Entity\Contact;

class MainController extends Controller
{
    /**
     * @Route("/", name="main")
     */
    public function index(Request $request, \Swift_Mailer $mailer)
    {
        $contact = new Contact();
        $theForm = $this->createForm(ContactType::class, $contact);

        $theForm->handleRequest($request);

        if ($theForm->isSubmitted() && $theForm->isValid()) {
            // save in database
            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->persist($contact);
            $entityManager->flush();

            // send email
            $message = (new \Swift_Message('JnjSite.com:: mensaje desde la web'))
                ->setFrom(['info@jnjsite.com' => 'Web JnjSite.com'])
                ->setTo([
                    'info@jnjsite.com', ])
                ->setBody(
                    $this->renderView(
                        'main/email.html.twig',
                        array('data' => $theForm->getData())
                ),
                'text/html'
            );
            if ($mailer->send($message)) {
                // Email enviado correctamente, vamos a limpiar el formulario.
                $theForm = $this->createForm(ContactType::class);
            } else {
                // Aquí podemos hacer algo más porque no se han enviado bien el email.
            }
        }

        return $this->render('main/index.html.twig', [
            'theForm' => $theForm->createView(),
        ]);
    }
}

Verás que no hay que complicarse mucho. Y por último necesitamos también la plantilla del correo electrónico, que la he puesto en templates/main/email.html.twig:

¡Hola!<br>
Hemos recibido un mensaje en el formulario.<br>
<br>
Nombre: <strong>{{ data.name }}</strong><br>
Email: <strong>{{ data.email }}</strong><br>
Asunto: <strong>{{ data.subject }}</strong><br>
Mensaje:<br>
<strong>{{ data.message }}</strong><br>

Terminando

Si todo ha ido bien, ahora podemos probar el formulario arrancando el proyecto en local, si ponemos esto en el terminal:

php bin/console server:start

Y visitamos http://localhost:8000/ nos enviamos un formulario y debemos de ver algo como esto:

Symfony Tutorial 2 enviando mail formulario

..sino me he explicado bien, o quieres decir algo, no dudes en dejar un comentario aquí abajo 😉


Symfony: creando landings con formularios

2018-04-21 - Categorías: PHP / Symfony
Landing pages con Symfony

Traigo hoy un HOWTO para hacer landing pages sobre Symfony 4 orientadas a captación de clientes. Un code-kata con el que en menos de 1 hora tendremos la estructura básica funcional sobre Symfony 4 para recibir contactos, guardarlos en base de datos y enviárnoslos por email.

Llevo un par de semanas bien ajetreadas: migrando un proyecto desde Symfony 3 al 4, otro desde un Joomla en mal estado a Symfony 4, otro proyecto terminándolo de poner en marcha con Symfony 4. Pequeños proyectos de poco tiempo que me han dado muchas ideas para escribir. Así que, cargado de ideas, sigo poco a poco redescubriendo Symfony con Symfony 4. Y me sigo sintiendo como un niño con juguete nuevo 😀

Tengo que decir que Symfony 4 ha mejorado mucho en simplicidad. No hay que saberse cómo funciona todo el conjunto con los 50-60 componentes, ni gran parte de ellos, para comenzar a hacer aplicaciones web robustas: https://symfony.com/components Ni tampoco hay que hacer complicados tutoriales muy largos antes de comenzar a construir con Symfony. Eso sí, tenemos que tener claro cómo funciona la línea de comandos con PHP, y tener muy claro cómo funciona Composer, esto ya lo expliqué en el primer tutorial sobre Symfony 4. Si todavía no te manejas bien con Composer y la línea de comandos.. ¡será mejor que no sigas!

Vayamos al grano..

Comenzando

Pasando de la teoría, y partiendo de que ya hamos visto los posts anteriores, vamos a seguir los siguientes pasos:

  1. Preparar los componentes que necesitamos.
  2. Preparar la base de datos que va a almacenar los contactos.
  3. Pintar el formulario en la página de aterrizaje, o landing page para los amigos.
  4. Recibir el formulario.
  5. Guardar en base de datos.
  6. Y enviarlo a nuestro email.

Comencemos..

1. Preparando los componentes

Creamos el esqueleto del proyecto, entramos al directorio y ponemos los componentes que vamos a usar:

composer create-project symfony/skeleton symfony-tutorial-2
cd symfony-tutorial-2
composer require twig
composer require form
composer require security
composer require doctrine
composer require maker
composer require server

2. Preparando la base de datos

Para simplificar el proceso, y no tener que instalarnos localmente un motor de base de datos completo propongo usar SQLite. SQLite es un tipo de base de datos embebida en la aplicación. Esto quiere decir que no necesita de instalación, simplemente la aplicación creará un fichero y manejará los datos sin ningún otro programa intermediario.

Primero vamos a crear la entidad Contact, que va a ser un objeto de PHP que va a almacenar los datos que un visitante nos deja en el formulario. A su vez, esta entidad se reutiliza para guardar automáticamente en la base de datos cada registro en una tabla que se creará automáticamente a partir de la entidad Contact. También se reutilizará para crear automáticamente el formulario. Esto de que Symfony genera automáticamente los códigos fuentes es brillante. Ejecutemos:

php bin/console make:entity

Y seguimos las instrucciones, vamos a crear los campos clásicos: nombre, email, asunto y mensaje.

Symfony Tutorial 2 landings Entity

Si te equivocas creando los campos no te preocupes, borra los ficheros y vuelve a empezar. Es la única forma de hacerlo y de aprender. Además, este comando make:entity te permite también añadir campos nuevos sobre la marcha si es que la entidad ya existe.

Ahora tenemos que decirle a la aplicación web que guarde los datos en SQLite, ya que por defecto los tratará de guardar en Mysql. Así que vamos a nuestro fichero .env y ponemos:

#DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
DATABASE_URL=sqlite:///%kernel.project_dir%/var/data.db

Ahora las principales variables de configuración como contraseñas, parámetros de configuración, etc.. entran a la aplicación a modo de variables de entorno. Esto es más seguro y práctico, pero también es material para otro post. Ya está, ahora ejecutamos esto:

php bin/console doctrine:database:create
php bin/console doctrine:schema:create

Si todo ha ido bien, acabamos de crear el fichero data.db y la tabla Contact para guardar los contactos que nos hagan los visitantes.

3. Pintar el formulario en la página de aterrizaje

Vamos a simplificar todo, así que sólo tendremos una página que va a ser la home, en donde estará este formulario. Así creamos el controlador que recibe la visita:

php bin/console make:controller

Yo le he llamado MainController al mío y me crea los ficheros necesarios:

Symfony tutorial 2 make controller

De nuevo Symfony nos ha hecho mucho trabajo. Podemos ya arrancar el servidor de desarrollo haciendo esto:

php bin/console server:start

Y vamos a ver los resultados en http://localhost:8000/

Para poner el formulario aquí vamos a editar el fichero symfony-tutorial-2/templates/main/index.html.twig y ponemos:

{% extends 'base.html.twig' %}

{% block title %}¡Creando landings!{% endblock %}

{% block body %}
    {{ form(theForm) }}
{% endblock %}

Ahora mismo la plantilla intentará pintar el formulario llamado theForm pero no se lo hemos pasado, vamos a crearlo:

php bin/console make:form
Symfony tutorial 2 formulario

Mira en la imagen, si le decimos a Symfony al crear el formulario que cargue de una entidad que ya hemos creado, Symfony creará todos los campos del formulario automáticamente. Así que ahora queda pasar con el controlador el formulario a la plantilla Twig. Editamos el fichero symfony-tutorial-2/src/Controller/MainController.php para que quede como lo siguiente:

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use App\Form\ContactType;

class MainController extends Controller
{
    /**
     * @Route("/", name="main")
     */
    public function index()
    {
        $theForm = $this->createForm(ContactType::class);

        return $this->render('main/index.html.twig', [
            'theForm' => $theForm->createView(),
        ]);
    }
}

Ya podemos recargar la página en el navegador y debemos ver el formulario. Sino, algo nos falta. Ahora nos queda recibir los formularios, guardarlos en base de datos y enviarnos estos datos a nuestro email.

4. Recibir el formulario

Si nos fijamos en el formulario, todavía no tiene botón de enviar, así que vamos a editar el fichero del formulario para añadírselo. En el fichero symfony-tutorial-2/src/Form/ContactType.php añadimos esta línea en los campos:

->add('submit', SubmitType::Class)

..y en la cabecera incluimos la clase del tipo submit así:

use Symfony\Component\Form\Extension\Core\Type\SubmitType;

Refrescamos y nos sale el formulario listo para enviar los datos:

Symfony tutorial 2 formulario submit

Ahora vamos a recibir los datos en el controlador. Para esto tenemos que recibir los datos en un objeto de PHP, del tipo de objeto que hemos creado antes. Es decir, vamos a usar la entidad Contact para que Symfony se encargue de todo. Es más fácil leer el código que explicarlo, en el controlador ponemos ahora:

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use App\Form\ContactType;
use App\Entity\Contact;
use Symfony\Component\HttpFoundation\Request;

class MainController extends Controller
{
    /**
     * @Route("/", name="main")
     */
    public function index(Request $request)
    {
        $contact = new Contact();
        $theForm = $this->createForm(ContactType::class, $contact);

        $theForm->handleRequest($request);

        if ($theForm->isSubmitted() && $theForm->isValid()) {
            // save in database
            // send email
        }

        return $this->render('main/index.html.twig', [
            'theForm' => $theForm->createView(),
        ]);
    }
}

He marcado en negrita lo que acabo de añadir. Con esto se recibe y se valida que los datos son correctos automáticamente. Es una maravilla, ¡Symfony se encarga de casi todo! Ya sólo nos queda guardar el contacto en la base de datos y enviárnoslo por email.

5. Guardar en la base de datos

Para guardarlo en la base de datos simplemente añadimos lo siguiente:

// save in database
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($contact);
$entityManager->flush();

Ahora sí, probamos el formulario y nos lo enviamos. Tendremos que poder abrir el fichero de la base de datos para ver cómo se guardan estos datos en la tabla que corresponde. Tengo Sqliteman instalado para ver estos ficheros, que viene en los repositorios de Ubuntu, pero hay muchos gestores de SQLite. Con un gestor de ficheros SQLite podremos abrir el fichero symfony-tutorial-2/var/data.db y veremos algo parecido a esto:

Symfony tutorial 2 formulario recibiendo datos

Ya sólo nos quedaría enviárnoslo a nuestro email. Es sencillo pero vamos a dejarlo para el siguiente post, que este ya está quedando muy espeso. Además el envío de correos electrónicos tiene mucho juego y hoy no me queda más tiempo 🙂

¡Un saludo!


Magento 1: resolviendo conflictos entre módulos

2018-04-07 - Categorías: Magento / PHP
Magento conflictos entre modulos

Magento es muy grande, aguanta carros y carretas, pudiéndole añadir gran cantidad de módulos. Uno de los proyectos en los que he participado alcanzó la friolera de 131 módulos, siendo algunos de estos módulos mega-módulos. Ha requerido mucho esfuerzo, todo hay que decirlo. Casi nunca suele ser «copiar y pegar los ficheros y ya está» como aquel que dice. Por el camino hay que resolver los conflictos, y tratamos día a día de evitar el añadir módulos si no es bien necesario. Hacemos limpieza de todos los que no se usen, y tratamos de actualizar todos los que se puedan, depende del tiempo que haya. Siempre surgen conflictos, y supone mucho tiempo hacer funcionar todas las opciones de ciertos módulos que entran en conflicto entre sí. Esto es el día a día del mantenimiento de los Magentos.

Origen de los problemas

Los desarrolladores hacen los módulos en un Magento limpio, recién instalado, sin que se requiera ningún otro módulo para su funcionamiento. Este es el entorno ideal, un Magento recién instalado. Pero la realidad nunca es así.

Continuar leyendo..

Magento 1: flushear la caché de Magento

2018-03-27 - Categorías: Magento / PHP
Flus Magento Cache

Es habitual que cuando haces cambios en Magento necesites flushear la caché. Esto es resetear, borrar los ficheros o datos temporales, que almacena Magento para agilizar sus tareas.

Magento va guardando ficheros intermedios que se ejecutan más rápido que los originales. También guarda variables, combina ficheros de configuración de los módulos, traducciones, bloques, layouts de las plantillas, etc.. Todos estos ficheros agilizan mucho la ejecución, así que si no tienes la caché activada deberias de activarla ya mismo.

Problema

Puede ser que tengas que estar instalando y desinstalando módulos y de repente deja de funcionar Magento. Quizá has modificado en la base de datos algún dato y no se ven los cambios. O quizá incluso modificando algunos ficheros te deja de funcionar Magento.

El problema viene cuando no puedes entrar al panel de control de Magento y darle al botón de ‘Flush Magento Cache’.

Continuar leyendo..

Symfony: tutorial 1: extendiendo el ¡hola mundo! y el enrutador de URLs

2018-03-22 - Categorías: PHP / Symfony
Symfony 1 el enrutamiento

En este segundo tutorial de la serie sobre Symfony. Dejo aquí explicado cómo se cargan las URLs. Para esto, tenemos aquí este clásico tutorial al estilo de ¡Hola Mundo! un poco más azucarado que el post el anterior. Lo primero en lo que hay que pensar son los puntos de entrada a la web: qué URLs vamos a tener y de qué forma, qué prefijos y sufijos van a tener, cómo se va a dividir la web desde el punto de vista del visitante que va viendo las URLs.

Todo esto es lo que llamaremos el enrutamiento de la web. Es decir, todas las URLs de entrada a la web pasan por un enrutador. Este enrutamiento se encargará de saber lo que tiene que hacer, llevando la visita al controlador que corresponda para hacer lo que tenga que hacer, y devolver al visitante la respuesta con la página que corresponda.

Creando el proyecto

Vamos a ir al grano, ejecutamos lo siguiente desde línea de comandos, terminal, consola, o como queramos llamarlo.. para tener lo indispensable para este tutorial:

composer create-project symfony/skeleton symfony-tutorial-1
cd symfony-tutorial-1

A partir de Symfony 5 tenemos disponible el comando de symfony que es más sencillo. Podemos hacer así entonces:

symfony new symfony-tutorial-1
cd symfony-tutorial-1

Instalando los componentes necesarios

Antes de Symfony 5 podíamos hacer lo siguiente para comenzar:

composer require server profiler symfony/maker-bundle --dev
composer require annotations twig

Ahora en Symfony 5 podemos hacer lo siguiente:

composer require profiler symfony/maker-bundle --dev
composer require annotations twig

Fíjate que pongo varios componentes instalados sólo para el entorno de desarrollo, por eso tienen el –dev.

Creando el primer controlador

Para esto hemos instalado el componente symfony/maker-bundle que nos ahorrará mucho tiempo. No sólo para crear controladores, sino que también tiene generador de códigos fuentes para crear formularios, CRUDs, entidades para guardar en base de datos, comandos de consola, subscribers, etc.. Entonces, ejecutamos desde línea de comandos:

php bin/console make:controller

Cuando nos pregunte le podemos poner de nombre por ejempo StaticController ya que va a encargarse de servir páginas estáticas. Esto crea los 3 ficheros siguientes:

symfony-tutorial-1/src/Controller/StaticController.php
symfony-tutorial-1/templates/base.html.twig
symfony-tutorial-1/templates/static/index.html.twig

Este controlador inicial se creará para recibir las visitas a la URL http://localhost:8000/static ya que por convención, el maker de controladores aplica estas configuraciones.

Editando las rutas de entrada, las URLs de la web

Para comprender cómo funciona el enrutamiento de Symfony con las anotaciones, vamos a hacer un ejercicio muy simple: vamos a modificar el controlador recién creado para que admita muchas URLs de entrada con sólo 3 funciones. Usaremos la variable {pageUrl} en la ruta de URL para esto.

Estoy acostumbrado a usar las anotaciones en los controladores para ser más prácticos. Es decir, que las anotaciones en los controladores te ayudan a trabajar los códigos mejor en el día a día de la programación. Así que.. vamos al grano: vamos modificar el controlador para permitir que reciba visitas en las siguientes URLs:

http://localhost:8000/
http://localhost:8000/static/
http://localhost:8000/static/cualquier-cadena
http://localhost:8000/cualquier-cadena

Editamos el fichero symfony-tutorial-1/src/Controller/StaticController.php para dejarlo como este:

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class StaticController extends AbstractController
{
    /**
     * @Route("/", name="home")
     * @Route("/static/", name="home_static")
     */
    public function home()
    {
        return $this->render('static/index.html.twig', [
            'controller_name' => 'StaticController/home',
        ]);
    }

    /**
     * @Route("/static/{pageUrl}", name="static_page")
     */
    public function staticPage($pageUrl)
    {
        return $this->render('static/'.$pageUrl.'.html.twig', [
            'controller_name' => 'StaticController/staticPage',
        ]);
    }

    /**
     * @Route("/{pageUrl}", name="static_page_other")
     */
    public function staticPageOther($pageUrl)
    {
        return $this->render('static/'.$pageUrl.'.html.twig', [
            'controller_name' => 'StaticController/staticPageOther',
        ]);
    }
}

Fíjate que he marcado en negrita las anotaciones que especifican qué URLs recibe este controlador. Vamos ahora con las plantillas.

Las plantillas en Twig

Antes de crear el controlador, al principio cuando instalábamos los componentes de Symfony que íbamos a utilizar, hemos instalado el componente de Twig. Esto nos facilita la vida, sobre todo a los maquetadores. Todas las plantillas en Symfony van a estar ahora bajo la ruta del proyecto templates/ . De esta forma duplicamos el fichero:

symfony-tutorial-1/templates/static/index.html.twig

Y creamos los ficheros:

symfony-tutorial-1/templates/static/page-url-1.html.twig
symfony-tutorial-1/templates/static/page-url-2.html.twig

..con el mismo contenido que el index.html.twig . Arrancamos entonces el proyecto para ver los resultados. Antes de Symfony 5 podíamos hacer esto si instalábamos dentro del proyecto el servidor de desarrollo:

php bin/console server:start

A partir de Symfony 5 tenemos que usar el comando symfony siguiente:

symfony server:start

Y tenemos que poder acceder con el navegador a las siguientes URLs:

http://localhost:8000/
http://localhost:8000/static/
http://localhost:8000/static/page-url-1
http://localhost:8000/page-url-1
http://localhost:8000/static/page-url-2
http://localhost:8000/page-url-2

Terminando

Fíjate la potencia que nos dan las anotaciones en los controladores. También con el uso de variables puedes cargar dinámicamente las plantillas. Incluso generar páginas que no existen, o con contenido 100% dinámico en función de la URL de entrada. Con esto puedes internacionalizar una web desde el principio cargando el código de idioma al inicio de la URL. Cualquier cosa que se te ocurra hacer con las URLs que se pongan en el navegador se puede hacer.

Llegó el momento de volver atrás, revisar los códigos fuentes de arriba y hacer probaturas. Espero que no me haya quedado el post demasiado espeso, el enrutamiento es simple pero se pueden hacer muchas cosas a partir del enrutamiento. Para cualquier cosa no lo dudes, mensaje aquí abajo y con gusto contestaré 😉

Tienes los códigos fuentes subidos a GitHub aquí:
https://github.com/jaimenj/symfony-starter-tutorials

Sólo me queda remitirte a la documentación oficial relacionada con este post:
https://symfony.com/doc/current/page_creation.html

¡Un saludo!


Symfony: tutorial 0: preparando el espacio de trabajo

2018-03-15 - Categorías: PHP / Symfony
Herramientas para desarrollar en Symfony

A partir de la versión 4, tenemos un Symfony orientado a microservicios, en la que te vas construyendo tu propio framework poco a poco, con los componentes que necesites. Esto quiere decir que no te instalas el framework completo cuando empiezas a trabajar, sino que poco a poco vas añadiendo los componentes.

Gracias a Composer vas acoplando sólo los componentes que necesitas, ya sean del propio Symfony, o sean componentes externos al framework. Esto hace a su vez que la curva de aprendizaje no sea tan pronunciada.

Hay aquí una serie de tutoriales de iniciación, para principiantes, y no tan principiantes, con referencias para que los más avanzados sigáis adelante..

Continuar leyendo..

Magento 1: listar todas las alertas por vuelta a stock de producto

2018-03-07 - Categorías: Magento / PHP

En el post anterior hablaba de cómo activar estas alertas, para que el cliente se pudiera registrar a las alertas por vuelta a stock de producto. Si tenemos activada esta opción deben de haberse apuntado los clientes interesados en ciertos productos que no tienes en stock ahora mismo.

El siguiente paso es pedir productos a los proveedores..

Ahora bien, según vuelvas a tener stock, si había algún suscrito a esta alerta, recibirá un email invitándole a venir a comprar el producto. Pero y si además de esto, ¿miras qué suscripciones y a qué productos se han suscrito para hacer las compras más a tiro hecho?

Continuar leyendo..

Magento 1: listar clientes con más actividad en los últimos meses

2018-02-26 - Categorías: Magento
eCommerce clientes y ventas

Una información muy interesante para el equipo directivo de una empresa, puede ser simplemente el saber qué clientes son los más activos. Quizá queremos calcular un promedio de pedidos por cliente, cuántos intentos de pedido ha habido sin llegar a éxito, terminados en cancelación o no. Quizá sólo hacen un pedido y no vuelven más a la web. O quizá no suelen hacer ni un pedido, pero los que hacen pedidos suelen repetir…

Esta información, y mucha más, es información necesaria para lo llamado como: Inteligencia de Negocio. Esta información, muchas veces no es suficiente con los reportes del panel del control, pero es bastante sencillo de sacar a partir de scripts en PHP.

En el panel de control de Magento, podemos ir a la sección de Informes > Clientes > Clientes por total de pedidos, o a Informes > Clientes > Clientes por número de pedidos y veremos listados exportables como el siguiente:

Los subreportes en Magento de casa están limitados a 5, por esto que sólo verás 5 resultados por día o por mes. Lo que no veo, por ejemplo, es que no salen los clientes con 0 pedidos, tampoco tengo emails ni teléfonos para arrancar acciones comerciales. Esto es un problema, porque aunque puedo ver cierta información, y la puedo exportar a CSV, no tengo casi información reutilizable.

Así que aquí abajo dejo el script que saca el 100% de los resultados. Editarlo para añadir la información de los clientes y sus pedidos no es complicado.

Listando clientes

Vamos con el simple caso de sacar un listado de los clientes y su número de pedidos. Primero que todo necesitaremos los clientes, vamos a sacar sólo los creados este año:

$customers = Mage::getModel('customer/customer')->getCollection()
    ->addFieldToFilter('created_at', array(
        'from' => '2018-01-01 00:00:00',
    ));

Dentro de $customers tendremos un array de clientes. Luego vamos a necesitar los pedidos para cada uno de ellos.

Listando pedidos

Así tenemos los pedidos de un sólo cliente desde una fecha:

$orderCollection = Mage::getResourceModel('sales/order_collection')
    ->addFieldToFilter('customer_id', $customerId)
    ->addFieldToFilter('created_at', array(
        'from' => '2018-01-01 00:00:00',
    ))
    ->setOrder('created_at', 'desc');

..donde $customerId es el identificador del cliente dentro de Magento.

Todo junto

Juntando todo en un sólo script nos puede quedar algo así:

<?php

require_once __DIR__.'/app/Mage.php';

Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

$customers = Mage::getModel('customer/customer')->getCollection()
    ->addFieldToFilter('created_at', array(
        'from' => '2018-01-01 00:00:00',
    ));

echo 'ID,TAXVAT,EMAIL,NOMBRE,APELLIDOS,PEDIDOS'.PHP_EOL;

foreach ($customers as $customer) {
    $customer = Mage::getModel('customer/customer')->load($customer->getId());

    echo $customer->getId().','
        .trim($customer->getTaxvat()).','
        .trim($customer->getEmail()).',"'
        .trim($customer->getFirstname()).'","'
        .trim($customer->getLastname()).'",';

    $orderCollection = Mage::getResourceModel('sales/order_collection')
        ->addFieldToFilter('customer_id', $customer->getId())
        ->addFieldToFilter('created_at', array(
            'from' => '2018-01-01 00:00:00',
        ))
        ->setOrder('created_at', 'desc');

    echo $orderCollection->count();

    echo PHP_EOL;
}

Este script lo podemos meter dentro de un fichero .php, por ejemplo llamado customersAndOrders.php, y lo ponemos en el directorio raíz del proyecto. Ahora lo ejecutamos desde línea de comandos:

$ php customersAndOrders.php

Y deberemos de ver un listado de estos clientes en formato .csv

ID,TAXVAT,EMAIL,NOMBRE,APELLIDOS,PEDIDOS
76022,1231321E,afasf.asfafsaf@gdfgfdg.com,"Nombre1","Apellidos1",1
76023,,asdasd@dfgdfg.com,"Nombre2","Apellidos2",3
76025,54566654F,sadsadasd@dfgdfg.com,"Nombre3","Apellidos3",1

Que de igual manera podemos guardarlo a un fichero .csv para luego estudiarlo en LibreOffice o similar como un Excel, así:

$ php customersAndOrders.php > customersAndOrders.csv

¿Sencilllo verdad? Espero que sirva.

Un saludo.


PrEDA: cálculo empírico del coste temporal de Binomial

2018-02-04 - Categorías: PHP / PrEDA
Números

El coeficiente binomial es una función muy utilizada en combinatoria. Sirve para saber el número de combinaciones de elementos que podemos hacer. Se utiliza mucho en computación para estudiar la estrategia de programación dinámica, porque ejemplifica muy bien la mejora que supone utilizar dicha estrategia. Por ejemplo, la forma de escoger de entre 6 elementos 2 de ellos, es igual al coeficiente binomial (6 2).

Continuar leyendo..

© 2024 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.