Continuamos programando 1 agenda CSV con PHP

En el video anterior explicamos una idea de análisis muy importante que consistía en centrar el desarrollo de nuestra aplicación en los objetos que ésta gestiona, así como en las operaciones que se llevan a cabo sobre dichos objetos. Por esta razón creamos la carpeta people con los archivos CRUD para crear, leer, actualizar y borrar los contactos.

Hoy vamos a comentar otras ideas de diseño igualmente importantes. Fíjate que estamos desarrollando nuestra agenda solo con PHP, sin ningún framework de desarrollo, pero lo hacemos separando claramente el código PHP del código HTML, o dicho de otra forma, separando la lógica controladora de la capa de presentación.

Agenda

¿Por qué separamos el código PHP del código HTML?

Porque si más adelante queremos pasar nuestra agenda a un framework MVC, como por ejemplo Laravel, Symfony, Zend, o el que sea, podamos tomar el código muy fácilmente y ponerlo donde toque, en el framework en cuestión. Con esta práctica de programación simplemente separamos el código en partes claramente diferenciadas para hacerlo mantenible.

Archivo list.php:

<?php
// Ejecutamos la lógica de arranque de la app, o lógica de bootstrap
require '../vendors/AgendaPHPGuay/People.php';
use \AgendaPHPGuay\People;
// Obtenemos los datos de los contactos
$people = People::getInstance(__DIR__ . "/../data/people.csv")
    ->getCsv()
    ->people;
?>
<!DOCTYPE html>
<html lang="es">
    <?php include '../views/head.php'; ?>
    <body>
        <div class="container-narrow">
            <div class="masthead">
                <h3 class="muted">Agenda PHP guay</h3>
            </div>
            <div class="jumbotron">                
                <a class="btn btn-large btn-success" href="add.php">Añadir contacto</a>
                <?php
                if(empty($people))
                { ?>
                    <h4>La agenda de contactos está vacía</h4>
                <?php
                }
                else 
                { ?>
                    <table class="table">
                        <thead>
                            <tr>
                                <th>Nombre</th>
                                <th>Apellido</th>
                                <th>Email</th>
                                <th>Acciones</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php
                            foreach($people as $person)
                            { ?>
                            <tr>
                                <td><?php echo $person['name']; ?></td>
                                <td><?php echo $person['surname']; ?></td>
                                <td><?php echo $person['email']; ?></td>
                                <td>
                                    <a href="/agenda/people/update.php?name=<?php echo urlencode($person['name']); ?>&surname=<?php echo urlencode($person['surname']); ?>&email=<?php echo urlencode($person['email']); ?>" class="btn">Editar</a>
                                    <a href="/agenda/people/delete.php?email=<?php echo urlencode($person['email']); ?>" class="btn">Borrar</a>
                                </td>       
                            </tr>
                            <?php
                            } ?>
                        </tbody>
                    </table>
                <?php
                } ?>
            </div>
            <hr>
            <?php include '../views/footer.php'; ?>
        </div> <!-- /container -->
        <script src="../assets/bootsrap/js/bootsrap.min.js"></script>
    </body>
</html>

Este archivo instancia un objeto de tipo People y obtiene la información CSV, en concreto, el listado de las personas. Un poco más adelante, en el siguiente video, ya verás cómo funciona todo esto por dentro, cuando te muestre el código de la clase People. De mientras puedes echar un vistazo al código en este repo de GitHub.

¿Y cómo es el constructor de People?

Bueno, te voy a avanzar 1 cosa. El constructor de People toma el archivo CSV y carga la información en un objeto stdClass, en memoria.

/**
 * Constructor que inicializa el CSV en memoria
 * @param string $path
 */
protected function __construct($path)
{        
    $this->csv = new \stdClass;
    $this->csv->path = $path;
    // Cargamos la cabecera y las personas del archivo CSV en memoria
    $fp = @fopen($this->csv->path, 'r') or die('The file cannot be opened');
    while (($row = fgetcsv($fp, 1024, ",")) !== false)
    {
        !isset($this->csv->header) 
            ? $this->csv->header = $row 
            : $this->csv->people[] = array_combine($this->csv->header, $row);
    }
    fclose($fp);   
}

Ese stdClass tiene un array llamado header que guarda los datos de la cabecera CSV, y un array people con los datos de los contactos. Por otro lado, People también cuenta con este método para obtener el CSV:

/**
 * Devuelve el CSV cargado en memoria
 * @return array
 */
function getCsv()
{
    return $this->csv;
}

En consecuencia, list.php obtiene el array people del siguiente modo:

// Obtenemos los datos de los contactos
$people = People::getInstance(__DIR__ . "/../data/people.csv")
    ->getCsv()
    ->people;

Así ya podemos recorrer los datos muy cómodamente:

<tbody>
    <?php
    foreach($people as $person)
    { ?>
    <tr>
        <td><?php echo $person['name']; ?></td>
        <td><?php echo $person['surname']; ?></td>
        <td><?php echo $person['email']; ?></td>
        <td>
            <a href="/agenda/people/update.php?name=<?php echo urlencode($person['name']); ?>&surname=<?php echo urlencode($person['surname']); ?>&email=<?php echo urlencode($person['email']); ?>" class="btn">Editar</a>
            <a href="/agenda/people/delete.php?email=<?php echo urlencode($person['email']); ?>" class="btn">Borrar</a>
        </td>       
    </tr>
    <?php
    } ?>
</tbody>

Bueno amig@s, pues esto es todo por hoy. En la tercera parte te mostraré cómo funciona el componente estrella de la aplicación, la clase People, y veremos un montón de cosas avanzadas de PHP: repasaremos conceptos de POO, aprenderemos cómo funciona el patrón de diseño Singleton, aprenderemos a gestionar archivos de texto con las funciones nativas de PHP, etc. ¡No te pierdas la próxima entrega!