# Programación orientada a objetos en PHP. ## Orientación a objetos en PHP Los pilares fundamentales de la POO son: - **Herencia**. Es el proceso de crear una clase a partir de otra. - **Abstracción**. Hace referencia a que cada clase oculta en su interior las peculiaridades de su implementación, y presenta al exterior una serie de métodos (interface) cuyo comportamiento está bien definido. - **Polimorfismo**. Un mismo método puede tener comportamientos distintos en función del objeto con que se utilice. - **Encapsulación**. En la POO se juntan en un mismo lugar los datos y el código que los manipula. Las ventajas más importantes que aporta la programación orientada a objetos son: - **Modularidad**. Los programas se dividen en partes o módulos más pequeños, que son independientes unos de otros pero que se pueden comunicar. - **Extensibilidad**. Podemos añadir nuevos métodos al código, o crear nuevos objetos. - **Mantenimiento**. Los programas desarrollados utilizando POO son más sencillos de mantener. No debe haber dos clases en un mismo fichero, ni otro código aparte del propio de la clase. ### Características de orientación a objetos en PHP. A partir de la **versión 3**, **se empezaron a introducir algunos rasgos de POO** en el lenguaje. Esto **se potenció en la versión 4**, aunque todavía de forma muy rudimentaria. Por ejemplo, en **PHP4**: - Los objetos se pasan siempre por valor, no por referencia. - El nivel de acceso para todos es público. - No existen los interfaces. - No existen métodos destructores A partir de la versión de 5, se reescribió el soporte de orientación a objetos del lenguaje, ampliando sus características y mejorando su rendimiento y su funcionamiento general. Las características de POO que soporta PHP incluyen: - **Métodos estáticos**. - **Métodos constructores y destructores**. - **Herencia**. - **Interfaces**. - **Clases abstractas**. (A partir de la versión 5.4.0) Entre las características que no incluye PHP, y que puedes conocer de otros lenguajes de programación, están: - **Herencia múltiple**. - **Sobrecarga de métodos**.(incluidos los métodos constructores). - **Sobrecarga de operadores**. ### Creación de clases Uno de los motivos para crear atributos privados es que su valor forma parte de la información interna del objeto y no debe formar parte de su interfaz. Otro motivo es mantener cierto control sobre sus posibles valores. ```php= public function setCodigo($nuevo_codigo) { if (noExisteCodigo($nuevo_codigo)) { $this->codigo = $nuevo_codigo; return true; } return false; } public function getCodigo() { return $this->codigo; } ``` Aunque no es obligatorio, el nombre del método que nos permite obtener el valor de un atributo suele empezar por get, y el que nos permite modificarlo por set, y a continuación el nombre del atributo con la primera letra en mayúsculas. En PHP5 se introdujeron los llamados métodos mágicos, entre ellos __set y __get. Si se declaran estos dos métodos en una clase, PHP los invoca automáticamente cuando desde un objeto se intenta usar un atributo no existente o no accesible. ```php= class Producto { private $atributos = array(); public function __get($atributo) { return $this->atributos[$atributo]; } public function __set($atributo, $valor) { $this->atributos[$atributo] = $valor; } } ``` Cuando desde un objeto se invoca un método de la clase, a éste se le pasa siempre una referencia al objeto que hizo la llamada. Esta referencia se almacena en la variable $this. ```php= echo "<p>" . $this->codigo . "</p>"; ``` No es necesario que exista ningún objeto de una clase para poder acceder al valor de las constantes que defina. Además, sus nombres suelen escribirse en mayúsculas. En PHP, una clase puede tener atributos o métodos estáticos, también llamados a veces atributos o métodos de clase. Se definen utilizando la palabra clave static. ```php= class Producto { private static $num_productos = 0; public static function nuevoProducto() { self::$num_productos++; } … } ``` **Para acceder a las constantes y valores estáticos de una clase**, se debe utilizar el nombre de la clase y **el operador ::**, llamado operador de resolución de ámbito. ```php= class DB { const USUARIO = 'gestor'; … } echo DB::USUARIO; ``` ```php= Producto::nuevoProducto(); ``` - **self**: Para acceder a valores estáticos y constantes dentro de una clase - **$this**: Para acceder a propiedades y funciones dentro de una clase ```php= self::$num_productos ++; ``` Los atributos estáticos de una clase se utilizan para guardar información general sobre la misma, como puede ser el número de objetos que se han instanciado. PHP permite a los desarrolladores declarar métodos constructores para las clases. Aquellas que tengan un método constructor lo invocarán en cada nuevo objeto creado, lo que nos permite la inicialización que el objeto pueda necesitar antes de ser usado. Como **PHP no admite sobrecarga** de métodos sólo podremos crear un constructor por clase. ```php= class Persona{ public static $id; private $nombre; private $perfil; public function __construct(){ $perfil="Público"; } } // Creamos persona1 que tiene inicializado su atributo $perfil a Público. $persona1=new Persona(); ``` Con el uso de las funciones **"func_get_args()"**, **"fun_get_arg()"** y **"func_num_arg()"**. podemos pasar distinto número de parámetros a un constructor **"simulando" la sobrecarga** del mismo. Otra posibilidad es usar el método mágico **"__call"** para capturar llamadas a métodos que no estén implementados. También es posible definir un método destructor, que debe llamarse **"__destruct"** y permite definir acciones que se ejecutarán cuando se elimine el objeto. ```php= class Producto { private static $num_productos = 0; private $codigo; public function __construct($codigo) { $this->$codigo = $codigo; self::$num_productos++; } public function __destruct() { self::$num_productos--; } … } $p = new Producto('GALAXYS'); ``` ## Utilización de objetos. Una vez creado un objeto, puedes utilizar el operador **instanceof** para comprobar si es o no una instancia de una clase determinada. ```php <?php if ($p instanceof Producto) { . . .} ``` ### Funciones de utilidad para objetos y clases en PHP | Función | Ejemplo | Significado | | -------- | -------- | -------- | | **get_class()**|![](https://i.imgur.com/OIZKccH.png)|Devuelve el nombre de la clase del objeto.| | **class_exists** |![](https://i.imgur.com/7V9wRH5.png)|Devuelve true si la clase está definida o false en caso contrario.| | **get_declared_classes()** |![](https://i.imgur.com/SPQd4uI.png)|Devuelve un array con los nombres de las clases definidas.| | **class_alias()**|![](https://i.imgur.com/Qv3mjTu.png)|Crea un alias para una clase.| | **get_class_methods()**|![](https://i.imgur.com/9nGdJOz.png)|Devuelve un array con los nombres de los métodos de una clase que son accesibles desde dónde se hace la llamada.| | **method_exists()**|![](https://i.imgur.com/PKmVLpV.png)|Devuelve true si existe el método en el objeto o la clase que se indica, o false en caso contrario, independientemente de si es accesible o no| | **get_class_vars()** |![](https://i.imgur.com/2t46dUj.png)|Devuelve un array con los nombres de los atributos de una clase que son accesibles desde dónde se hace la llamada.| | **get_object_vars()**|![](https://i.imgur.com/ifTujVP.png)|Devuelve un array con los nombres de los métodos de un objeto que son accesibles desde dónde se hace la llamada| | **property_exists()**|![](https://i.imgur.com/5yw4qou.png)|Devuelve true si existe el atributo en el objeto o la clase que se indica, o false en caso contrario,independientementede si es accesible o no.| Desde PHP5, puedes indicar en las funciones y métodos de qué clase deben ser los objetos que se pasen como parámetros así como el tipo del dato devuelto. Para ello, debes especificar el tipo antes del parámetro. Para el dato devuelto poner ":tipoDato", despues de la declaración de la función o el método y antes de las llaves. ```php= public function precioProducto(Producto $p) :float { . . . return $precio; } ``` Si cuando se realiza la llamada, el parámetro no es del tipo adecuado, se produce un error que podrías capturar. Una característica de la POO que debes tener muy en cuenta es qué sucede con los objetos cuando los pasas a una función, o simplemente cuando ejecutas un código como el siguiente: ```php= $p = new Producto(); $p->nombre = 'Samsung Galaxy S'; $a = $p; ``` En **PHP4**, la última línea del código anterior **crea un nuevo objeto con los mismos valores del original**. Sin embargo, a partir de **PHP5 se crea un nuevo identificador** del mismo objeto. Recuerda que, aunque haya dos o más identificadores del mismo objeto, en realidad todos se refieren a la única copia que se almacena del mismo. Si necesitas copiar un objeto, debes utilizar **clone**. Al utilizar clone sobre un objeto existente, **se crea una copia de todos los atributos del mismo en un nuevo objeto**. ```php= $p = new Producto(); $p->nombre = 'Samsung Galaxy A6'; $a = clone($p); ``` Además, existe una forma sencilla de personalizar la copia para cada clase particular, puedes crear un método de nombre **__clone** en la clase. Este método se llamará automáticamente después de copiar todos los atributos en el nuevo objeto. ```php= class Producto { … public function __clone($atributo) { $this->codigo = nuevo_codigo(); } … } ``` Si utilizas el operador de comparación "==", comparas los valores de los atributos de los objetos. Por tanto dos objetos serán iguales si son instancias de la misma clase y, además, sus atributos tienen los mismos valores. ```php= $p = new Producto(); $p->nombre = 'Samsung Galaxy A6'; $a = clone($p); // El resultado de comparar $a == $p da verdadero // pues $a y $p son dos copias idénticas ``` Sin embargo, si utilizas el operador "===", el resultado de la comparación será true sólo cuando las dos variables sean referencias al mismo objeto. ```php= $p = new Producto(); $p->nombre = 'Samsung Galaxy A6'; $a = clone($p); // El resultado de comparar $a === $p da falso // pues $a y $p no hacen referencia al mismo objeto $a = & $p; // Ahora el resultado de comparar $a === $p da verdadero // pues $a y $p son referencias al mismo objeto. ``` A veces puede ser útil mostrar el contenido de un objeto sin tener que usar var_dump() para ello podemos usar el método mágico **__toString()**. Este método siempre debe devolver un String. ```php= class Persona{ public $nombre; public $apellidos; public $perfil; public function __toString() :String{ return "{$this->apellidos}, {$this->nombre}, Tu pérfil es: {$this->perfil}"; } } $persona = new Persona(); $persona->nombre="Manuel"; $persona->apellidos="Gil Gil"; $persona->perfil="Público"; echo $persona; //muestra: Gil Gil, Manuel, Tu pérfil es: Público ``` ## Mecanismos de mantenimiento del estado Los objetos no tienen un único tipo. Cada objeto tendrá unos atributos u otros en función de su clase. Por tanto, para almacenar los objetos en la sesión del usuario, hace falta convertirlos a un formato estándar. Este proceso se llama serialización. En PHP, para **serializar un objeto** se utiliza la función **serialize()**. El resultado obtenido es un string que contiene un flujo de bytes, en el que se encuentran definidos todos los valores del objeto. ```php= $p = new Producto(); $a = serialize($p); ``` A partir de ella, es posible reconstruir el objeto original utilizando la función **unserialize()**. ```php= $p = unserialize($a); ``` Pero **en PHP** esto aún es más fácil. **Los objetos que se añadan a la sesión del usuario son serializados automáticamente**. Por tanto, **no es necesario usar serialize() ni unserialize()**. ```php= session_start(); $_SESSION['producto'] = $p; ``` **Para** poder **deserializar** un objeto, **debe estar definida su clase**. En PHP además tienes la opción de personalizar el proceso de serialización y deserialización de un objeto, utilizando los métodos mágicos **"__sleep()"** y **"__wakeup()"**. Si en la clase está definido un método con nombre **"__sleep()"**, se ejecuta antes de serializar un objeto. Igualmente, si existe un método **"wakeup()"**, se ejecuta con cualquier llamada a la función unserialize(). ## Herencia Las nuevas clases que heredan también se conocen con el nombre de subclases. La clase de la que heredan se llama clase base o superclase. ```php= class Producto { public $codigo; public $nombre; public $nombre_corto; public $pvp; public function muestra() { echo "<p>" . $this->codigo . "</p>"; } } ``` Si quieres personalizar la información que vas a tratar de cada tipo de producto, puedes crear nuevas clases que hereden de Producto. ```php= class TV extends Producto { public $pulgadas; public $tecnologia; } ``` Como puedes ver, para definir una clase que herede de otra, simplemente tienes que utilizar la palabra extends indicando la superclase. Los nuevos objetos que se instancien a partir de la subclase son también objetos de la clase base; se puede comprobar utilizando el operador instanceof(). ```php= $t = new TV(); if ($t instanceof Producto) { // Este código se ejecuta pues la condición es cierta. . . . } ``` | Función | Ejemplo | Significado | | -------- | -------- | -------- | | **get_parent_class()** | echo get_parent_class($t); | Devuelve el nombre de la clase padre del objeto o la clase que se indica. | | **is_subclass_of()** | if (is_subclass_of($t, 'Producto') | Devuelve true si el objeto o la clase del primer parámetro, tiene como clase base a la que se indica en el segundo parámetro, o false en caso contrario. | La nueva clase hereda todos los atributos y métodos públicos de la clase base, pero no los privados. Si quieres crear en la clase base un método no visible al exterior que se herede a las subclases, debes utilizar la palabra protected en lugar de private. Además, puedes redefinir el comportamiento de los métodos existentes en la clase base, simplemente creando en la subclase un nuevo método con el mismo nombre. ```php= class TV extends Producto { public $pulgadas; public $tecnologia; public function muestra() { echo "<p>" . $this->pulgadas . " pulgadas</p>"; } } ``` Existe una forma de **evitar que las clases heredadas puedan redefinir el comportamiento** de los métodos existentes en la superclase: utilizar la palabra **final**. ```php= class Producto { public $codigo; public $nombre; public $nombre_corto; public $pvp; public final function muestra() { echo "<p>" . $this->codigo . "</p>"; } } ``` Incluso se puede declarar una clase utilizando **final**. La palabra **abstract** se utiliza tanto con métodos como con clases completas, pero en lugar de prohibir la herencia, obliga a que se herede. Es decir, una clase con el modificador abstract no puede tener objetos que la instancien, pero sí podrá utilizarse de clase base y sus subclases sí podrán utilizarse para instanciar objetos. ```php= abstract class Producto { . . . } ``` Y un método en el que se indique abstract, debe ser redefinido obligatoriamente por las subclases, y no podrá contener código. ```php= class Producto { . . . abstract public function muestra(); } ``` Obviamente, no se puede declarar una clase como abstract y final simultáneamente. abstract obliga a que se herede para que se pueda utilizar, mientras que final indica que no se podrá heredar. En PHP, si la clase heredada no tiene constructor propio, se llamará automáticamente al constructor de la clase base. Sin embargo, si la clase heredada define su propio constructor, deberás ser tú el que realice la llamada al constructor de la clase base si lo consideras necesario, utilizando para ello la palabra parent y el operador de resolución de ámbito. ```php= class TV extends Producto { public $pulgadas; public $tecnologia; public function __construct($row) { parent::__construct($row); //llama al constructor de la clase padre $this->pulgadas = $row['pulgadas']; $this->tecnologia = $row['tecnologia']; } public function muestra() { echo "<p>" . $this->pulgadas . " pulgadas</p>"; } } ``` Al utilizar **parent** haces referencia a la clase base de la actual, tal y como aparece tras extends. ## Interfaces Un interface es como una clase vacía que solamente contiene declaraciones de métodos. Se definen utilizando la palabra interface. ```php= interface iMuestra { public function muestra(); } ``` Y cuando crees las subclases deberás indicar con la palabra **implements** que tienen que implementar los métodos declarados en este interface. ```php= class TV extends Producto implements iMuestra { . . . public function muestra() { echo "<p>" . $this->pulgadas . " pulgadas</p>"; } . . . } ``` **Todos los métodos** que se declaren en un **interface deben ser públicos**. Además de métodos, **los interfaces podrán contener constantes** pero no atributos. Un interface **es como un contrato que la clase debe cumplir**. Al implementar todos los métodos declarados en el interface se asegura la interoperabilidad entre clases. Si sabes que una clase implementa un interface determinado, sabes qué nombre tienen sus métodos, qué parámetros les debes pasar y, probablemente, podrás averiguar fácilmente con qué objetivo han sido escritos. Es posible crear clases que implementen varios interfaces, simplemente separando la lista de interfaces por comas después de la palabra "implements". ```php= class TV extends Producto implements iMuestra, Countable { . . . } ``` La única restricción es que **los nombres de los métodos que se deban implementar en los distintos interfaces no coincidan**. En PHP también se pueden crear nuevos interfaces heredando de otros ya existentes. Se hace de la misma forma que con las clases, utilizando la palabra "extends". Una de las dudas más comunes en POO, es qué solución adoptar en algunas situaciones: interfaces o clases abstractas. Ambas permiten definir reglas para las clases que los implementen o hereden respectivamente. Y ninguna permite instanciar objetos. Las diferencias principales entre ambas opciones son: - En las clases abstractas, los métodos pueden contener código. Si van a existir varias subclases con un comportamiento común, se podría programar en los métodos de la clase abstracta. Si se opta por un interface, habría que repetir el código en todas las clases que lo implemente. - Las clases abstractas pueden contener atributos, y los interfaces no. - No se puede crear una clase que herede de dos clases abstractas, pero sí se puede crear una clase que implemente varios interfaces. | Función | Ejemplo | Significado | | -------- | -------- | -------- | | **get_declared_interfaces()** | print_r(get_declared_interfaces()); | Devuelve un array con los nombres de los interfaces declarados. | | **interface_exists()** | if (interface_exists('iMuestra') | Devuelve true si existe el interface que se indica, o false en caso contrario. | ## Programación en capas El más extendido es el patrón de diseño Modelo – Vista – Controlador (MVC). Este patrón pretende dividir el código en tres partes, dedicando cada una a una función definida y diferenciada de las otras. - **Modelo**. Es el encargado de manejar los datos propios de la aplicación. - **Vista**. Es la parte del modelo que se encarga de la interacción con el usuario. - **Controlador**. En este módulo se decide qué se ha de hacer, en función de las acciones del usuario con su interface. La gran ventaja de este patrón de programación es que genera código muy estructurado, fácil de comprender y de mantener. ## Namespaces en PHP Los namespace nos ayudaran para organizar y reestructurar mejor nuestro código y proporcionan una manera para agrupar clases, interfaces, funciones y constantes relacionadas. ```php= <?php namespace Proyecto; // La declaración del namespace debe ser la primera línea si no obtendremos un error ``` En un espacio de nombres se engloban: - Constantes. - Funciones. - Clases, interfaces, traits, clases abstractas. ```php= <?php namespace Proyecto; const E = 2.7182; function saludo(){ echo "Buenos dias"; } class Prueba{ private $nombre; public function probando(){ echo "Esto es el método probando de la clase Prueba"; } } ``` Para pode usar este archivo en otra parte podemos hacerlo de varias formas: ```php= <?php include "ejemploNamespace.php"; echo Proyecto\E; // accedemos a la constante Proyecto\saludo(); // accedemos a la función $prueba=new Proyecto\Prueba(); $prueba->probando(); ``` ```php= <?php include "ejemploNamespace.php"; use const Proyecto\E; use function Proyecto\saludo; use Proyecto\Prueba; // ahora ya podemos usarlos echo E; saludo(); $prueba = new Prueba(); ``` ## Gestionar Dependencias Composer es un gestor de dependencias en proyectos, para programación en PHP. Entre sus principales virtudes destacan: - Es simple de utilizar - Cuenta con un repositorio propio donde podemos encontrar casi de todo - Disminuye significativamente problemas de cambio de entorno de ejecución (Mediante su funcionalidad de congelar dependencias) - Actualiza las librerías a nuevas versiones fácilmente si queremos mediante "composer update". Vemos a empezar a trabajar con Composer, para ello veremos la instalación y los primeros pasos: - **Instalación**: Nos descargamos el archivo desde la página oficial. Una vez hecho esto y si no ha habido problemas tendremos el archivo "composer.phar" en el directorio donde estemos. - **Primeros pasos**: En la raíz del directorio donde vaya a estar nuestro proyecto y desde la terminal tecleamos "composer init" a continuación se nos hacen unas preguntas y vamos contestando. Al final nos muestra un archivo JSON, se nos pregunta que si queremos generarlo, contestamos que si y nos genera el archivo "composer.json". Una vez generado el archivo tecleando "composer install" nos instalará las dependencias. Una de las cosas que hace composer es gestionarnos el tema de la autocarga de clases/librerías. Para ello debemos crearnos, en el raíz del proyecto que vayamos a usar, un directorio de nombre y modificar el archivo "composer.json". Para el "autoload" de clases y librerías se hace uso de los namespaces. ```php= "name": "usuario/usuario", "description": "Ejemplo Blade", "type": "project", "config": { "optimize-autoloader": true }, "autoload": { "psr-4": { "Clases\\": "src" } }, "license": "GNU/GPL", "authors": [ { "name": "usuario", "email": "usuario@correo.es" } ] } ``` En el directorio "src" meteremos todas las clases y comenzaremos el archivo como ya vimos "namespace Clases". Cada vez que modifiquemos el fichero "composer.json" hay que hacer un "composer install" para instalar las nuevas dependencias que hayamos puesto. Si deseamos añadir dependencias a posteriori podemos escribir el comando: "composer require vendor/libreria". ## Separación de la lógica de negocio Un **motor de plantillas web** es una aplicación que **genera una página web a partir de un fichero con la información de presentación** (denominado **plantilla o template**, que viene a ser similar a la vista en el patrón MVC) y otro con la **lógica interna de la aplicación** (similar al modelo de MVC). **Blade** es un sistema de plantillas (Laravel) que nos permite generar HTML dinámico con una **sintaxis mucho más limpia** que si usáramos PHP plano. Veamos como instalarlo, configurarlo y unos primeros pasos Blade necesita una **carpeta "cache"** (donde se guardara una cache de las vistas para su carga) y una **carpeta "views"** que será la carpeta donde guardaremos los archivos de plantilla. **Todas las vistas Blade** tienen que tener la **extensión ".blade.php"**. En la carpeta del proyecto en el que usemos blade creamos las carpetas **"public"**(será la parte accesible desde el servidor web), **"src"** (guardaremos las clases que vayamos a crear si es el caso), **"caches"** y **"views"**. En la carpeta **"cache"** el servidor web (Apache) necesita permiso de escritura. - Paquete de Blade: "Search for a package:" ponemos "laravel-blade" y elegimos la opción: "philo/laravel-blade". A veces el paquete puede no aparecer (puede haber cambiado el nombre, el desarrollador...), no pasa nada, vete a Packagist , desde su buscador localiza el paquete y sigue las instrucciones, que básicamente son poner unas líneas en tu archivo "composer.json" y hacer "composer install". O generar el archivo y hacer el "composer require" después como ya vimos. Para utilizar Blade, y suponiendo que estamos trabajando con la estructura de directorios que se propuso en el apartado anterior, simplemente tienes que añadir a tus páginas del directorio "public" lo siguiente: ```php= <?php require 'vendor/autoload.php'; use Philo\Blade\Blade; $views = '../views'; $cache = '../cache'; $blade = new Blade($views, $cache); echo $blade->view()->make('vista')->render(); ``` Esto me cargaría la vista "vista.blade.php" de la carpeta "views". Fíjate que solo hace falta poner el nombre de la vista y no la extensión ".blade.php". #### Funciones Blade Cada instrucción de Blade viene precedida de "@". - **@yield()**: Se usa para mostrar el contenido de una sección determinada. - **@extends()**: Se usa para llamar a la plantilla - **@section()**: Se usa para abrir una sección - **@endsection()**: Se usa para cerra una sección Ejemplo: *Plantilla* ```php= <!doctype html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scal <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- css para usar Bootstrap --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/ <title>@yield('titulo')</title> </head> <body style="background:#0277bd"> <div class="container mt-3"> <h3 class="text-center mt-3 mb-3">@yield('encabezado')</h3> @yield('contenido') </div> </body> </html> ``` *Vista* ```php= @extends('plantillas.plantilla1') @section('titulo') {{$titulo}} @endsection @section('encabezado') {{$encabezado}} @endsection @section('contenido') <table class="table table-striped"> <thead> <tr class="text-center"> <th scope="col">Código</th> <th scope="col">Nombre</th> <th scope="col">Nombre Corto</th> <th scope="col">Precio</th> </tr> </thead> <tbody> @foreach($productos as $item) <tr class="text-center"> <th scope="row">{{$item->id}}</th> <td>{{$item->nombre}}</td> <td>{{$item->nombre_corto}}</td> @if($item->pvp>100) <td class='text-danger'>{{$item->pvp}}</td> @else <td class='text-success'>{{$item->pvp}}</td> @endif </tr> @endforeach </tbody> </table> @endsection ``` ## Generación del interface de usuario En la carpeta "public" vamos a tener dos archivos: "familias.php" que se encargará de llamar a la vista "vistaFamilias.blade.php" y pasar las variables necesarias, y "productos.php" que hará lo mismo con la vista "vistaProductos.blade.php". Fíjate en el código. ```php= <?php require '../vendor/autoload.php'; use Philo\Blade\Blade; use Clases\Producto; $views = '../views'; $cache = '../cache'; $blade = new Blade($views, $cache); $titulo='Productos'; $encabezado='Listado de Productos'; $productos=(new Producto())->recuperarProductos(); echo $blade->view()->make('vistaProductos', compact('titulo', 'encabezado', 'productos') ``` - Con el "require" llamamos al archivo "autoload.php" de la carpeta "vendor". - Las líneas del "use" son para poder usar nuestras Clases y las de "Philo\Blade". - Las siguientes son para indicar la ruta relativa de las carpetas "views" y "cache" y guardarla en sendas variables. - En la siguiente nos creamos un objeto de la clase "Blade", le pasamos las rutas de las carpetas "views" y "cache" e inicializamos las variables que pasaremos a la vista: $titulo, $encabezado y $productos. - En la última línea llamamos a la vista: 'vistaProductos'de la carpeta "views" y le pasamos usando "compact()" las tres variables: $titulo, $encabezado y $productos. ```php= <?php require '../vendor/autoload.php'; use Philo\Blade\Blade; use Clases\Familia; $views = '../views'; $cache = '../cache'; $blade = new Blade($views, $cache); $titulo='Familias'; $encabezado='Listado de Familias'; $familias=(new Familia())->recuperarFamilias(); echo $blade->view()->make('vistaFamilias', compact('titulo', 'encabezado', 'familias')) ``` ## Preguntas 1. Antes de PHP5, el comportamiento cuando se pasaba una variable a una función era siempre el mismo, independientemente de si la variable fuera un objeto o de cualquier otro tipo: siempre se creaba una nueva variable copiando los valores de la original. - [x] Verdadero - [ ] Falso 2. En lugar de programar un método set para modificar el valor de los atributos privados en que sea necesario, puedo utilizar el método mágico __set - [ ] Verdadero - [x] Falso 3. ¿Cuál es la utilidad del operador de resolución de ámbito ::? - [ ] Nos permite hacer referencia a la clase del objeto actual. - [X] Se utiliza para acceder a los elementos de una clase, como constantes y miembros estáticos. 4. Si serializas un objeto utilizando serialize, ¿puedes almacenarlo en una base de datos MySQL? - [X] Verdadero - [ ] Falso 5. La función is_subclass_of recibe como primer parámetro: - [ ] Un objeto - [X] Un objeto o una clase 6. Si una subclase no tiene método constructor, y su clase base sí lo tiene, cuando se instancie un nuevo objeto de la subclase: - [X] Se llamará automáticamente al constructor de la clase base. - [ ] No se llamará automáticamente al constructor de la clase base. 7. ¿Cuál es el nombre de la función que se utiliza para hacer una copia de un objeto? - [X] clone - [ ] __clone 8. Si en tu código utilizas un interface, y quieres crear uno nuevo basándote en él: - [X] Puedes utilizar la herencia para crear el nuevo constructor extendiendo al primero. - [ ] No puedes hacerlo, pues no se puede utilizar herencia con los interfaces; solo con las clases. 9. En un namespace solo guardaremos las clases para evitar colisiones entre ellas. - [ ] Verdadero - [X] Falso 10. ¿Necesitamos usar el Framework Laravel pasar sacar ventajas del gestor de plantillas Blade ? - [ ] Verdadero - [X] Falso 11. Las plantillas que crees en Blade es preferible alojarlas: - [x] En un lugar no accesible por el servidor web. - [ ] En un lugar accesible por el servidor web. ###### tags: `DAW` `DSW` `UT5` `PHP`