Вы находитесь на странице: 1из 226

Documentacion Laravel

3.6-POO: Inyeccin de dependencias


en Laravel (IV)
Esta es la cuarta parte de la mini serie de inyeccin de dependencias en Laravel,
lee la primera, la segunda y la tercera antes de continuar.
Necesitas conocimientos bsicos de Laravel y POO para hacer este tutorial.

Vimos en captulos anteriores que la inyeccin de dependencias, pese a su
nombre complicado, es realmente un concepto simple que permite escribir objetos
desacoplados, es decir, que no sean dependientes uno del otro.

La inyeccin de dependencias nos permite disear ORMs que en vez de estar
atado a un solo motor de DB, reciban como parmetro clases MySQL o Postgresql
o incluso de MongoDB que funcionen siempre que cumplan con una interfaz.

El contenedor de inyeccin de dependencias es como una mquina
ensambladora que conecta una parte con otra y hace que todo el sistema
funcione.

Tambin vimos que manipular las dependencias de nuestro sistema puede ser
difcil, por eso el contenedor de Laravel es inteligente, y an as sigue siendo
simple! Para demostrarlo les cre un demo.
Bien ahora dejmonos de demos y vamos a usar el contenedor real de Laravel!

Para ensearles cmo usar la inyeccin de dependencias en Laravel necesito 3
pasos:

Primero crearemos una clase de ejemplo y luego la integraremos con el
contenedor de Laravel.

Paso 1: Clase Alert de ejemplo

Yo cre para uds. una mini versin de mi clase Alert que es un helper para enviar
mensajes del controlador a las vistas, en mi caso uso los estilos de Bootstrap pero
es adaptable.

<?php namespace Components;
use Illuminate\Session\Store as Session;
use Illuminate\View\Environment as View;
class Alert {
const SESSION_NAME = 'AlertMessages';
public function __construct(Session $session, View $view)
{
$this->session = $session;
$this->view = $view;
}
public function message($message, $type)
{
$messages = $this->session->get(static::SESSION_NAME,
array());
$messages[] = compact('message', 'type');
$this->session->flash(static::SESSION_NAME, $messages);
}
public function render($template = 'alert')
{
$messages = $this->session->get(static::SESSION_NAME,
null);
if ($messages != null)
{
$this->session->flash(static::SESSION_NAME, null);
return $this->view->make($template)-
>with('messages', $messages);
}
return "";
}
}

Esta clase tiene dos mtodos: message graba mensajes y render los muestra.

La clase usa la Sesin de Laravel para guardar mensajes entre una peticin y otra
y la clase de Vista para los templates.

Para usarla:

1. Dentro de app creen las carpetas y el archivo: app/library/Components/Alert.php
all copien y peguen el cdigo de arriba.
2. Abran composer.json y en autoload -> classmap agreguen
"app/library/Components" ejemplo:


"autoload": {
"classmap": [
...
"app/library/Components"

3. Ejecuten en la consola php artisan dump-autoload.
4. En la carpeta app/views creen un archivo llamado alert.blade.php y copien lo
siguiente:

app/views/alert.blade.php

@foreach ($messages as $msg)
<div class="alert alert-block alert-{{ $msg['type'] }} fade in">
<button type="button" class="close" data-
dismiss="alert">&times;</button>
<p><strong>{{ $msg['message'] }}</strong></p>
</div>
@endforeach
Esta es la plantilla que usar la clase Alert por defecto.

Veamos un ejemplo de cmo usarla, en un mtodo cualquiera de un controlador
agreguen esto:

$alert = new Components\Alert(App::make('session.store'),
App::make('view'));
$alert->message('Laravel es genial', 'info');
Asignen la variable $alert a la vista:

return View::make('admin/users/list')->with('alert', $alert);
Y en cualquier Vista simplemente:

{{ $alert->render() }}
Si usan una plantilla que implemente Bootstrap vern un bonito mensaje en azul
que dir Laravel es genial.
Con esto terminamos el paso 1.
Paso 2: Usar el contenedor de inyeccin de dependencias de Laravel

El cdigo anterior se enfrenta al menos a dos inconvenientes.
1. Usarlo es complicado, es decir instanciar la clase, es demasiado cdigo y difcil
de recordar:
$alert = new Components\Alert(App::make('session.store'),
App::make('view'));
De hecho podra ser peor, pero yo tom un atajo y us el contenedor de Laravel
(alias App) para traerme la clase de session y la clase de view:

App::make('session.store')
De lo contrario hara falta instanciar esas clases y cada una de sus dependencias,
lo cual podra volverse fcilmente unas 10 lneas de cdigo.
2. La clase y variable $alert debe pasarse siempre a la vista, de lo contrario
obtendremos un error de que la variable no est definida.
Con el contenedor de Laravel podemos resolver ambos problemas muy
fcilmente:
Usando los ServiceProviders
Laravel le llama Service Providers a las clases que almacenan la configuracin de
la inyeccin de dependencias, son como los ensambladores de la aplicacin.

1. Creen un archivo nuevo en app/library/Components/AlertProvider.php y peguen
este cdigo:
<?php namespace Components;
use Illuminate\Support\ServiceProvider;
use Illuminate\Foundation\AliasLoader;
class AlertProvider extends ServiceProvider {
public function register()
{
$this->registerAlert();
}
public function registerAlert()
{
$this->app->bind('alert', function($app)
{
return new Alert($app['session.store'],
$app['view']);
});
}
}
2. Ejecuten nuevamente php artisan dump-autoload.

3. Vamos a decirle a Laravel que queremos incluir este ServiceProvider en nuestra
App, vamos a app/config/app.php y en el array providers agregaremos
'Components\AlertProvider' a la lista:


'providers' => array(

...
'Components\AlertProvider'
),
4. Ya podemos instanciar nuestra clase Alert con el contenedor de dependencias!
Es decir:


$alert = App::make('alert');
$alert->message('Laravel es genial', 'info');
Paso 3: Uso de los Facades en Laravel
An App::make(alert) se ve algo extrao, no? A pesar de que es ms limpio, no
sera mejor tener algo como Route::get ? De hecho Route::get es lo que Taylor
Otwell llam facades.
Creemos el nuestro:
1. Creen el archivo app/library/Components/AlertFacade.php
2. Y coloquen lo siguiente:
<?php namespace Components;

use Illuminate\Support\Facades\Facade;
class AlertFacade extends Facade {
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor() { return
'alert'; }
}
2. Luego regresemos a nuestro ServiceProvider y vamos a crear
un Alias para el Facade:
<?php namespace Components;
use Illuminate\Support\ServiceProvider;
use Illuminate\Foundation\AliasLoader;
class AlertProvider extends ServiceProvider {
public function register()
{
$this->registerAlert();
$this->setAliases();
}
public function registerAlert()
{
$this->app->bind('alert', function($app)
{
return new Alert($app['session.store'],
$app['view']);
});
}
public function setAliases()
{
$this->app->booting(function ()
{
$loader = AliasLoader::getInstance();
// Facades
$loader->alias('Alert',
'Components\AlertFacade');
});
}
}
3. No olviden ejecutar el dump-autoload.
4. Una vez hecho estos tres pasos en nuestro controlador ya podemos usar el
Alert as:
Alert::message('Laravel es genial', 'info');
Noten que NO estamos instanciando la clase, por lo tanto tampoco necesitamos la
variable $alert, en la vista queda as:
{{ Alert::render() }}
Ms limpio y bonito imposible. Sin embargo noten que tampoco estamos haciendo
uso de clases estticas, lo cual es una mala prctica casi siempre, lo que ocurre
es que el Facade se encarga de interactuar con el contenedor de inyeccin de
dependencias de Laravel que a su vez instancia y almacena la clase por nosotros.

Es decir, cada vez que haz hecho Route::get o View::make en realidad estabas
trabajando con inyeccin de dependencias sin darte cuenta!.

Les recomiendo seguir la documentacin de Laravel IoC Container y Facades para
aprender ms de estos geniales conceptos.















1 - Laravel, un framework PHP
El 2012 sirvi para ver como la oveja negra a PHP. Todos se deslumbraban con
nuevos lenguajes/paradigmas como Node.js, Ruby On Rails y dems. Si
mencionabas PHP te comenzaban a ver como aquel hombre de 45 aos,
divorciado, con un trozo de pizza en su escritorio y programando en COBOL.



Es cierto que se resaltaron muchas de las carencias del tan popular PHP, pero
eso lejos de matarlo, lo fortaleci. Se empez a trabajar en versiones mejoradas,
se aprendi de los nuevos lenguajes y empezaron a llegar Frameworks de alto
nivel, prcticos, fciles de usar y con un futuro muy prometedor.
Laravel, un framework para PHP

He trabajado en un par de proyectos utilizando el Framework de Laravel para
PHP, y el resultado hasta ahora ha sido fantstico. La curva de aprendizaje es
relativamente sencilla.Nunca antes haba sido tan fcil: asociar una ruta a un
controller y a una vista,
crear restful APIs est a dos pasitos,
el ORM es tan prctico como cualquiera que se base en el patrn ActiveRecord
...en s es un Framework muy bien diseado.

Laravel se basa en la elegancia y simpleza. Programar ya no tiene que ser tan
doloroso y de hecho puede ser agradable con las herramientas
necesarias. Laravel es una de esas herramientas.

Est pensado para todos los programadores, inclusive los nuevos programadores
que estn iniciando con PHP, y ofrece grandes experiencias de desarrollo a los
programadores avanzados.
Gracias a la arquitectura nica de Laravel, posibilita a los desarrolladores a crear y
disear su propia infraestructura para sus aplicaciones de la manera ms flexible.

Para m, Laravel, es la bandera ms fuerte que me hace seguir apostando por
PHP. Debo mencionar que he hecho proyectos con Node.js, y me parece muy
bueno, no estoy casado con ningn lenguage, simplemente creo que an hay
muchas razones para seguir trabajando con PHP. Se habla mucho de de las
diferencias de performance, en casos prcticos se invita a que se demuestre eso,
por ejemplo, aqui Node.js tarda 0.389 seconds en procesar 1000 requests, en
cambio PHP 0.130 seconds.
No dejen de leer este artculo donde dan mas detalles de las cosas buenas que se
vienen para PHP.



4 - Cmo usar mltiples bases de
datos en Laravel
Laravel hace posible la conexin a diferentes bases de datos de la manera ms
fcil posible, actualmente soporta los motores de base de datos ms
populares:MySQL, PostgreSQL, SQLite y SQLServer, y por eso nos hace
siempre felices.
En aplicaciones y proyectos web sencillos es comn tener una conexin a una
sola base de datos, la cual es ms que suficiente para almacenar y leer la
informacin administrada por nuestro proyecto. En aplicaciones web ms
robustas, de mayor tamao o con requerimientos muy especiales surge la
necesidad de utilizar mltiples bases de datos, una para leer, otra para escribir la
informacin o tal vez una base de datos que tiene algn propsito especial en otro
sistema.
Configuracin

Primero que todo debemos realizar la configuracin de las conexiones, esta
configuracin se hace en el archivoCdigo:
app/config/database.php
.
En este archivo puedes establecer la configuracin para todas las bases de datos
que necesites, de forma predeterminada Laravel provee cuatro configuraciones
de ejemplo para cada uno de los motores de base de datos mencionados:

Cdigo :
'connections' => array(
'sqlite' => array(
'driver' => 'sqlite',
'database' => __DIR__.'/../database/production.sqlite',
'prefix' => '',
),

'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),

'pgsql' => array(
'driver' => 'pgsql',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
),

'sqlsrv' => array(
'driver' => 'sqlsrv',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => '',
'prefix' => '',
),

),

Si necesitas una nueva conexin solo basta con aadirla al arreglo de conexiones
y establecerle un nombre nico:

Cdigo :
'connections' => array(

'stark' => array(
'driver' => 'mysql',
'host' => 'westeros',
'database' => 'database',
'username' => 'JonSnow',
'password' => 'Y0uN0th1ngJ0nS4nw',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),

'lannister' => array(
'driver' => 'mysql',
'host' => 'westeros',
'database' => 'database',
'username' => 'Joffrey',
'password' => 'Wh0R3memb3rTh4atL1ttleB1tch?',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),

),


En el archivo de configuracin tambin se puede establecer la conexin de base
de datos que se usar de forma predeterminada, es la opcin siguiente:
Cdigo :
'default' => 'mysql'
Uso de mltiples conexiones en Laravel

El uso de diferentes conexiones es, como bien sabemos, muy fcil e intuitivo en
Laravel:
Esquema
Para definir el esquema de base de datos usa el mtodo:
Cdigo :
Schema::connection

Cdigo :
Schema::connection('stark')->create('deaths', function($table)
{
$table->increments('id');
$table->string('type');
$table->string('name');
});
Consultas
Si ests usando el constructor de consultas simples usa el mtodo:
Cdigo :
DB::connection

Cdigo :
$users = DB::connection('lannister')->select(...);
Eloquent
Si ests usando Eloquent puedes definir la conexin de base de datos en el
modelo a travs de la propiedad.
Cdigo :
$connection


Cdigo :
<?php
class Death extends Eloquent {

protected $connection = 'stark';

}


Tiempo de ejecucin
Si necesitas cambiar de conexin de base de datos durante la ejecucin de alguna
funcin puedes hacerlo con el mtodo:
Cdigo :
setConnection

el cual recibe como parmetro el nombre de la conexin:
Cdigo :
<?php

class KillController extends BaseController {

public function decapitate()
{
$death = new Death;

$death->setConnection('lannister');

$joffrey = $death->find(1);

return $joffrey;
}

}


Como vimos Laravel ofrece soluciones sencillas a los problemas comunes que
surgen en nuestras aplicaciones web.





4.1 - Anlisis y extensin de clases
en PHP con ReflectionMethod
Reflection es una clase o ms bien un conjunto de clases de PHP que permiten
saber todo sobre tus otras clases, mtodos, funciones, parmetros, etctera...
Quizs es una de las funcionalidades ms c00l que PHP ha agregado
recientemente y quizs una de las que menos se conoce o se
usa: ReflectionMethod.

Por ac les dejo un cdigo que me pareci bastante prctico y su siguiente
explicacin:

Supongamos que necesitan llamar a un mtodo de una clase (un controlador o
algo as) usando call_user_func_array desde alguna parte de nuestro script, pero
antes de llamarlo directamente, quieren validar que:
El mtodo a llamar sea pblico.
La cantidad de parmetros enviados no es menor que la cantidad de parmetros
requeridos por el mtodo.
Y adicionalmente les gustara no slo pasar los parmetros como parmetros
ordinarios, sino tambin tenerlos disponibles en una clase aparte, es decir, que al
llamar a una funcin como:
Cdigo :
function verLista($year, $month)

Con los siguientes valores:

Cdigo :
call_user_func_array(array($controller, 'verLista'), array(2008,
10));


Permita generar en el Controller un objeto con los siguientes valores:

Cdigo :
$this->params->year = 2008;
$this->params->month = 10;

Lo cual tal vez sera util si ms adelante se necesita pasar estos valores de un
mtodo a otro dentro del controlador sin necesidad del uso de parmetros y si se
quiere agregar una seguridad extra al script (como bloquear la posibilidad de
sobreescribir o reemplazar parametros)
En fin, esta es la idea.. Aqu el cdigo:
Primeramente tenemos una clase bsica llamada ControllerParams que permite
guardar y obtener datos / parmetros:
Cdigo :
class ControllerParams
{

private $params = array();

function __set($name, $value)
{
$this->params[$name] = $value;
}

function __get($name)
{
return $this->params[$name];
}

}


Y aqu el mtodo que hace la funcionalidad ya descripta:

Cdigo :

class Controller
{

protected $params = null;

final function execute($action, $params = null) //funcion
intermedia
{

$reflectionMethod = new ReflectionMethod($this, $action);
//se crea una instancia de ReflectionMethod con la referencia al
metodo que necesitamos llamar

//asi ya tenemos disponible las funcionalidades de
ReflectionMethod:

if(($action == 'execute') || !$reflectionMethod-
>isPublic() || (count($params) < $reflectionMethod-
>getNumberOfRequiredParameters()))
{
//LANZAR ERROR
}

$parametros = $reflectionMethod->getParameters(); //con
esto obtenemos los parametros de nuestro metodo

$this->params = new ControllerParams();

foreach($parameters as $key => $parameter) //y hacemos un
ciclo con ellos
{
$name = $parameter->getName(); //obtenemos el nombre

if(isset($params[$key])) //si el usuario mand algun
valor lo asignamos
{
$this->params->$name = $params[$key];
}
else
{
$this->params->$name = $parameter-
>getDefaultValue(); //sino tambien podemos tomar el valor por
defecto
}

}

call_user_func_array(array(&$this, $action), $params);
//y por ultimo hacemos el llamado de costumbre
}

}


Ntese que los parmetros son tambin objetos con funcionalidades ...
















Redimensionar imgenes en PHP
con clases abstractas
Las clases abstractas en la programacin orientada a objetos son clases de las
que no se pueden crear instancias/objetos directamente de ella.
Para qu defino una clase como abstracta si no puedo crear objeto de
ella?

Si puedes crear instancias pero solo de clases que hereden dicha clase (que no
sean abstractas por supuesto). El objetivo principal de la herencia es mejorar la
clase heredada. As que sabiendo esto, las clases abstractas en su ms pura
esencia son clases mejorables!
Una clase abstracta puede tener mtodos y propiedades como cualquier otra
clase.

Cuando debo definir una clase abstracta?

Cuando puedas crear diferentes clases que tengan propiedades y mtodos
comunes, y an sabiendo que en el futuro que puedes crear ms clases del mismo
tipo.

En la clase abstracta se definiran las propiedades y mtodos comunes, para que
las clases que la hereden no tengan la necesidad implementar esos mtodos o
definir las propiedades.
Mtodos Abstractos

As como hay clases abstractas, tambin hay mtodos abstractos. Estos mtodos
no son implementados en su definicin, pero obliga a las clases que hereden el
mtodo a implementarlo.
Un mtodo abstracto se puede definir en casi cualquier clase, no necesariamente
debe ser una clase abstracta. Un ejemplo en las que no se deberan definir
mtodos abstractos serian en las clases finales, pues no se podran implementar.

Las clases finales: son las clases engredas en la POO su lema principal: Nadie
me puede mejorar!. Es decir, que no se pueden heredar. Entonces se podra decir
que son las opuestas a las clases abstractas que son la de baja autoestima su
lema: "Soy intil sola, mejorame por favor ".
Redimensionar imgenes en PHP usando clase abstracta

Definimos una clase abstracta llamada ImageBase. Todas las clases que hereden
esta clase tendrn:
Las propiedades width y height, con sus respectivos setters y getters.
Adems de dos metodos comunes los cuales son: gdFromFile y gdToFile.
Obliga a la clase que le herede a implementar el metodo save

Cdigo :
abstract class ImageBase
{
protected $width;
protected $height;

public function setWidth($w)
{
// gd solo maneja enteros, ergo obligamos que ancho sea
entero.
$w = (int) $w;
// ancho debe ser mayor que 0
if ($w > 0) $this->width = $w;
}

public function getWidth()
{
return $this->width;
}

public function setHeight($h)
{
// gd solo maneja enteros, ergo obligamos que alto sea
entero
$h = (int) $h;
// alto debe ser mayor que 0
if ($h > 0) $this->height = $h;
}

public function getHeight()
{
return $this->height;
}

/**
* Genera una imagen gd del archivo con nombre $filename
* Retorna FALSE si ocurrior algun error, por ejemplo: el
tipo no es soportado
*
* @param string $filename nombre del archivo
* @param int $type Tipo de imagen para saber que funcion
usar
* @return resource Una imagen gd.
*/
protected function gdFromFile($filename, $type)
{
$gd = false;
switch ($type)
{
case IMAGETYPE_PNG:
$gd = imagecreatefrompng($filename);
break;
case IMAGETYPE_JPEG:
$gd = imagecreatefromjpeg($filename);
break;
case IMAGETYPE_GIF:
$gd = imagecreatefromgif($filename);
break;
}
return $gd;
}

/**
* Guarda una imagen gd en el archivo de nombre $filename
*
* @param resource $gd La imagen a guardar
* @param string $filename nombre del archivo
* @param int $type Tipo de imagen para saber que funcion
usar
* @return bool TRUE en caso de exito, FALSE en caso
contrario
*
*/
protected function gdToFile($gd, $filename, $type)
{
$success = false;
// si $filename es nulo las funciones posteriores
imprimiran en la salida directamente
// aqui tratamos de evitar eso
$filename = (string) $filename;
if (trim($filename) != "")
{
// no tiene sentido verificar si el archivo existe,
pues si no existe se creara
// las siguientes funciones retornan false si
ocurrio algun error, true en caso de exito
switch ($type)
{
case IMAGETYPE_PNG:
$success = imagepng($gd, $filename);
break;
case IMAGETYPE_GIF:
$success = imagegif($gd, $filename);
break;
case IMAGETYPE_JPEG:
$success = imagejpeg($gd, $filename);
break;
}
}
return $success;
}

// Obligamos a que las clases que hereden esta clase
implementen este mtodo
/**
* La intencion de este metodo es que guarde la imagen
creada en un archivo
*
* @param string $filename Nombre del archivo
* @return bool TRUE en caso de exito, FALSE en caso
contrario
*/
abstract public function save($filename);
}


Creamos ImageResize que hereda ImageBase.
Cdigo :
class ImageResize extends ImageBase
{

private $src;
private $origWidth;
private $origHeight;
private $origType;
private $hasError = false;

public function __construct($src)
{
$this->setSrc($src);
}

private function setSrc($src)
{
if (is_file($src))
{
// getimagesize retorna un arreglo si tuvo exito con la
informacion de la imagen
// false en caso contrario
$info = getimagesize($src);
if ($info !== FALSE)
{
$this->src = $src;
$this->origWidth = $info[0]; // ancho de la imagen
$this->origHeight = $info[1]; // alto de la imagen
$this->origType = $info[2]; // constante de php que
tiene el tipo de imagen, un entero

// por defecto usaremos las dimensiones de la imagen
original
$this->resize($this->origHeight, $this->origHeight);
}
else
{
$this->throwError("$src is not an image file",
E_USER_ERROR);
}
}
else
{
$this->throwError("$src is not file valid",
E_USER_ERROR);
}
}

/**
* Asigna los valores a los que se redimensionara la imagen
*
* @param int $w ancho
* @param int $h alto
*/

public function resize($w, $h)
{
if ($w < 1) $this->throwError("Ancho debe ser mayor que
0", E_USER_NOTICE);
if ($h < 1) $this->throwError("Alto debe ser mayor que
0", E_USER_NOTICE);
$this->setWidth($w);
$this->setHeight($h);
}

/**
* Redimensiona la imagen con el ancho y alto asignado en
resize
* y la guarda en el archivo de nombre $filename
*
* @param string $filename nombre del archivo
* @return bool TRUE en caso de exito, FALSE si algo salio
mal
*/

public function save($filename)
{
$success= false;
// obtenemos la imagen en gd del archivo
$orig = $this->gdFromFile($this->src, $this->origType);
if ($gd !== FALSE) // si lo obtuvimos
{
// creamos una imagen vacia con ancho y alto, servira
de contenedor
$base = imagecreatetruecolor($this->width, $this-
>height);

// aqui redimensionamos la imagen
// la imagen redimensionada queda en $base, esta
funcion retorna TRUE si tuvo exito, FALSE en caso contrario
$resized = imagecopyresampled($base, $orig, 0, 0, 0,
0, $this->width, $this->height, $this->origWidth, $this-
>origHeight);
if ($resized) // pudimos redimensionar
{
// guardamos gd en el archivo $filename
if (!$this->gdToFile($base, $filename, $this-
>origType))
{
$this->throwError("Archivo no generado",
E_USER_WARNING);
}
else
{
// todo salio bien
$success = true;
// liberamos los recursos gd
imagedestroy($base);
imagedestroy($orig);
}
}
}
else
{
$this->throwError("Gd no fue generado.",
E_USER_WARNING);
}
return $success;
}

private function throwError($msg, $level)
{
trigger_error($msg, $level);
}
}
?>


Uso de ImageResize

Cdigo :
<?php
$src = "archivo.jpg";
$dest = "archivo150x150.jpg";
$resize = new ImageResize($src);
$resize->resize(150,150);
if (!@$resize->save($dest))
{
echo "Archivo no fue generado. Error: " . error_get_last();
}
else
{
echo "Archivo $dest generado.";
}
?>



Qu otra clase pudiera heredar ImageBase?


Que tantas clases puede crear con la libreria gd de php?
Captcha: una clase que genere captcha.Grficos: una clase que genere
grficos.Thumbs: si no te gusta ImageResize, mejorala o crea tu propia clase.

Se te ocurre una otra? Comenta aqu.
Nota: la implementacin de ambas clases se pueden mejorar. La nica intencin
de estas implementaciones es mostrar un ejemplo real de como se deben usar y lo
til que son las clases abstractas.

















1.3 - Porqu elegir Laravel en vez de
Codeigniter
Empezar a programar con PHP nunca ha sido sencillo. El sitio oficial tiene una
documentacin muy completa de todas las funcionalidades del lenguaje, sin
embargo, no es un buen punto de partida para aprender a hacer algo
funcional, por ejemplo un mdulo con PHP.



Empezando mi carrera autodidacta para ser desarrollador web, recuerdo
que imprim TODA la documentacin de PHP y la le completa durante unas
vacaciones.

Hice lo mismo con la documentacin de MySQL. Al final no saba hacer
NADA.

S me sirvi de referencia aprender qu hacan las funciones del lenguaje,
aunque hoy en da sigo consultando el sitio a menudo.

Entonces comenc a buscar tutoriales ms prcticos de PHP. Por
ejemplo las memorias de un aprendiz. Alguien lo recuerda?

Pero hoy en da si quieres trabajar con PHP adems tienes que:
Elegir el Framework adecuado

Esto quiere decir que tenga:

Un desarrollo activo: te garantiza correccin de problemas de seguridad,
mejoras, etc.
Una comunidad activa: la vas a necesitar cuando no sepas cmo hacer
algo.
Buena documentacin: puede ser el mejor framework del mundo pero si
nadie sabe cmo usarlo no sirve de nada.


Pero la mayora de los frameworks ya tienen
eso: Symfony, Codeigniter, Laravel, entre otros, entonces:
Cul framework elegir?

Hace unos aos atrs era una respuesta difcil, mi decisin estaba entre
Symfony y Codeigniter, a m me gustaba ms Symfony pero mi equipo de
trabajo prefera el segundo.

Symfony era y sigue siendo complejo, muy difcil de aprender, por otro lado,
CodeIgniter muy fcil de aprender porque es muy simple, carece de muchas
utilidades necesarias en un verdadero framework.

En Symfony 1.4 gastaba el 80% del tiempo investigando cmo hacer algo y
corrigiendo bugs y el 20% ejecutando, mientras que en CodeIgniter solo
20% investigando pero 80% ejecutando.
De vuelta al 2013

Hoy en da Symfony 2 es el framework para PHP ms robusto que
existe, Fabien Potencier, su creador, es una mquina escribiendo cdigo. Es
increble tener en PHP componentes como el DOM crawler (disponible tambin
en Laravel) que te permite recorrer y revisar desde PHP el cdigo HTML
como lo haras conFirebug y eso se lo debemos a Fabien.

Sin embargo, Symfony parece no estar escrito para seres humanos.
Slo algunos pocos privilegiados son capaces de aprovechar todo su potencial.

Lo que hace que muchos se hayan ido a CodeIginter, pero
Porqu elegir Laravel en vez CodeIgniter

CodeIgniter no ofrece nada ms all de sencillez, despus de leerte su
documentacin en un da y tener que enfrentarte a las necesidades de un
proyecto real quedas en frente de una carpeta de modelos vaca preguntndote
Y ahora qu? Es all donde:
Si eres experto, instalas plugins o construyes un sub-framework encima de
CodeIgniter para suplir sus carencias.
Si eres principiante empiezas a lanzar un montn de lneas de cdigo en un
controlador.


Codeigniter miente y no tiene ORM propio
Slo tiene un constructor de queries que ellos dicen que es una versin
modificada del patrn de diseo Active Record pero eso es falso.

El patrn Active Record permite trabajar tus tablas como si fueran clases y
tus filas como objetos, con Laravel puedes (as como con Ruby on Rails):
Cdigo :
$user = new User;
$user->name = Duilio;
$user->save(); // This is awesome


En Codeigniter sera esto:
Cdigo :
$this->db->insert(users, array(name => Duilio); // No active record
at all


PHP 5 en adelante est orientado a poner a disposicin de sus
programadores el potencial de la programacin orientada a objetos. Si bien
el enfoque de la base de datos de Codeigniter fue funcional en un tiempo, ya
qued en el pasado.

Laravel en constraste tiene un ORM llamado Eloquent y adems tiene un
constructor de queries llamado Fluent, ambos superan al Active record del
otro framework.

No incentiva al uso de plantillas en las vistas
En Codeiginiter:
Cdigo :
<ul>

<?php foreach ($addressbook as $name):?>

<li><?=$name?></li>

<?php endforeach; ?>

</ul>


Contrastado con Laravel:
Cdigo :
<ul>
@foreach ($addressbook as $name)

<li>{{ $name }}</li>

@endforeach

</ul>


La documentacin de CodeIgniter miente de nuevo al decir que los pseudo-
lenguajes de plantillas, como el sistema de plantillas Blade de Laravel, son ms
lentos en ejecutarse. Esto no es cierto porque todos al final se compilan a
cdigo PHP, y lo que se leer una y otra vez ser PHP y no pseudo-
lenguaje.

CodeIgniter ofrece un parser de plantillas muy simple, pero ste pierde el
concepto de un VERDADERO lenguaje de plantillas: convertir etiquetas de
<?=name?> a {{ name }} es slo la punta del iceberg.

Un verdadero lenguaje de plantillas debe tener herencia de plantillas
(layouts) y muchas otras caractersticas que Smarty, Twig poseen,
all Blade de Laravel no se queda muy atrs.

Super Controlador al rescate...
Como Codeigniter es tan bsico, muchos programadores terminan
escribiendo la mayor parte de la lgica de sus aplicaciones en un solo lugar:
el controlador.

Por ejemplo la clase de rutas es tan simple, que se queda corta en los
proyectos de la vida real y no queda ms que lidiar con los segmentos de
las URL desde el controlador, donde ya tu aplicacin debera saber qu
hacer.

Incluso en el mismo ncleo de Codeigniter, el controlador es una especie de
super clase que est a cargo de casi todo, como lo demuestra esta imagen:



Al tratar de solucionar todos los problemas en una sola capa estars
escribiendo un cdigo difcil de leer y mantener y no estars aprovechando
las funcionalidades que un framework en el ao 2013 debe tener para ti.

Laravel tiene rutas, modelos, eventos, filtros, etc. que permiten que tus
controladores puedan verse as:
Cdigo :
public function edit($user)
{
return View::make('admin.users.form')->with('form', $form);
}


Puedes configurar una URL users/{id} para que Laravel consulte la BD por
ti, te traiga el usuario correspondiente a la ID o lance un 404 si no es
encontrado, todo eso antes de llegar al controlador.

En contraste con lo que sera Codeigniter:
Cdigo :
public function edit($id)
{
$user = $this->db->select('users', array('id' => $id));

if (is_null ($user)) $this->error404();

//etc...
}


Revisen la documentacin de Codeigniter vs la de Laravel en el tema de rutas
y comparen la diferencia.
Laravel es FCIL

Hace aos justificaba que la gente trabajara con Codeigniter, Symfony es
muy complejo y otras alternativas como CakePHP son inciertas.

Hoy en da en el mundo de PHP tenemos un framework que est bien
hecho, combina las mejores prcticas de desarrollo y hace que nosotros,
programadores de PHP podamos escribir un cdigo del cual sentirnos
orgullosos.

En tu primer proyecto con Laravel usars el 40% del tiempo para
documentarte, otro 40% para desarrollarlo y un 20% para contemplar
cun genial qued tu cdigo.

Saludos!












2 - Introduccin a Laravel
Laravel es uno de los frameworks ms fciles de aprender para
PHP, yo dira que tan fcil como Codeigniter. Sin embargo en
Laravel, fcil no quiere decir simple. Este potente framework
combina los features ms modernos de PHP para brindarnos una
interfaz elegante y hasta divertida de usar:

Quieren una ruta?
Cdigo :
// En app/routes.php:
Route::get(welcome, function() {
return Bienvenidos a Laravel;
});


Ahora quieren usar vistas con HTML?
Cdigo :
<!-- En app/views/welcome.blade.php: -->
<h1>Bienvenidos a Laravel</h1>


Quieren que la vista tenga un header y un footer? Laravel usa un
concepto ms potente llamado Layout. Cambiamos nuestra plantilla
welcome.blade.php a:
Cdigo :
@extends(layout)

@section(content)
<h1>Bienvenidos a Laravel</h1>
@stop



Y ahora creamos nuestro Layout

Cdigo :
<!-- En app/views/layout.blade.php -->
<!doctype html>
<html>
<head>
<title>Hacer vistas en Laravel es muy sencillo</title>
</head>
<body>
@yield(content)
</body>
</html>


Cuando usemos nuestra vista "welcome", Laravel cargar
automticamente la vista layout por nosotros, y reemplazar en la
plantilla layout la lnea @yield('content') por todo el HTML que
hayamos escrito en la plantilla welcome entre @section('content') y
stop, quedando el resultado as:
Cdigo :
<!doctype html>
<html>
<head>
<title>Hacer vistas en Laravel es muy sencillo</title>
</head>
<body>
<h1>Bienvenidos a Laravel</h1>
</body>
</html>

De esta forma tendremos 1 solo layout que usaremos en todas
nuestras vistas, evitando repetir el cdigo.

Ahora usar nuestras vistas es tan fcil como esto:
Cdigo :
Route::get(welcome, function() {
return View::make(welcome);
});


Y as en adelante Quieren hacer una redireccin?
Cdigo :
return Redirect::to(goodbye)


Generar una URL?
Cdigo :
URL::to(welcome)


Que tal si quisiramos pasar parmetros dinmicos a nuestra
vista? Tan fcil como esto:
Cdigo :
View::make(welcome)->with(name, Duilio);


Nuestra vista welcome.blade.php quedara de la siguiente manera:
Cdigo :
<h1>Bienvenido, {{ name }}</h1>


O as (si prefieren usar PHP directamente):
Cdigo :
<h1>Bienvenido, <?php echo $name ?></h1>



Caractersticas de la versin 4 de Laravel

Lo ms interesante de la versin 4 de Laravel es que detrs de toda
esta interfaz tan fcil de usar se esconde una arquitectura bastante
slida (SOLID).

Por ejemplo, los mtodos estticos que vimos hace poco no son
ms que una fachada (Facade). Por debajo se hace el llamado al
contenedor de Laravel, el cual maneja todas las dependencias entre
las clases del framework y de nuestra aplicacin.

Tanto si entendiste o no el ltimo prrafo, tanto si eres un entusiasta
que busca hacer sitios web de forma rpida y simple, o eres un
experto que busca crear una robusta aplicacin, fcil de mantener y
probar: Laravel es el framework para ti.

La idea de este set de tutoriales es ensearlos a usar Laravel desde
lo ms bsico (rutas, vistas, formularios, bases de datos) hasta lo
ms avanzado (inyeccin de dependencias, pruebas unitarias).









2.1 - Cmo instalar Laravel y
Composer
En el captulo anterior de Introduccin a Laravel les mostr un poco
sobre la fcil sintxis de Laravel. Tambin les mencion brevemente
que detrs de esta interfaz que nos permite casi hablarle al
framework: redireccioname a, haz una vista con este
parmetro/valor, debajo de todo eso se esconde una
arquitectura SLIDA de desarrollo, haciendo a Laravel un
framework de PHP ideal tanto para principiantes como para
expertos.

Mi intencin era despertar la curiosidad en la herramienta, si ests
ac, quizs tuve xito. Ahora es momento de ver cmo instalar
Laravel y Composer.


Requisitos para Instalar Laravel

Laravel es un framework para PHP, obviamente tiene como
requisito tener instalado... PHP, en este caso, la versin de PHP
5.3.2. Adems necesitaremos laextensin MCrypt de PHP.
Tambin necesitan un servidor web como Apache y una base de
datos como MySQL. Hay cientos de artculos sobre cmo
conseguir todo esto, tambin hay herramientas como XAMPP que
instalan todo esto por t.



Ms adelante necesitarn el mdulo Rewrite (mod_rewrite) de
Apache. Si han trabajado antes con otros frameworks sabrn de
qu les hablo, sino, por ahora les comento que es un mdulo que
hace posible URLs amigables como las de Cristalab:
Cdigo :
cristalab.com/tutoriales/introduccion-a-laravel-c111339l/

En vez de:Cdigo :
cristalab.com/tutoriales.php?id=c111339I.

Estas son tiles para los motores de bsqueda y tambin para los
usuarios. En otro tutorial hablaremos de esto.

Tambin necesitarn un conocimiento bsico de PHP, es un
plus si saben de programacin orientada a objetos o si ya han
usado otros frameworks. Igual tratar de explicar todo
detalladamente y adems tenemos la seccin de comentarios donde
pueden hacer preguntas, con suerte adems de m, otros usuarios
tambin quieran ayudar a aclarar dudas.


Cmo instalar Laravel y Composer

Si tienen experiencia con PHP sabrn que ste es un lenguaje
interpretado, bsicamente una library para PHP (un framework por
ej.) no es ms que una serie de archivos .php dentro de carpetas
dentro de sub-carpetas, y para instalarlo por lo general no hace falta
ms que descargar archivos de un repositorio GIT o de una pgina,
descomprimirlos en algn lado y listo.

Para instalar Laravel 4, hace falta un paso extra. Pero no nos
preocupemos, en realidad es una ventaja que nos pondr no slo a
Laravel sino a miles de paquetes a nuestra disposicin, me refiero a
Composer.


Composer

Composer es un excelente manejador de paquetes y
dependencias entre paquetes para PHP.




Qu son dependencias y paquetes?
Imagina que tienes un pequeo proyecto como ir de viaje de una
ciudad a otra y para hacerlo necesitas un medio de transporte, en
este caso, digamos, un automvil.

Si fueras un programa de software el automvil sera un paquete, y
tu viaje sera la aplicacin que "depende" de l.

Entonces, en este caso, Composer viene siendo como el personaje
Tank de la pelcula Matrix, t le dices Composer, necesito un auto
para mi viaje y Composer se encarga de buscar el paquete auto e
instalarlo para ti. Luego auto le dir a Composer que necesita
tambin un paquete motor, otro paquete sistema de frenos, y as
sucesivamente. Composer ir buscando e instalando cada
paquete y las dependencias de cada subpaquete,
recursivamente, hasta armar el auto, todo lo cual ser transparente
para ti.


Cmo instalar Composer

Aqu tienen las instrucciones de la pgina oficial, bsicamente hay
dos formas:


Instalar Composer en Linux:

Ejecuten desde su consola el siguiente comando:
Cdigo :
curl -sS https://getcomposer.org/installer | php


O si no tienen CURL instalado:
Cdigo :
php -r
"eval('?>'.file_get_contents('https://getcomposer.org/installer'
));"


Si todo sale bien ya podrn usar Composer con el siguiente
comando:
Cdigo :
php composer.phar


Instalar Composer globalmente.
Es mejor instalar y tener disponible Composer en todo todo el
sistema, para ello hay que renombrar el archivo a composer (sin
extensin) y moverlo a /usr/local/bin.

Si no tienes el directorio /usr/local/bin puedes ejecutar echo $PATH
en la consola para obtener las carpetas adecuadas.



Instalar Composer en Windows:
Descarga el instalador desde aqu o desde la pgina oficial (para
desconfiados), ejectalo y presiona: siguiente, siguiente, finalizar.



Tambin les har falta una consola de GIT, yo uso sta. Mismo
proceso: descarguen, ejecuten, siguiente, siguiente, finalizar.




Instalar Laravel

Una vez instalado composer, usando la consola/terminal (si estamos
en Windows usaremos la consola de GIT que recien instalamos),
vamos a nuestra carpeta de proyectos, por ejemplo: cd /var/www o
/home/usuario/proyectos_web/ o /c/xampp/httpdocs/ y all tipeamos:

Cdigo :
composer create-project laravel/laravel pruebalaravel



Para usuarios de Linux que no instalaron Composer globalmente:

(El comando sera php composer.phar y necesitaran obviamente
tener el archivo composer.phar en la misma carpeta desde donde
ejecutan el comando)

Tiempo de ir por un caf.

Mientras nos tomamos un descanso, Composer se encargar de
descargar el proyecto base de Laravel, el framework y todas sus
dependencias.

Si son curiosos vern cmo la consola va descargando decenas de
paquetes que sern usados por Laravel ms adelante.



Algunos de estos paquetes pertenecen al framework Symfony.


Symfony?

S, antes cuando elegamos un framework como Codeigniter,
Symfony o Cake, elegamos una herramienta y descartbamos las
otras. Si nos gustaba lo fcil que era Codeigniter pero tambin nos
gustaba el ORM de symfony 1.4 tenamos que decidirnos por uno o
por otro, o elegir Codeigniter y buscar en foro tras foro cmo integrar
el ORM usado por symfony nativamente (Doctrine 1.2 en este caso)
en Codeigniter, cruzar los dedos y esperar que todo saliera bien.

O supongamos que queramos crear un nuevo CMS para PHP, pero
an as estbamos totalmente satisfechos con la forma en cmo
symfony maneja las rutas. No haba forma fcil de usar slo las
rutas de symfony, porque era un framework "acoplado" y tenamos
que elegir usar todo o nada.

Con la salida de proyectos como Symfony 2 y Composer, esto
cambi radicalmente. De hecho la versin Symfony 2 fue
liberada como un conjunto de componentes que pueden ser usados
por separado, de manera que proyectos como Drupal 8 integran
ciertos componentes de Symfony, y as lo hace Laravel.


Todo lo cual lleva el desarrollo de PHP a otro nivel, donde
nosotros, los programadores podemos aprovechar el trabajo de
otros y fcilmente poner parte de nuestro trabajo al alcance de
otros, en vez de seguir reinventando la rueda una y otra vez.


Pero volviendo a la instalacin de Laravel...

Una vez que se complete la descarga de los paquetes, verificamos
nuestro directorio, el cual debe lucir similar a ste:



..con todas las carpetas instaladas por Composer.

Y, como personas impacientes que somos, tambin iremos
corriendo al navegador, y tipearemos, en mi caso:
Cdigo :
http://localhost/laravelpruebas/public



Directorio pblico:

(Es importante acceder a la carpeta /public que es la puerta de
nuestro proyecto para la web, ms adelante veremos esto en
detalle)

Y si todo ha salido bien:


Si leste you have arrived en tu navegador, ests listo para la
tercera parte, sino tienes varios das, los comentarios de abajo y
Google para investigar qu sali mal y prepararte para la siguiente
entrega, donde explicar lo que contienen las carpetas y archivos
instalados por Composer, entre otros temas.

Stay tuned
2.2 - Configurar Base de Datos y
crear tablas con Laravel
En los tutoriales anteriores, vimos una introducin al framework
Laravel y aprendimos cmo instalar Laravel y Composer. De
ahora en adelante comenzaremos un tutorial terico - prctico de
Laravel.


Crear un mdulo de Usuarios con Laravel

Si bien no es el mdulo ms emocionante del mundo, lo considero
prctico dado que hace falta en la mayora de las aplicaciones. Para
comenzar, necesitamos configurar nuestra base de datos y crear la
tabla de usuarios.


Cmo configurar la base de datos en Laravel

Lo haremos en cuatro sencillos pasos:

1 - Abrimos el archivo database.php localizado en:
Cdigo :
app/config/database.php


2 - En la lnea 29, encontraremos lo siguiente:
Cdigo :
'default' => 'mysql'


Si estamos trabajando con MySQL, como es mi caso, dejaremos la
lnea intacta, sino editaremos el valor entre comillas a sqlite, pgsql,
etc. segn sea el caso.
Entre las bases de datos soportadas por defecto en Laravel
encontramos: MySQL, SQL Lite, PostgreSQL y SQL Server.

3 - Usamos PHPMyAdmin o cualquier otra herramienta de nuestra
preferencia para crear la base de datos, en mi caso,
con PHPMyAdmin y MySQL crear una DB llamada
pruebalaravel:
Cdigo :
CREATE DATABASE `pruebalaravel` ;


4 - Una vez creada la DB debemos indicarle a Laravel el nombre de
nuestra base de datos y un usuario con acceso a ella, para MySQL
tenemos en el mismo archivo database.php lo siguiente (lnea 55):
Cdigo :
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'pruebalaravel',
'username' => 'root',
'password' => 'CLAVE_ULTRA_SECRETA',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),


All cambiamos database por el nombre de nuestra base de datos:
Cdigo :
'database' => 'pruebalaravel',


Y ms abajo el usuario que hayan configurado cuando instalaron
MySQL, comnmente root, luego, en la lnea siguiente, el password
que dependiendo de su instalacin pudiese estar en blanco o ser
una clave ultra secreta.

Una vez configurada la DB, veamos:


Cmo crear las tablas en la base de datos con Laravel

Para ello usaremos migraciones.

Las migraciones permiten configurar y modificar la estructura
de una base de datos. Creando una especie de control de
versiones de base de datos que puede ser usada por una o ms
personas dentro del equipo de desarrollo.

Por ejemplo:
Inicialmente crearemos una tabla llamada users.
En unas semanas necesitaremos otra tabla llamada tasks.
Luego agregaremos un campo adicional llamado role en la tabla
users para dividir los administradores de los usuarios normales.

Cada uno de estos pasos implicar crear una migracin diferente
con la que el framework sabr cmo modificar la base de datos,
tanto hacia el nuevo esquema (del paso 1 al paso 2) como al
esquema anterior (por ejemplo: de vuelta al paso 2 desde el paso
3).

Ahora veamos:


Cmo instalar el sistema de migraciones en Laravel

Abrimos nuestra consola o terminal (recuerden usar la consola
instalada por GIT si usan Windows) y tipeamos lo siguiente:
Cdigo :
php artisan migrate:install


Artisan es la interface de comandos de consola que trae Laravel

Si configuramos bien la base de datos deberamos recibir el
siguiente mensaje:
Cdigo :
Migration table created successfully


(Sino recibes este mensaje, vuelve al punto anterior sobre
configurar la base de datos y revisa que todo est bien)

Tabla de migracin creada con xito?
S, si vuelves a tu herramienta de base de datos (ej. PHPMyAdmin)
vers la siguiente tabla:



Esta es una sencilla tabla que usa Laravel para conocer el estado
de la migracin en tu servidor, por ahora est vaca.

Siguiente paso:


Crear nuestra primera migracin con Artisan y Laravel

Para ello ejecutamos el siguiente comando:
Cdigo :
php artisan migrate:make create_user_table


Si todo sali bien, recibiremos un mensaje similar a ste:
Cdigo :
Created Migration: 2013_09_03_211545_create_user_table
Generating optimized class loader


El primer mensaje (migracin creada) nos indica que fue creado el
archivo donde vamos a:


Crear el esquema de nuestra tabla usando el Schema Builder

Abrimos el archivo localizado en:
Cdigo :
app/database/migrations/2013_09_03_211545_create_user_table.php


El nombre del archivo adems de lo especificado por nosotros
(create_user_table) contiene una fecha/hora que permite indicarle al
framework el orden en que fueron creadas las migraciones, en mi
caso 2013_09_03_21...

Ok, abrimos el archivo, tenemos la siguiente estructura:
Cdigo :
<?php

use Illuminate\Database\Migrations\Migration;

class CreateUserTable extends Migration {

/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}

}


Bsicamente tenemos una clase llamada CreateUserTable y dentro
tiene dos mtodos up and down.

El mtodo up servir, en este caso, para definir nuestra tabla,
reemplacemos el mtodo vaco por lo siguiente:
Cdigo :
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function($table)
{
$table->increments('id');

$table->string('email');
$table->string('password');
$table->string('full_name');

$table->timestamps();
});
}


Dentro tenemos un llamado al
[url=http://es.wikipedia.org/wiki/Facade_(patr%C3%B3n_de_dise%C
3%B1o)]facade[/url] Schema::create que nos permite crear el
esquema de una tabla usando una interfaz de PHP orientada a
objetos, es decir, como si nuestra tabla fuera un objeto.

Schema::create acepta como primer parmetro el nombre de
nuestra tabla, en este caso: users

El segundo parmetro es una closure o funcin annima al cual se
le inyecta el objeto $table, dicho objeto nos permitir definir los
campos de nuestra tabla, por ejemplo:

Cdigo :
$table->increments('id');


Le dice a Laravel que nuestra tabla tendr un campo de tipo auto
incremento llamado id, el cual es muy comn en MySQL.

Luego le decimos a Laravel que necesitamos un campo string
llamado email:
Cdigo :
$table->string('email');


Pero en MySQL no existe el campo de tipo string...

Laravel se encarga de ello convirtiendo al tipo adecuado de acuerdo
a la base de datos que hayamos configurado al principio, en el caso
de MySQL nuestro campo resultante ser de tipo VARCHAR.

Lo mismo para password y full_name, al final tenemos lo siguiente:
Cdigo :
$table->timestamps();


?

Bsicamente este mtodo le dice a Laravel que queremos crear 2
campos, uno llamado created_at y otro updated_at ambos de tipo
TIMESTAMP que servirn para saber cuando fue creado o
modificado cada uno de los registros de nuestra tabla.

Ok, Estn listos? Vamos a ejecutar la migracin: vamos de nuevo
a la consola y escribimos lo siguiente:
Cdigo :
php artisan migrate


Si todo sali bien recibiremos un mensaje as:
Cdigo :
Migrated 2013_..._create_user_table


Ahora corremos a ver el PHPMyAdmin y



Voil!

S que estn emocionados con nuestra nueva tabla, pero -aunque
suene doloroso- tendremos que deshacernos de ella, no se
preocupen, crearemos una nueva ms tarde y nadie notar la
diferencia:

Reemplacemos el mtodo down por lo siguiente:
Cdigo :
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('users');
}


S:

Cdigo :
Schema::drop('users');


Es el fatdico mtodo que eliminar nuestra recin creada tabla
users, ahora tomen valor y escriban en la consola:
Cdigo :
php artisan migrate:rollback


Recibiremos el siguiente mensaje:
Cdigo :
Rolled back: 2013...create_user_table


Indicndonos que migracin se ha descartado. Corremos a
PHPMyAdmin pero nuestra tabla users no est, its gone Se ha
ido.

No puede ser!

Rpidamente regresamos a la consola y tipeamos de nuevo:
Cdigo :
php artisan migrate


Volvemos a PHPMyAdmin y Nuestra tabla users est de nuevo con
nosotros! Djenla all por ahora, la necesitaremos en un prximo
tutorial.

Adems de agregar drama a nuestra vida, el rolled back sirve tanto
si cometimos un error definiendo una tabla, como si queremos
regresar nuestra base de datos a un estado anterior. Ms adelante
aprenderemos un poco ms sobre las migraciones en Laravel.

Es todo por ahora Qu les pareci el tutorial? Cuntanos en los
comentarios. Adems me gustara saber si quieren que les explique
un poco ms sobre programacin orientada a objetos en PHP 5.3,
por ejemplo: Qu es un namespace? En un prximo tutorial.

Usa los enlaces claves dentro del mismo tutorial para descubrir
artculos interesantes relacionados con el tema.





















2.3 - Primeros pasos con Laravel
Ya sabes qu es Laravel, ya lo instalaste y configuraste la
base de datos? Muy bien, porque pronto comenzaremos a
programar nuestro mdulo! Pero antes, en esta cuarta entrega,
hablaremos un poco sobre cmo funciona la web:

Los sitios web funcionan con un protocolo llamado HTTP que
permite que un cliente se comunique con un servidor y viceversa.
Veamos un par de grficos sencillos sobre esto:


Veamos, esta es una sencilla peticin (request) donde tu navegador
(Firefox) solicita obtener (GET) la informacin de la pgina
cristalab.com/tags/laravel. Una vez que leas el tutorial querrs
dejar un comentario, para ello llenars el formulario al final del post
y apretars el botn enviar comentario, en ese momento se
producir otra solicitud:



Ahora Firefox le dice al servidor de cristalab.com que quiere publicar
(POST) un comentario, y obviamente le enva la informacin
correspondiente (tu email, tu comentario) y Cristalab devolver un
cdigo 200 (todo bien, la pgina fue encontrada, el servidor funciona
bien), sin embargo el HTML contendr un mensaje de xito o un
mensaje de error.

En resumen cada peticin (Request) tiene un verbo (GET, POST
son los ms comunes) y una direccin (cristalab.com/tags,
laravel.com/docs, etc.). Una respuesta (Response), por otro lado, se
constituye de un cdigo (200 si todo est bien, 404 si no fue
encontrada la pgina, 500 error de server, etc.) y el cuerpo de la
respuesta, que es por lo general HTML.

Los programadores expertos dirn: Y que hay de los HEADERS?
Y las variables de sesin? No te olvides de las cookies!

Lo s, pero quera mantener esto sencillo; veamos, adems de lo
que ya les expliqu cada peticin y respuesta transporta otros datos
como headers, variables de sesin y cookies.

Por ejemplo, un header en una peticin puede tener la informacin
de la IP del usuario, en PHP prueben
imprimiendo $_SERVER['REMOTE_ADDR'] o de donde proviene el
usuario $_SERVER['HTTP_REFERER'] o el navegador que usa
$_SERVER['HTTP_USER_AGENT']

Ok pero esta informacin no es segura
Dicen los expertos y s, tienen razn, pero mantengmoslo simple
por ahora.

Las variables de sesin (Session) almacenan tu informacin
cuando, por ejemplo, haces login en una pgina y se borran cuando
haces logout. Si le dices a un sitio web que recuerde tu usuario por
dos semanas, probablemente eso vaya a una Cookie, que es un
pequeo archivo que se almacena en tu computador. Ms adelante
veremos todo esto en detalle.

Por ahora recuerden Solicitud = Verbo + Direccin. Respuesta =
Cdigo + Texto.


Ok, comencemos a programar con Laravel

Est bien! Tranquilos. Vamos a comenzar abriendo el archivo
app/routes.php

Listos?. En este archivo se manejan las rutas de Laravel. Es,
digamos, la primera capa de nuestra aplicacin.


Y qu es lo que hace una ruta?
Vern, una ruta recibe una peticin (Request) del usuario y luego de
un determinado proceso debe devolver una respuesta (Response):

Entonces esto:
Cdigo :
Route::get('/', function()
{
return View::make('hello');
});


Significa que cuando el usuario solicite (GET) la pgina de inicio ( / )
va a recibir respuesta cdigo 200: todo bien y el HTML de la vista
hello (views/hello.php).

Como ven Laravel nos brinda una interfaz elegante y sencilla para
poder manejar las solicitudes y devolver las respuestas adecuadas.

Por debajo, Laravel se apoya en el excelente componente HTTP
Foundation de Symfony2 que encapsula, mejora y normaliza todas
las funcionalidades que ya trae el lenguaje PHP para manejar
requests y responses.

Obviamente nuestra aplicacin necesitar mucho ms que una
pgina para funcionar, veamos cmo hacer una segunda pgina:

Guindonos por la ruta inicial vamos a escribir otra debajo de esa,
as:
Cdigo :
Route::get('cristalab', function()
{
return View::make('cristalab');
});


Ahora copien y peguen el archivo app/views/hello.php dentro de la
misma carpeta, cambien el nombre a cristalab.php, y cambien el
contenido de app/views/cristalab.php que hay dentro del <body>
</body> por este HTML:
Cdigo :
<div class="welcome">
<a href="http://cristalab.com" title="Cristalab"><img
src="http://www.cristalab.com/images/header/logo.png"></a>
<h1>Hello Cristalab!</h1>
</div>


Ahora escriban en el
navegador http://localhost/pruebalaravel/public/cristalab

Excelente, no?

S, pero parece muy simple

Est bien, compliquemos un poco las cosas. Nuestras rutas pueden
tener parmetros que nos permitirn tener rutas dinmicas, y ms
complejas, por ejemplo:
Cdigo :
Route::get('hello/{usuario}', function($usuario)
{
return "Hello $usuario";
});


Si el resultado de una ruta es una cadena de texto (string), Laravel
devolver una respuesta de tipo 200 (todo bien) y el cuerpo ser
dicho texto.

Ahora en su navegador tipeen: hello/tu-nombre

Exacto! As pueden tener una URL dinmica que responda a
cualquier nombre. Lo mismo nos servira para tags, tutoriales, etc.
Otro ejemplo:
Cdigo :
Route::get('tags/{tag}', function($tag)
{
return "You are browsing $tag tag";
});


Quieren limitar un parmetro a que slo sea nmeros, por
ejemplo? Sencillo:
Cdigo :
Route::get('user/edit/{id}', function($id)
{
return "You are editing the user with the ID #$id";
})
->where('id', '[0-9]+');


Noten el mtodo where que se concatena a nuestra ruta y
usando una expresin regular muy simple ([0-9]+) se limita a que el
parmetro id sea compuesto por uno o ms nmeros del 0 al 9.

Tipeen user/edit/5 y recibirn el mensaje: "You are editing the
user with the ID #5". Pero si ahora tipean user/edit/laravel recibirn
un error 404 dado que ni esta ni otra ruta coincide con nuestra
peticin.

Laravel nos brinda otros tipos de respuestas que analizaremos ms
adelante.

Tambin veremos las rutas ms a fondo as como la creacin de
controladores en un prximo captulo.






2.4 - Controladores y MVC con
Laravel
Hoy quiero que aprendamos sobre los controladores con Laravel.
Cuando se habla del patrn MVC (Modelo-Vista-Controlador) se
dice que:
Un controlador es la capa intermediaria encargada de invocar a los
modelos y pasar datos a las vistas
Laravel es compatible con el patrn MVC (por ejemplo: en la carpeta
apps/ encontramos las sub-carpetas controllers/ models/ y views/.
Ms adelante hablar de MVC -pros y contras- en detalle.


Qu son los controladores?

Imaginen que en vez de una aplicacin web estamos liderando un
restaurante. Los comensales (Usuarios) son recibidos por nuestro
anfitrin Laravel. Laravel se encarga de llevarlos dentro del
restaurante (Aplicacin) donde los esperan los mesoneros (Rutas).

Cada mesonero (Ruta) se encarga de tomar nota del
pedido (Solicitud o Request) de cada comensal (Usuario) y de
dirigirlo a la estacin adecuada. Por ejemplo: si ordeno cocteles
nuestro mesonero (ruta) llevar el pedido (request) al bar, si ordeno
una pasta con albndigas dicho pedido ser llevado por el
mesonero (ruta) a la estacin de cocina italiana.

En este ejemplo, los Controladores son los encargados de cada
estacin (bar, comida italiana, comida mexicana, etc.).

Por ejemplo, nuestro maestro de cocina italiana que acaba de recibir
el pedido de albndigas y pasta, es un controlador.

De qu se encargar? De cocinar? Absolutamente NO! El
controlador solamente debe encargarse de dirigir la operacin. Por
eso, debe disponer de un grupo de chefs (Repositorios o
Modelos) a su cargo y solicitar a cada uno lo que corresponda.

Ok, s que quieren aprender a programar, s que quieren ver
cdigo, so, here we go:

Cdigo :
<?php
//app/routes.php

Route::get('pasta-with-meatballs/{id_table}, {type}', array('as'
=> 'pasta_meatballs', 'uses' =>
'ItalianController@pastaWithMeatBalls'))->where(id_table, [0-
9]+);


Cdigo :
<?php
//app/controllers/ItalianController.php

class ItalianController extends KitchenController {

protected $pastaRepo;
protected $meatRepo;
protected $sauceRepo;

public function __construct(PastaRepoInterface $pasta,
MeatRepoInterface $meat, SauceRepoInterface $sauce)
{
$this->pastaRepo = $pasta;
$this->meatRepo = $meat;
$this->sauceRepo = $sauce;
}

public function pastaWithMeatballs($idTable, $type = long)
{
// Si el usuario pidi pasta larga cocinaremos espaguetis
if ($type == long)
{
$pasta = $this->pastaRepo->cookSpaghetti();
}
// Si el usuario pidi pasta corta cocinaremos rigatonis
else if ($type == short)
{
$pasta = $this->pastaRepo->cookRigatoni();
}
else
{
return Redirect::route(table, array($idTable)-
>with(message, Por favor elija pasta corta o pasta larga);
}

$meatBalls = $this->meatRepo->cookMeatBalls();
$napoliSauce = $this->sauceRepo->cookNapoliSauce();

$food = compact(pasta, meatBalls, napoliSauce);

return View::make(dishes/italian, $food);
}
}


Interesante, no? Lamentablemente ni Laravel ni PHP pueden
preparar comida por nosotros, eso sera genial, pero si leyeron en
detalle el cdigo descrito arriba y lo entienden han dado un gran
paso para ser buenos chefs, quiero decir, programadores en
Laravel.

Examinemos el cdigo:


Cmo darle nombre a una ruta y enlazarla a un controlador

Cdigo :
Route::get('pasta-with-meatballs/{id_table}/{type}', array('as'
=> 'pasta_meatballs', 'uses' =>
'ItalianController@pastaWithMeatBalls'))->where(id_table, [0-
9]+);


Fjense que ya el segundo parmetro no es una funcin
annima, como en los ejemplos anteriores.

Ahora es un array:

El parmetro as define el nombre de la ruta, suponiendo que
escribimos nuestra vista views/menu.blade.php podremos colocar el
enlace a nuestra ruta as:
Cdigo :
<!-- app/views/menu.blade.php -->
<ul>
<li><a href={{ route(pasta_meatballs, array($idTable,
long)) }}>Pasta larga</a></li>
<li><a href={{ route(pasta_meatballs, array($idTable,
short)) }}>Pasta corta</a></li>
</ul>


O un redirect:
Cdigo :
Redirect::route(pasta_meatballs)


El nombre de la ruta NO es la URL De hecho, ms adelante
podramos cambiar la URL a pasta-con-albondigas y el men y el
Redirect seguirn funcionando como si nada. Bastante til.

El parmetro usesdefine el controlador y la accin que se van
a usar , separados por una arroba:
Cdigo :
'ItalianController@pastaWithMeatBalls'


Composer y Laravel saben cmo cargar nuestros controladores y
otras clases. Ms adelante hablaremos del Autoloader de Composer

Entonces una vez que nuestro usuario haga click en los tems
Pasta larga o Pasta corta de nuestro men Laravel armar por
nosotros la Estacin de comida italiana ItalianController y asignar
los chefs (clases, repositorios) para la pasta, la carne y la salsa, y
una vez que est todo listo llamar a la funcin /
accinpastaWithMeatBalls.


Cmo funciona un constructor en los controladores de Laravel

Revisemos de nuevo el constructor de nuestra clase
ItalianController:
Cdigo :
public function __construct(PastaRepoInterface $pasta,
MeatRepoInterface $meat, SauceRepoInterface $sauce)
{
$this->pastaRepo = $pasta;
$this->meatRepo = $meat;
$this->sauceRepo = $sauce;
}

Un constructor es un mtodo especial de PHP que se llama cada
vez que creamos un objeto

Pero de dnde salen esos parmetros $pasta, $meat, $sauce?

Laravel los crea y asigna por nosotros automticamente!, siempre
que las interfaces existan y haya al menos una clase que
implemente dicha interfaz. Lo nico que necesitamos hacer es
decirle a Laravel qu clases van a ser usadas por cada interfaz:
Cdigo :
// al final de app/start/globals.php agregaramos lo siguiente:
App::bind(PastaRepoInterface, PastaRepo);
App::bind(MeatRepoInterface, MeatRepo);
App::bind(SauceRepoInterface, SauceRepo);


En nuestra carpeta app/models/ podemos programar
los repositorios y modelos y tambin las interfaces


Qu es una Interfaz

Una interfaz, es como un contrato que permite definir los mtodos
(funcionalidades) mnimos que una clase debe tener. En s NO
implementa cdigo, slo sirve para definir los requerimientos de
las clases de cierto tipo. En nuestro ejemplo, los requisitos
mnimos que nuestro restaurante exige para contratar a un chef de
pasta, seran:
Cdigo :
// app/models/PastaRepoInterface

interface PastaRepoInterface {

public function cookSpaghetti();
public function cookRigatoni();
public function cookLasagne();

}


Debe saber cmo preparar espagueti, rigatonis, y lasaa, why
not?

Ahora si queremos crear un chef encargado de proveerle pasta a las
cocinas escribiramos lo siguiente:
Cdigo :
// app/models/PastaRepo

class PastaRepo implements PastaRepoInterface {

public function cookSpaguetti()
{
return Pasta::where(type, =, spaguetti)->get();
}

public function cookRigatoni()
{
return Pasta::where(type, =, rigatoni)->get();
}

// Etc. Etc...

}


PastaRepoInterface es el contrato. PastaRepo es el chef que
conoce las recetas.

Lo interesante de este ejemplo es que si luego queremos cambiar
nuestro especialista en pastas, slo tendramos que regresar a
app/start/globals.php y decirle a Laravel:
Cdigo :
//app/start/globals.php
App::bind(PastaRepoInterface, MongoPastaRepo);


Que ahora nuestro Chef de Pastas no ser Eloquent sino Mongo.

Siempre que el nuevo chef MongoPastaRepo implemente la
interfaz PastaRepoInterface nuestra cocina seguir
funcionando sin ningn tipo de cambio adicional. Genial No?

Por cierto, las recetas en este caso seran la lgica de nuestra
aplicacin o lgica de negocios. En este caso todas las hemos
puesto dentro de nuestra carpeta de modelos, como debe ser.


Vistas o Capa de Presentacin

Una vez que el controlador ItalianController obtiene toda la comida
necesaria para crear nuestra pasta con albndigas:
Cdigo :
$food = compact(pasta, meatBalls, napoliSauce);


Esta se pasa a la vista, que en nuestro ejemplo sera la estacin
encargada de decorar el plato para que no slo tenga la
comida (data) adecuada sino que luzca bien (diseo, layouts,
HTML5).

Pero no siempre necesitaremos una capa de presentacin.
Qu pasa si el usuario pide su comida para llevar, por ejemplo?
Slo habra que entregarla en un envase, sin platos, sin adornos, sin
HTML, A qu les recuerda eso? Cuando hacemos una
peticin AJAX, el servidor simplemente nos devuelve los datos en
formato JSON:

Cdigo :
return Response::json($food);



Cmo redirigir una accin a otra ruta


Fjense qu pasa si el tipo de pasta ($type) solicitado no es long ni
short:

Cdigo :
return Redirect::route(table, array($idTable))-
>with(message, Por favor elija pasta corta o pasta larga);


De una manera muy sencilla le decimos a Laravel que redirija la
peticin del usuario de nuevo a su mesa, donde le pediremos que
por favor elija pasta corta o larga.

Por supuesto necesitaramos definir otra ruta:
Cdigo :
//app/routes.php

// [More code here]

Route::get(table/{id}, array(as => table, uses =>
tableController@index))->where(id, [0-9]+); //etc



Conclusin

En este captulo y con un ejemplo sencillo aprendimos qu son los
controladores, cmo se crean y usan en Laravel, tambin
aprendimos cmo enlazar las rutas a ellos y aprendimos sobre
Repositorios e Interfaces que mantienen la lgica y
responsabilidades de nuestra aplicacin separadas, como debe ser.
Tambin le dimos un vistazo a cmo trabajar con vistas,
redirecciones y JSON.

En los prximos captulos ir detallando todo lo anterior.

Como ltima nota, quizs algunos lectores estn pensando algo
como: Pero yo no necesito un restaurante o aplicacin tan
elegante. Yo hago pginas web ms sencillas.

Con Laravel podramos hacer esto:

Cdigo :
// app/routes.php
Route::get(pasta-with-meatballs, function () {
$pasta = Pasta::where(type, =, short)->get();
// Etc. Etc.

return View::make(dish, array($pasta));
});


Para qu crear un controlador y luego una interfaz y un repositorio
y etc. etc. si se puede hacer todo tan rpido y fcil?

Tienen razn, eso tambin funciona, como uno de esos puestos de
comida rpida que son atendidos por una o dos personas que te
dan la bienvenida, preparan la comida, te sirven y te cobran y
limpian las mesas eso funciona. Pero si quieren ser
programadores de alta categora, lo mejor es que aprendan y
usen las mejores prcticas de desarrollo en el lenguaje y framework
en el cual se desempeen... Esto es un poco de lo que quiero lograr
con Laravel y estos captulos: que aprendan Laravel pero aprendan
bien.

No subestimen sus proyectos, no subestimen a sus clientes y
sobretodo no se subestimen a uds. mismos.

Como siempre todas sus impresiones, dudas, preguntas, aportes,
en los comentarios, por favor


2.5 - Blade, el sistema de plantillas
de Laravel
Para cerrar esta primera parte de los tutoriales quiero mostrarles
cmo funcionan las vistas en Laravel. Este es quizs el tutorial ms
fcil de todos. Veremos cmo usar el sistema de plantillas de
Laravel llamado Blade.

No te pierdas los anteriores tutoriales de Laravel:
introduccin a Laravel,
su instalacin,
Cmo configurar la base de datos y crear migraciones,
las rutas
y los controladores.



Qu es y cmo funciona Blade

Blade es bsicamente un sub-lenguaje muy sencillo, que antes de
ser usado por nuestra aplicacin, es compilado a PHP plano. Para
usar Blade, simplemente creen sus plantillas en el
directorio views/ con la extensin .blade.php en vez de .php.

Por ejemplo:
Cdigo :
views/template.blade.php


Ahora creen una ruta o controlador que llame a la plantilla (ya saben
cmo, Cierto?)

En caso de que no En app/routes.php pongan esto:
Cdigo :
Route::get('template', function () {
return View::make('template');
});


Ahora en views/template.blade.php escriban algo de HTML:
Cdigo :
<h1>Hello Cristalab</h1>


Bastante bsico, es decir, en este punto da igual si usamos Blade o
no Pero, vamos a ver:


Cmo escribir vistas dinmicas con Blade

Ok, supongamos que, como en ejemplos anteriores, queremos usar
un nombre variable:

Cdigo :
Route::get('template/{name}', function ($name) {
$name = ucwords(str_replace('-', ' ', $name));
return View::make('template')->with('name', $name);
});


En este caso, para hacer el ejemplo ms interesante, lo pasamos
por la ruta, y luego lo asignamos a la vista, con el mtodo ->with()
que va concatenado a View::make, fjense:
Cdigo :
View::make('template')->with('name', $name)


Ok, ahora en nuestra vista, si estuviramos usando slo PHP,
tendramos que escribir algo as:
Cdigo :
<h1>Hello <?php echo $name ?></h1>


Pero gracias a Blade, podemos escribirlo as:
Cdigo :
<h1>Hello {{ $name }}</h1>


Bsicamente: {{ }} es un sustituto de <?php ?> que por un lado es
ms corto y fcil de escribir, por otro usar etiquetas PHP (<? ?>) se
mezcla con las etiquetas del HTML, as que usar motores como
Blade es ms limpio por as decirlo.

Blade slo reemplaza {{ * }} por <?php echo * ?>, es decir, todo el
cdigo PHP que quieras escribir es vlido dentro de {{ }}, por
ejemplo:

Cdigo :
<h1>Hello {{ strtoupper($name) }}</h1>


Otros motores de plantillas para PHP ms avanzados
como Smarty o Twig compiladores ms poderosos, que permiten
usar, por ejemplo, sintaxis de punto para los arrays, la cual no es
soportada por PHP, etc.


Cmo escribir estructuras de control con Blade

Por ltimo veremos cmo se escriben estructuras de control
sencillas pero muy comunes como IF y FOREACH.

Blade tiene una sintaxis bien simple, por ejemplo:
Cdigo :
@if ($name == 'Walter White' OR $name == 'Jesse Pinkman')
<h1>Goodbye Breaking Bad</h1>
@else
<h1>Hello {{ $name }}</h1>
@endif


Nuevamente, todo lo que est dentro del parntesis del IF es PHP
comn y corriente, lo que cambia es que en vez de escribir:

Cdigo :
<?php if (...): ?>


O:

Cdigo :
<?php if (...) { ?>


Escribimos:

Cdigo :
@if (...)


Es una sintaxis mucho ms limpia y adecuada para nuestras
vistas

Por supuesto, si estn escribiendo los ejemplos pueden ejecutarlos
en el navegador, escribiendo algo como:
Cdigo :
http://localhost/pruebalaravel/public/template/walter+white


Esto es con respecto a la sintaxis, pero Blade tambin nos brinda
una herramienta potente para escribir vistas:


Uso de Layouts en Laravel con Blade

Casi todos los proyectos, por no decir todos, tienen un layout que
consiste, por lo general en un header + un footer. Por ejemplo
fjense Cristalab.com Han visitado esa pgina? Todas las pginas
dentro del site cristalab.com llevan en la cabecera el logo de
Cristalab + el men etc. y en el pie de pgina tiene el men repetido
y la foto de Freddier en un pony (bueno no, pero sera ms
divertido).

Ese HTML que se repite en cada pgina se llama layout y en
Blade podemos escribirlo as:

Creen una vista llamada:

Cdigo :
views/layout.blade.php


Con el siguiente HTML de ejemplo:

Cdigo :
<html lang="en">
<head>
<meta charset="utf-8">
<title>Aprendiendo Laravel</title>
</head>
<body>
@yield('content')
<hr />
Copyright 2013 - Todos los ponies reservados.
</body>
</html>


Y luego en views/template.blade.php coloquen lo siguiente:

Cdigo :
@extends ('layout')

@section ('content')

<h1>Hello {{ $name }}</h1>

@stop


El PHP en nuestra ruta sigue igual, es decir, seguiremos invocando
a template, no a layout:
Cdigo :
View::make(template)


Pero template a su vez extiende la plantilla layout, como si fuera
un objeto hijo que extiende de un objeto padre:
Cdigo :
<!-- views/template.blade.php
@extends ('layout')


Ahora, si se fijan, en views/layout.blade.php pueden ver lo siguiente,
dentro del body:
Cdigo :
@yield('content')


Esa etiqueta de Blade permite definir una seccin dinmica que
puede ser reemplazada en la plantilla hijo, en este caso
template.blade.php usando las etiquetas:
Cdigo :
@section ('content')

<!-- HTML AQUI -->

@stop


Fjense que content es el nombre de la seccin en ambas
plantillas. Por supuesto podemos crear tantas secciones como
queramos:
Cdigo :
<!-- views/layout.blade.php -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>@yield('title', 'Aprendiendo Laravel')</title>
</head>
<body>
@yield('content')
<hr />
Copyright 2013 - Todos los ponies reservados.
</body>
</html>


Noten que el ttulo HTML cambi a:
Cdigo :
<title>@yield(title, Aprendiendo Laravel)</title>


En este caso el segundo parmetro de @yield sera el valor por
defecto, es decir, si abrimos en el navegador nuestra direccin:
Cdigo :
http://localhost/pruebalaravel/public/template/cristalab


Seguiremos viendo en el ttulo del mismo la frase: Aprendiendo
Laravel, que es nuestro ttulo por defecto.

Pero si cambiamos views/template.blade.php a:
Cdigo :
@extends ('layout')

@section ('title') Saludos a {{ $name }} @stop

@section ('content')

<h1>Hello {{ $name }}</h1>

@stop


Entonces el ttulo ahora ser, por ejemplo: Saludos a Cristalab.
Tengan en cuenta que pueden crear tantas secciones como gusten,
y que cada seccin puede tener un valor por defecto y un valor
distinto en cada sub-plantilla. Adems pueden usar variables, etc.
en cada seccin.

Para finalizar, 2 tips:

1. En HTML, como ya deben saber, los comentarios se escriben as:

Cdigo :
<!-- comentario -->


Y suelen ser tiles cuando el HTML que escribimos es muy complicado, sin
embargo dichos comentarios se envan al navegador junto con el resto de las
etiquetas, y esto no es siempre lo que queremos, dado que cualquiera podra
leerlos y hacen el HTML un poco ms pesado, etc

Con Blade podemos escribir comentarios as:

Cdigo :
{{-- Esto es un comentario --}}


Dichos comentarios no son compilados como HTML ni enviados al navegador.

2. A veces Blade no es suficiente y necesitamos PHP en nuestras plantillas, por
ejemplo, para asignar una variable:

Cdigo :
<?php $user = Auth::user() ?>


Es posible usar PHP plano dentro de Blade, slo traten de mantener sus plantillas
lo ms limpias posibles, limiten el uso de PHP, y si en tal caso lo necesitan,
escriban slo sentencias sencillas y preferiblemente al inicio de la plantilla.

Visiten la documentacin oficial para obtener ms ejemplos sobre
Blade

2.6 - Crear un mdulo de usuarios
con Laravel (I)
En esta segunda parte de tutoriales de Laravel, quiero que
utilicemos los conocimientos aprendidos en la primera parte, con los
cuales aprenderemos a crear nuestro primer mdulo de Laravel,
adems les explicar cmo validar datos, crear formularios, entre
otros temas.

Vamos a hacer un mdulo de usuarios, no es lo ms emocionante
del mundo, s, pero casi siempre necesitaremos uno en nuestra
aplicacin. Vamos a ir muy paso a paso, lo primero que vamos a
hacer es:


Crear las rutas y el controlador

Laravel dispone de algo llamado Resource Controller (traducido
sera algo como Controlador de recursos)

Un Resource Controller sirve para crear una interfaz RESTful para
un mdulo.

Como este tutorial es ms prctico que terico, slo les dir que
este recurso RESTful permite definir todas las acciones para que el
mdulo pueda: Crear, Obtener, Actualizar y Borrar (lo que se
conoce como CRUD por las siglas en ingles: Create, Red, Update,
Delete)

Vamos a crear entonces todo lo que necesitamos del controlador y
las rutas en 2 pasos:
Cdigo :
Route::resource('admin/users', 'Admin_UsersController');


Esto es lo nico que hace falta para vincular el Resource
Controller a nuestras rutas.
El primer parmetro es la direccin desde donde comenzar a
funcionar nuestro recurso, en este caso admin/users
El segundo parmetro es el controlador al que apunta.



Generando nuestro controlador

Laravel nos pone a disposicin un sencillo comando para generar
un controlador de recursos.

Abran el terminal o consola de comandos, vayan a la carpeta del
proyecto (ejemplo: C:\xamp\httpdocs\pruebalaravel\) y tipeen:
Cdigo :
php artisan controller:make Admin_UsersController


Esto generar un nuevo controlador con los mtodos necesarios
para nuestro mdulo.

Vayan a app/controllers y vern un nuevo archivo
llamado Admin_UsersController.php

Un ltimo paso importante: Creen una carpeta llamada admin/
dentro de app/controllers, renombren el archivo a
UsersController.php y colquenlo dentro de la carpeta admin/ de
modo que quede as:
Cdigo :
app/controllers/admin/UsersController.php


Esto es importante para mantener la organizacin de nuestros
mdulos, que presumo, seran editados en un panel de
administracin (admin) y para que la ruta admin/users que
escribimos antes, funcione. Ahora si abrimos el archivo
controllers/admin/UsersController.php veremos lo siguiente:
Cdigo :
<?php

class Admin_UsersController extends \BaseController {

/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
//
}

/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
//
}

/**
* Store a newly created resource in storage.
*
* @return Response
*/
public function store()
{
//
}

/**
* Display the specified resource.
*
* @param int $id
* @return Response
*/
public function show($id)
{
//
}

/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return Response
*/
public function edit($id)
{
//
}

/**
* Update the specified resource in storage.
*
* @param int $id
* @return Response
*/
public function update($id)
{
//
}

/**
* Remove the specified resource from storage.
*
* @param int $id
* @return Response
*/
public function destroy($id)
{
//
}

}


Como ven tenemos ya definidos todos los mtodos para nuestro
CRUD, aunque por los momentos no hacen nada (si acceden en el
navegador a /admin/users vern una pantalla en blanco). Sin
embargo, podemos revisar que los mtodos funcionan si retornamos
un string en algunos de ellos, ademas veamos las rutas a las que
estn asignados:
A index se accede mediante /admin/users:
Cdigo :
public function index()
{
return 'Esta es la lista de usuarios';
}


A create se accede mediante /admin/users/create

Cdigo :
public function create()
{
return 'Aqui va el form para crear un usuario';
}


A show se accede mediante la URL del recurso + el ID numrico de
algn registro, en este caso no tenemos ninguno, pero para probar
podemos colocar cualquier nmero, por ejemplo: admin/users/5:
Cdigo :
public function show($id)
{
return 'Aqui mostramos la info del usuario: ' . $id;
}


As mismo, a edit se accede mediante la URL del recurso + un ID
numrico + el segmento /edit: por darles un ejemplo:
admin/users/10/edit
Cdigo :
public function edit($id)
{
return 'Aqui editamos el usuario: ' . $id;
}


Como ya lo habrn notado, el nmero que colquen en la URL se
pasa por parmetro a algunos de los mtodos, en este caso show y
edit, este nmero debera ser el ID de usuarios existentes en la
base de datos, esto lo veremos en las partes siguientes.

Tambin les comento que: index, create, show y edit son mtodos
GET. Recuerdan el tutorial sobre los [url=primeros pasos con
Laravel[/url]? Cuando tipeamos:
Cdigo :
/admin/users/5 en el navegador, estamos diciendole al servidor:
GET (Obten) /admin/users/5


Para acceder a los mtodos restantes store, update y destroy necesitamos otros
verbos / mtodos: POST, PUT, DELETE. Para ello necesitaremos crear vistas y
formularios que, comnmente, son los que generan ese tipo de peticiones, as
que esa ser la siguiente parte que publicaremos en un par de das.

2.7 - Mdulo de usuarios (II): Integra
Bootstrap con Laravel
En este nuevo tutorial veremos cmo integrar Bootstrap con
Laravel en nuestro mdulo de usuarios. ya creamos la ruta y el
controlador de nuestro mdulo, ahora trabajaremos con las vistas.

Para poder trabajar con las vistas, recomiendo ver el tutorial Blade,
el sistema de plantillas de Laravel publicado anteriormente en la
plataforma.


Integrando Bootstrap con Laravel

Esta parte es opcional, pero recomiendo que lo hagamos, no slo es
importante que nuestro mdulo funcione, tambin tenemos que
cuidar un poco la esttica, y Frameworks ya hechos
como Bootstrap caen perfectos en situaciones como sta.



Con Bootstrap practicaremos cmo hacer un Layout en Laravel,
adems de hacer que nuestro panel se vea mejor.

Si es de su preferencia intenten seguir el tutorial usando otro
framework, el procedimiento debera ser bastante estndar.


Descargar Bootstrap
Descarguen la ltima versin de Bootstrap
Busquen y descompriman el archivo a una carpeta cualquiera (ej.
/descargas/bootstrap/)
Luego, dentro de esa carpeta copien la carpeta dist/ a la carpeta
public de nuestro proyecto
Por ltimo, renombren la carpeta dist/ a assets/ de manera que
quede as, por ejemplo:


Cdigo :
../descargas/bootstrap-3.0.0/dist ->
../pruebalaravel/public/assets


Dentro de public/assets deberamos tener las carpetas css/ fonts/ y
js/ que vienen en la distribucin de Bootstrap. Si es as, todo bien.

Por ltimo vamos a copiar dos archivos que estn en
descargas/bootstrap-3.0.0/assets/js/
Cdigo :
html5shiv.js
respond.min.js


Y vamos a pegarlos en public/assets/js

html5shiv y respond.js hacen falta para que Bootstrap sea
compatible con las versiones anteriores de Explorer


Crear un layout sencillo con Bootstrap

Vamos a partir del layout bsico propuesto en la pgina oficial de
Bootstrap, con algunos cambios y con la sintaxis de Blade.

Creen la carpeta admin en app/views y el archivo:
app/views/admin/layout.blade.php, luego peguen esto:
Cdigo :
<!DOCTYPE html>
<html>
<head>
<title>Bootstrap 101 Template</title>
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet"
media="screen">

<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements
and media queries -->
<!--[if lt IE 9]>
<script src="../../assets/js/html5shiv.js"></script>
<script src="../../assets/js/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div id="wrap">
<div class="container">
<h1>Hello, world!</h1>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -
->
<script src="//code.jquery.com/jquery.js"></script>
<!-- Include all compiled plugins (below), or include
individual files as needed -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>



Qu hay que cambiarle a esto para convertirlo en un layout de Laravel?
Primero hay que utilizar lo que vimos en el tutorial anterior, para
definir las secciones (content y title por ahora est bien)

Cambien:
Cdigo :
<h1>Hello, world!</h1>


Por:
Cdigo :
@yield('content')


Y:
Cdigo :
<title>Bootstrap 101 Template</title>


Por:
Cdigo :
<title>@yield('title', 'Aprendiendo Laravel')</title>


Segundo, tenemos que corregir las llamadas a los assets (CSS,
JS) de modo que apunten al directorio correcto, para esto Laravel
tiene helpers, que colocan la ruta correcta por nosotros, y
son portables, es decir, aunque cambiemos el directorio de nuestro
proyecto, o lo subamos a un server, seguirn funcionando las rutas:

Cambien:
Cdigo :
<link href="css/bootstrap.min.css" rel="stylesheet"
media="screen">


Por:
Cdigo :
<link href="{{ asset(assets/css/bootstrap.min.css) }}"
rel="stylesheet" media="screen">


O an ms corto:
Cdigo :
{{ HTML::style('assets/css/bootstrap.min.css', array('media' =>
'screen')) }}


Con Javascript sucede lo mismo. Cambien:
Cdigo :
<script src="js/bootstrap.min.js"></script>


Por:
Cdigo :
<script src="{{ assets(assets/js/bootstrap.min.js)
}}"></script>


O mejor an:
Cdigo :
{{ HTML::script('assets/js/bootstrap.min.js') }}


Por ltimo, hagan lo mismo con las llamadas a los scripts para IE8,
intentenlo ustedes:
Cdigo :
<script src="../../assets/js/html5shiv.js"></script>
<script src="../../assets/js/respond.min.js"></script>


Qu habra que hacer aqu? Debajo la respuesta (spoiler alert):
Cdigo :
{{ HTML::script(assets/js/html5shiv.js) }}
{{ HTML::script(assets/js/respond.min.js) }}



Algunas observaciones
Como sospecharn: asset(), HTML::style y HTML::script son
todos helpers de Laravel, funciones que sirven de ayuda para
determinar la ruta, en el caso de asset y adems, escribir HTML de
forma ms dinmica en el caso de las funciones HTML::style y
HTML::script.

La llamada a Jquery hay que dejarla tal como est, dado que es una
URL absoluta: http://code.jquery.com/jquery.js no hay que usar los
helpers de Laravel.

Fjense que todas las dems rutas parten de public/ Laravel se
encargar de convertir:
Cdigo :
assets(assets/js/bootstrap.min.js)


...en una URL completa al archivo, como, por ejemplo:
Cdigo :
http://localhost/pruebalaravel/public/assets/js/bootstrap.min.js


Esto es muy conveniente. Adems me tom la libertad de cambiar
todos los comentarios HTML por comentarios de Blade (todo
excepto el que sirve de IF para las versiones de IE, ese qued igual
por supuesto).

Nuestro Layout final, siguiendo todos los pasos, debera haber
quedado as:
app/views/admin/layout.blade.php
Cdigo :
<!DOCTYPE html>
<html>
<head>
<title>@yield('title', 'Aprendiendo Laravel')</title>
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
{{-- Bootstrap --}}
{{ HTML::style('assets/css/bootstrap.min.css', array('media'
=> 'screen')) }}

{{-- HTML5 shim and Respond.js IE8 support of HTML5 elements
and media queries --}}
<!--[if lt IE 9]>
{{ HTML::script('assets/js/html5shiv.js') }}
{{ HTML::script('assets/js/respond.min.js') }}
<![endif]-->
</head>
<body>
{{-- Wrap all page content here --}}
<div id="wrap">
{{-- Begin page content --}}
<div class="container">
@yield('content')
</div>
</div>

{{-- jQuery (necessary for Bootstrap's JavaScript plugins) -
-}}
<script src="//code.jquery.com/jquery.js"></script>
{{-- Include all compiled plugins (below), or include
individual files as needed --}}
{{ HTML::script('assets/js/bootstrap.min.js') }}
</body>
</html>



Crear las otras vistas

Vamos a probar nuestro Layout. Primero regresemos a nuestro controlador, desde
all llamaremos a la vista admin/users/list.blade.php:

app/controllers/admin/UsersController.php:
Cdigo :
public function index()
{
return View::make('admin/users/list);
}


Por supuesto, esta vista tenemos que crearla, en este caso en:
Cdigo :
app/views/admin/users/list.blade.php


Recuerden que Laravel completa el resto del path por nosotros, es decir no hace
falta escribir app/views/ ni la extensin .blade.php cuando invocamos una vista

Como se dan cuenta necesitamos crear una nueva carpeta llamada users dentro
de app/views/admin dentro de ella colocaremos todas las vistas de nuestro
mdulo users.

app/views/admin/users/list.blade.php
Cdigo :
@extends ('admin/layout')

@section ('title') Lista de Usuarios @stop

@section ('content')

<h1>Lista de usuarios</h1>

@stop


Similar al ejemplo anterior cuando vimos las vistas todo lo que necesitamos fue
extender el layout principal y luego reemplazar las secciones.

Si accedemos ahora al navegador, por ejemplo, en mi caso:
Cdigo :
http://localhost/pruebalaravel/public/admin/users

Veremos el texto:
Cdigo :
Lista de Usuarios


Con algo de estilo bsico. Ms adelante all haremos nuestra lista de usuarios
dinmica

Ya con el layout preparado, en nuestro prximo tutorial aprenderemos cmo crear
un formulario con Laravel y probaremos las otras acciones de nuestro
controlador Admin_UsersController.















2.8 - Mdulo de Usuarios (III): Crear
un formulario con Laravel
En esta tercera parte hablaremos sobre algo que, estoy seguro, le
ha sacado canas a ms de un desarrollador, cmo realizar
formularios dinmicos con Laravel.

Si has llegado ac por primera vez: esta es una serie de tutoriales
para escribir un mdulo de usuarios bsico con Laravel. Asegrate
de revisar la primera y segunda parte.

Si eres asiduo a estos tutoriales: Bienvenido de vuelta.

Escribir un formulario con HTML es muy simple:
Cdigo :
<form role="form">
<div class="form-group">
<label for="email">Direccin de E-mail</label>
<input type="email" class="form-control" id="email"
placeholder="Introduce tu E-mail">
</div>
<div class="form-group">
<label for="role">Tipo de Usuario</label>
<select name="role" id="role" class="form-control">
<option>Usuario</option>
<option>Admin</option>
</select>
</div>
<!-- Mas campos aqui -->
</form>


Pero a medida que necesitamos hacerlo dinmico, debemos tener
en cuenta los siguientes detalles, por ejemplo:
Si estamos editando un usuario existente, deberamos mostrar el
email actual.
Si el usuario enva el formulario pero ocurre un error, deberamos
mostrar el campo tal como l lo haba llenado y no el valor anterior.
Adems, qu sucedera si el select de roles tiene valores dinmicos
en vez de dos opciones fjas.
Cmo hacer para que en el select de roles quede una de las
opciones (option) marcada como seleccionada (selected).


Hacer manualmente todo eso convertira nuestro simple formulario
en una montaa de IFs y cdigo PHP casi imposible de leer y
mantener. Les presentar cmo quedar el formulario para nuestro
mdulo de usuarios ya listo con Laravel, y luego explicar el cdigo
con calma, aqu vamos:

Creen un archivo llamado form.blade.php en la carpeta
app/views/admin/users y copien/peguen el siguiente contenido:

app/views/admin/users/form.blade.php
Cdigo :
@extends ('admin/layout')

@section ('title') Crear Usuarios @stop

@section ('content')

<h1>Crear Usuarios</h1>

{{ Form::open(array('route' => 'admin.users.store', 'method' =>
'POST'), array('role' => 'form')) }}

<div class="row">
<div class="form-group col-md-4">
{{ Form::label('email', 'Direccin de E-mail') }}
{{ Form::text('email', null, array('placeholder' =>
'Introduce tu E-mail', 'class' => 'form-control')) }}
</div>
<div class="form-group col-md-4">
{{ Form::label('full_name', 'Nombre completo') }}
{{ Form::text('full_name', null, array('placeholder' =>
'Introduce tu nombre y apellido', 'class' => 'form-control'))
}}
</div>
</div>
<div class="row">
<div class="form-group col-md-4">
{{ Form::label('password', 'Contrasea') }}
{{ Form::password('password', array('class' => 'form-
control')) }}
</div>
<div class="form-group col-md-4">
{{ Form::label('password_confirmation', 'Confirmar
contrasea') }}
{{ Form::password('password_confirmation', array('class'
=> 'form-control')) }}
</div>
</div>
{{ Form::button('Crear usuario', array('type' => 'submit',
'class' => 'btn btn-primary')) }}

{{ Form::close() }}

@stop


Adems de escribir el formulario, hay que enlazarlo desde nuestro
controlador a la vista, intenten hacerlo uds. mismos, abajo les dejar
el cdigo de cualquier forma:
Cdigo :
public function create()
{
return View::make('admin/users/form');
}


Ya con esto podemos ver el formulario en nuestro navegador si
tipeamos /admin/users/create, en mi caso:
Cdigo :
http://localhost/pruebalaravel/public/admin/users/create


Debera verse as:



El formulario paso a paso

El cdigo es muy sencillo, vamos a detallarlo por pasos:

La parte externa que define cul es el template padre (en este caso
admin/layout) y tambin define el ttulo y el contenido es idntica a
la plantilla anterior list.blade.php
Cdigo :
@extends ('admin/layout')

@section ('title') Crear Usuarios @stop

@section ('content')

<!-- Formulario aqu -->

@stop


La parte nueva, en la que vamos a enfocarnos, es la descripcin del
formulario dentro de la seccin content.

Ac simplemente estamos usando helpers nuevos de Laravel,
como hicimos en el captulo anterior, pero esta vez para escribir
formularios.

Cdigo :
{{ Form::open(array('route' => 'admin.users.store', 'method' =>
'POST'), array('role' => 'form')) }}
<!-- Formulario aqui -->
{{ Form::close() }}


Estos dos helpers (Form::open y Form::close) se encargan de abrir
y cerrar las etiquetas HTML del formulario, respectivamente, pero no
slo eso:


Form::open:
Genera URLs a travs de la clase de Rutas de Laravel.
Permite emular los mtodos PUT y DELETE (dado que los
navegadores slo soportan GET y POST).
Genera un token para proteccin anti ataques CSRF, lo cual est
habilitado en Laravel 4 automticamente. Ms sobre ataques CSRF.
Entre otros.



Form::close:
Es necesario cuando en vez de Form::open usamos Form::model
otro helper que veremos dentro de poco.
Mantiene concordancia con Form::open (nuestro IDE probablemente
protestara si usamos </form> sin antes haber usado explcitamente
<form*>.


El primer parmetro de Form::open permite definir un array con
ciertas caractersticas propias y dinmicas del form como la ruta a
donde va dirigido y el mtodo, el segundo parmetro es un array de
atributos HTML. Pueden ver ms ejemplos de Form::open en
la documentacin oficial

Noten, sobretodo, en el array del primer atributo esto:
Cdigo :
'route' => 'admin.users.store'


Esto es lo que le dice a Laravel que apunte nuestro form a la accin
store de nuestro recurso admin.users.

Noten que el / de admin/users definido en app/routes.php
necesitamos reemplazarlo por un punto cuando usemos las
funciones de rutas de Laravel como route() enlazadas a un
"Resource Controller".

Recuerden ver el HTML resultante haciendo control+U en Chrome,
para ver el cdigo fuente:
Cdigo :
<form method="POST"
action="http://localhost/pruebalaravel/public/admin/users"
accept-charset="UTF-8">
<input name="_token" type="hidden"
value="CrBlGF5WEwXNRreWfQ7m4JDoxbSx0ucCg8fwiBPG">


Eso es lo que genera Laravel por nosotros en este caso, no slo la
etiqueta form sino un campo oculto para generar el token como
expliqu ms arriba y la URL correcta en el atributo action del form.


Definiendo los campos del formulario

Ms abajo empezamos a definir los campos:
Cdigo :
{{ Form::label('email', 'Direccin de E-mail') }}
{{ Form::text('email', null, array('placeholder' =>
'Introduce tu E-mail', 'class' => 'form-control')) }}



Form::label
Permite definir una etiqueta <label> obviamente, el primer
parmetro es el ID del campo, el segundo es el texto que se
mostrar al usuario.


Form::text
Nos permite definir un campo de tipo text, el primer parmetro es
el atributo name muy importante, el segundo es el valor que tendr
el campo, en este caso nada por ahora (null), el tercer parmetro es
un array para definir atributos HTML para el campo, en este caso le
puse un lindo placeholder y adems la clase form-control que pide
Bootstrap para que el campo se vea bien

Usados en conjunto label y un campo permite que el label tenga su
atributo for y el campo tenga el atributo id ambos con el mismo
nombre, en este caso email de manera que, si tu navegador no es
Internet Explorer 6 X_X, cuando hagas clic en el label Direccin de
E-mail el navegador automticamente coloque tu cursor dentro del
campo email (Bootstrap sombrea en azul el campo activo)

Bien, veamos el HTML generado para nuestros dos primeros
campos:
Cdigo :
<label for="email">Direcci&oacute;n de E-mail</label>
<input placeholder="Introduce tu E-mail" class="form-control"
name="email" type="text" id="email">


Fjense que adems Laravel cambi mi caracter especial por su
correspondiente HTML automticamente, sweet.

Ahora pueden revisar el resto del HTML, es bsicamente lo mismo
una y otra vez, abajo los 2 campos de password usan el
helper Form::password en vez de Form::text dado que
necesitamos, obviamente, generar campos de tipo password.

Laravel tambin soporta campos de tipo textarea, hidden, etc. cada
uno tiene su helper (Form::textarea, Form::hidden) revisen la
documentacin oficial para ms informacin.

Por ltimo, para finalizar esta parte, es hora de hacer click en el
botn Crear usuario, aunque, como programadores curiosos que
son, estoy seguro que muchos ya lo hicieron

Ahora lo que sucede cuando cliquean ese botn es sorprendente. Si
cliquean el botn vern en el navegador NADA! Es
cierto, lo que sucede es que el mtodo que Laravel invoca:
Cdigo :
public function store()
{
//
}


No regresa nada, Solucionemos eso:

Cdigo :
public function store()
{
return Input::all();
}


Ahora cuando presionemos el botn Crear usuario recibiremos de
vuelta todos los datos de nuestro formulario en una cadena de texto
en formato JSON:

Cdigo :
{"_token" : "CrBlGF5WEwXNRreWfQ7m4JDoxbSx0ucCg8fwiBPG" , "email"
: "silence[at]dessigual.com" , "full_name" : "Duilio Palacios" ,
"password" : "1234" , "password_confirmation" : "1234"}


Fjense que tanto la URL de inicio que invoca al mtodo
index: admin/users como sta que invoca al mtodo store son las
mismas! Lo que cambia es el verbo o mtodo que se est usando:

Cdigo :
GET admin/users -> llama a index()
POST admin/users -> llama a store()


Como pueden darse cuenta, cada vez est tomando ms forma
nuestro mdulo, en el prximo captulo avanzaremos un poco ms y
aprenderemos cmo validar los datos enviados por el usuario.













2.9 - Mdulo de Usuarios (IV):Validar
formulario y guardar datos con
Laravel
En este nuevo tutorial veremos cmo validar un formulario y guardar
datos con Laravel 4. En los captulos anteriores ya vimos los
siguientes temas:
Creamos el controlador (resource controller) y le asignamos la
ruta
Creamos un layout para nuestro mdulo, usando Bootstrap
Creamos el formulario para nuestro mdulo e hicimos una
prueba de envo de datos


Adems, para hacer este tutorial es necesario que hayan
completado: Configurar base de datos y crear tablas con
Laravel dado que necesitaremos una tabla users con los campos:
email, password, full_name, created_at y updated_at tal como
explica dicho tutorial.


Validar los datos enviados en el formulario

Esta es una tarea tan comn que todos los frameworks incluyen
clases dispuestas a asistir al usuario en la validacin de datos.
Laravel por supuesto no es la excepcin.

Volvamos a la funcin store donde quedamos anteriormente:
Cdigo :
public function store()
{
return Input::all();
}


Ac haremos todo el proceso.


Primero que nada, vamos a crear un nuevo usuario (new User)

En Laravel los registros de la base de datos se pueden manejar
como objetos gracias al ORM de Laravel: Eloquent.

S que es primera vez que les hablo de Eloquent, por lo tanto voy a
mantener todo el cdigo muy sencillo y en, digamos, posteriores
tutoriales s les hablar de temas un poco ms avanzados. La idea
es que todos puedan seguir este tutorial

Dado que, como les dije, cada registro (fila de la tabla users) es
manejado como si fuera un nuevo objeto, y aqu intentamos crear un
nuevo usuario, pues:
Cdigo :
$user = new User


Esto funciona slo porque Laravel viene con un modelo User.php ya
predefinido en:
Cdigo :
app/models/User.php


Ve a darle un vistazo y regresa cuando ests listo.

Ok, un gusto tenerte de vuelta.

Lo que haremos a continuacin es interactuar con nuestro
controlador Admin_UserController y nuestro modelo User para
validar y guardar el usuario.

Recuerda que como vimos en otro tutorial, el controlador debe
apoyarse en los modelos y otras clases lo ms posible, de manera
que la programacin del controlador sea limpia y la lgica de
negocio o dicho de otra forma, el cdigo pesado est en nuestro
modelo.

Nosotros, en otras palabras, queremos que la accin store de
nuestro controlador luzca as:
Cdigo :
/**
* Store a newly created resource in storage.
*
* @return Response
*/
public function store()
{
// Creamos un nuevo objeto para nuestro nuevo usuario
$user = new User;
// Obtenemos la data enviada por el usuario
$data = Input::all();

// Revisamos si la data es vlido
if ($user->isValid($data))
{
// Si la data es valida se la asignamos al usuario
$user->fill($data);
// Guardamos el usuario
$user->save();
// Y Devolvemos una redireccin a la accin show
para mostrar el usuario
return Redirect::route('admin.users.show',
array($user->id));
}
else
{
// En caso de error regresa a la accin create con
los datos y los errores encontrados
return Redirect::route('admin.users.create')->withInput()-
>withErrors($user->errors);
}
}


El cdigo se explica solo, de todas formas:
Creamos un nuevo usuario (new User).
Tomamos los datos enviados por el usuario (Input::all()).
Si son vlidos se lo asignamos al usuario, guardamos el usuario y
redireccionamos a show.
Si no son vlidos redireccionamos a la pantalla anterior pero
llevndonos de regreso la data y los errores generados en la
validacin, para mostrrselos al usuario.


Qu nos hace falta ac?

Bueno, bsicamente nunca le dijimos a Laravel qu o cmo validar,
de hecho la funcin User::isValid() no existe, si presionamos el
botn Crear usuario nos va a arrojar lo siguiente:
Cdigo :
Call to undefined method
Illuminate\Database\Query\Builder::isValid()


Ahora qu?

Vamos al modelo (app/models/User.php) y agregamos lo siguiente:
Cdigo :
public $errors;

public function isValid($data)
{
$rules = array(
'email' => 'required|email|unique:users'',
'full_name' => 'required|min:4|max:40',
'password' => 'required|min:8|confirmed'
);

$validator = Validator::make($data, $rules);

if ($validator->passes())
{
return true;
}

$this->errors = $validator->errors();

return false;
}


Primero definimos una propiedad dentro del modelo User que
servir para almacenar los errores (en caso de que haya alguno), la
coloqu pblica para simplificar el ejemplo:
Cdigo :
public $errors;


Lo segundo es definir el mtodo isValid, que acepta como
parmetro la data enviada por el usuario. Dentro fjense que defino
un array con las reglas de validacin rules.

Este array $rules es procesado por la clase de validacin de Laravel
(Validator) cuyo mtodo Validator::make acepta, como primer
parmetro un array de datos ($data) y como segundo parmetro un
array de reglas ($rules).

Fjense que las claves de ambos arrays coinciden y se refieren a los
nombres de los campos (en nuestro ejemplo: email, full_name y
password):

Entonces llamamos al mtodo:
Cdigo :
$validator = Validator::make($data, $rules)


As se crea un nuevo objeto almacenado en $validator que contiene
toda la data y las reglas de validacin. Ahora todo lo que hace falta
es ejecutar la validacin:
Cdigo :
$validator->passes() //devuelve TRUE si la validacin pasa


Cdigo :
$validator->fails() //Mtodo pesimista, devuelve TRUE si la
validacin falla


Si la validacin pasa, retornamos TRUE en nuestro mtodo isValid,
si falla entonces almacenamos en la propiedad $errors los errores
para decirle al usuario qu sali mal:

Cdigo :
$this->errors = $validator->errors();


Y retornamos FALSE.

Prcticamente siempre que necesitemos validar algo con Laravel,
usaremos este mtodo, lo que cambia son las reglas que tenemos
que definir.

Como pueden ver en el ejemplo anterior, las reglas se definen
escribiendo un array asociativo, donde la llave (key) es el nombre
del campo, y el valor es las reglas asignadas a ese campo
separadas con barra | y si la regla necesita un parmetro adicional
se define con : y si son varios parmetros es separan por coma, as:
Cdigo :
'nombre_de_campo' =>
'regla1|regla2|regla_con_parametros:parametro1,parametro2'



Reglas de validacin de Laravel

Segn usamos en el ejemplo:required sirve para indicar que un
campo es obligatorio.
email indica que el campo es de tipo email.
min:value exige que el campo tenga un mnimo de value
caracteres.
max al contrario del anterior, delimita el mximo posible.
confirmed til para confirmar email o contrasea, exige que haya
un campo con el mismo nombre pero con el sufijo _confirmation y
que ambos tengan el mismo valor (ej: password y
password_confirmation).
unique:table exige que el campo sea nico en la tabla table (til
para campos como username e e-mail).


Ms adelante veremos ms sobre la regla unique

Si quieren ver todas las reglas de validacin de Laravel vean
la documentacin oficial.

Penltimo paso:


Indicarle a Laravel qu campos se pueden llenar por asignacin
masiva

Volviendo al controlador, cuando hacemos:
Cdigo :
$user->fill($data)


Estamos haciendo algo llamado en Laravel Massive assignment
(asignacin masiva), es decir llenar todas las propiedades del
modelo a travs de un array de datos. Esto puede traer varios
problemas, por ello Laravel nos permite indicarle al modelo qu
campos son llenables (fillable) a travs de mtodos como User::fill:

En el modelo (app/models/User.php) agreguen esta otra propiedad:
Cdigo :
protected $fillable = array('email', 'full_name', 'password');


Ahora aunque algn aprendiz de hacker intente enviar campos
adicionales no conseguir romper la funcionalidad dado que slo
esos 3 campos son tomados en cuenta, ms an, tampoco se
intentar grabar el campo oculto _token ni el campo
password_confirmation que no hace falta en la tabla users.

Y ahora un ltimo paso:

Si llenamos nuestro formulario de forma invlida, digamos,
escribieron pepito en el campo email, la aplicacin es
redireccionada de vuelta al formulario (ruta admin.users.create) pero
no se muestran los errores ni nada, esto est muy mal

Hay muchas, muchas aplicaciones funcionando en produccin que
no muestran ningn error si algo sale mal, nunca le hagan esto a los
pobres usuarios


Cmo mostrar los errores de una validacin fallida:

Laravel parece ser un poco pesimista, porque siempre, en nuestras
vistas, se encuentra definida una variable llamada $errors con un
objeto de tipo MessageBagque tiene algunos mtodos bastante
bsicos, uno de ellos es any() que revisa si de verdad hay algn
error, otro es all() que devuelve el array con todos los posibles
errores.

Agreguemos esto a la vista app/views/admin/users/form.blade.php
justo debajo del ttulo:
Cdigo :
@if ($errors->any())
<div class="alert alert-danger">
<button type="button" class="close" data-
dismiss="alert">&times;</button>
<strong>Por favor corrige los siguentes errores:</strong>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif


Ahora intenten re-enviar el formulario nuevamente con el email
pepito y vern una lista de mensajes en rojo dicindote qu sali
mal:



Excelente!

Para colocar los mensajes de error en espaol hay que hacer 3
pasos:

Cambiar en app/config/app.php la variable locale a es
(actualmente tiene en).
Ir al directorio app/lang/ copiar la carpeta en/ y pegarla en el mismo
directorio, renombrndola a es/
Abrir la carpeta app/lang/es recin duplicada y traducir todos los
mensajes a espaol.


Es posible que estos mensajes ya estn disponibles si buscan en
Google, por ahora esto se escapa un poco del alcance de nuestro
tutorial.


Mantener los valores especificados por el usuario

El problema con esto es que aunque ya estamos mostrando la data
no estamos devolviendo los valores al usuario, aunque sea un error,
el campo email debera decir pepito y no estar en blanco, de forma
que el usuario pueda completar pepito@gmail.com sin tener que
reescribir todo de nuevo, por ejemplo.

Esto se puede resolver de forma muy simple con Laravel:

Modifiquemos nuestro mtodo create de manera que quede as:
Cdigo :
public function create()
{
// Creamos un nuevo objeto User para ser usado por el
helper Form::model
$user = new User;
return View::make('admin/users/form')->with('user',
$user);
}


Bsicamente lo mismo que tenamos antes, slo que instanciamos
un nuevo objeto User.

En nuestro form app/views/admin/users/form.blade.php vamos a
cambiar Form::open por otro helper llamado Form::model, que es
muy parecido, slo que como primer parmetro acepta un modelo, y
lo dems queda igual:
Cdigo :
{{-- Reemplazamos Form::open por Form::model: --}}
{{ Form::model($user, array('route' => 'admin.users.store',
'method' => 'POST'), array('role' => 'form')) }}


Listo! Ahora prueben registrarse con email pepito por ltima vez,
vern que no slo se muestran los errores sino que Laravel ahora
rebota los datos nuevamente al formulario.

Excelente!

Por ltimo veamos un grfico de lo que sucede entre el usuario y el
servidor cuando el usuario pone pepito u otro email o campo no-
vlido:



Esto nos ilustra las diferentes redirecciones que se llevan a cabo de
manera casi transparente.

Ahora si escriben todos los datos de forma vlida, vern cmo
Laravel los redirecciona a la vista show que por ahora slo
muestra algo as:

Cdigo :
Aqui mostramos la info del usuario: 1


Y este sera el grfico si todo va bien:



En prximos tutoriales por supuesto mejoraremos esto, tambin
mostraremos la lista de los usuarios que vayamos agregando.

Si van a PHPMyAdmin observarn que un nuevo registro fue
agregado a la tabla users de la base de datos pruebalaravel:



No es recomendable guardar las claves como texto plano











3 - Mdulo de usuarios (V): Lista y
paginacin con Laravel
Wow! Ya estamos en el quinto captulo de la serie de tutoriales
sobre cmo crear un mdulo de usuarios con Laravel. Si es tu
primera vez aqu, comienza por el principio, prometo que ser
divertido y tus conocimientos sobre Laravel, PHP y la programacin
en general aumentarn bastante.

Hoy vamos a hacer un tutorial bastante sencillo sobre cmo hacer
una lista (de usuarios) dinmica con Laravel.

Haremos una lista de usuarios (entre comillas) porque estos
conocimientos que estamos aprendiendo para crear este mdulo
son muy reusables para otras ocasiones Pero terminemos el
mdulo de usuarios primero y luego veremos lo dems

Cuando tengan una tarea que se vea complicada, divdanla en
fragmentos ms sencillos y cortos. De esa manera ser ms fcil y
estimulante avanzar y terminar dicha tarea.

Primero, vamos a ver cmo hacer una tabla que luzca bien con
Bootstrap:

Peguen lo siguiente dentro de la seccin content
de app/views/admin/users/list.blade.php:
Cdigo :
<h1>Lista de usuarios</h1>

<table class="table table-striped">
<tr>
<th>Full name</th>
<th>Email</th>
</tr>
<tr>
<td>Cloud Strife</td>
<td>cloud@square.com</td>
</tr>
<tr>
<td>Aerith Gainsborough</td>
<td>aerith@square.com</td>
</tr>
<tr>
<td>Tifa Lockhart</td>
<td>tifa@square.com</td>
</tr>
</table>


Recuerden simplemente tipear [URL del
proyecto]/public/admin/users para ver esta vista, en mi caso es:
Cdigo :
Acceder a http://localhost/pruebalaravel/public/admin/users:




Segundo, vamos a investigar cmo se traen registro de la base de
datos con Laravel

De vuelta a:

/app/controllers/admin/UsersController.php:
Cdigo :
<?php

class Admin_UsersController extends \BaseController {

/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
return View::make('admin/users/list');
}


Vamos a reemplazar el mtodo index() por esto:

Cdigo :
public function index()
{
$users = User::all();
return View::make('admin/users/list')->with('users',
$users);
}


Con el mtodo User::all(), Laravel se encarga de traernos todos los
registros de la tabla de usuarios por nosotros.
Aunque es posible escribir sentencias SQL de forma manual en
Laravel, con Eloquent y el Fluent Builder de Laravel en el 90% de
los casos no nos har falta.

Si desean investigar lo que devuelve el mtodo User::all pueden
hacerle un dd() a la variable $users:
Cdigo :
dd($users)


Vern que la variable contiene un objeto de
tipo Illuminate\Database\Eloquent\Collection, bsicamente este
objeto agrupa dentro de s todos los registros, que a su vez son
objetos de tipo User que contienen toda la data de cada usuario.

Al trabajar con objetos en vez de arrays planos obtenemos
muchas funcionalidades extras

Noten adems que, por su puesto, pasamos nuestra coleccin de
objetos a la vista:
Cdigo :
return View::make('admin/users/list')->with('users',
$users);


Por lo tanto en nuestra
vista app/views/admin/users/list.blade.php reemplacemos la lista
esttica por una lista dinmica, haciendo uso de un foreach para
recorrer cada usuario dentro de la coleccin creada por Laravel:
Cdigo :
<table class="table table-striped">
<tr>
<th>Full name</th>
<th>Email</th>
</tr>
@foreach ($users as $user)
<tr>
<td>{{ $user->full_name }}</td>
<td>{{ $user->email }}</td>
</tr>
@endforeach
</table>


Ahora al abrir admin/users yo puedo ver el mmm nico usuario de
mi tabla de usuarios, es decir, yo mismo:




Algunos puntos a considerar
PHP permite iterar objetos como si fueran arrays, por eso, aunque la
coleccin es objeto podemos hacerle un foreach, como si fuera un
array.

Cada usuario ($user) dentro de nuestra coleccin de usuarios
($users) tiene propiedades dinmicas las cuales, por defecto, tienen
el mismo nombre de las columnas de la tabla, en este caso:
full_name e email.

Accedan a admin/users/create y creen ms usuarios, digamos al
menos 5...

Wait a minute hagamos algo mejor, creen un botn para crear
nuevos usuarios debajo del ttulo de la lista:
Cdigo :
<h1>Lista de usuarios</h1>

<p>
<a href="{{ route('admin.users.create') }}" class="btn btn-
primary">Crear un nuevo usuario</a>
</p>

<!-- Etc -->




Super! No queremos que nuestros usuarios se aprendan todas las
URLs de nuestro panel, Cierto?

Noten el nombre de la ruta admin.users.create.

Dentro del form (app/views/admin/users/form.blade.php) podramos
colocar a un link para regresar a la lista. La ruta
sera admin.users.index. Intenten hacerla ustedes mismos.

Ahora s. Agreguen ms usuarios, al menos 5. Necesito que
agreguen nuevos registros porque vamos a aprender:


Cmo paginar filas con Laravel

Por supuesto si tenemos 5-10 hasta 20 usuarios no habra problema
con mostrarlos todos en una sola pgina, pero imaginen que se
vuelven tan buenos programadores con Laravel que los contratan
para hacer un sistema con cientos de usuarios No van usar all()
para traerlos todos de golpe, hay que buscar otra opcin, y una
buena es paginar los registros.

Paginar con Laravel es increblemente fcil, es hermoso, es

Slo reemplacen all por paginate en el controlador:
Cdigo :
$users = User::paginate();


Y en la vista, debajo de la tabla, agreguen esto:
Cdigo :
{{ $users->links() }}


Ahora recarguen la lista de usuarios (admin/users) y y No pasa
nada!

Esto es porque Laravel espera paginar los registros de 15 en 15, y
uds. no crearon ms de 15 registros, Cierto? En realidad confieso
que yo hice apenas 3

15 registros est bien para la mayora de las situaciones, pero slo
para probar que el paginador funcione podemos hacer 2 cosas:

1. Agregar una propiedad perPage en nuestro modelo User:

En app/models/User.php agregar esto:
Cdigo :
protected $perPage = 2;


Ahora refresquen la lista de usuarios y Tenemos paginacin!

Laravel se encarga de hacer la ruta, el query y el HTML por
nosotros

El mtodo 2 es pasarle directamente a la funcin
paginate, como primer parmetro, el nmero de registros que
queremos ver en cada pgina:
Cdigo :
$users = User::paginate(2);


Este segundo mtodo toma precedencia sobre el primero.


Cmo cambiar el HTML por defecto de la paginacin

Este tema es ms avanzado, pero si queremos que se vea bien la
paginacin nos tocar hacer un pequeo ajuste: vayan
a app/config/view.php y cambien:
Cdigo :
'pagination' => 'pagination::slider',


Por otra ubicacin (que ser relativa a app/views/) como:
Cdigo :
'pagination' => 'pagination'


Guarden y ahora vamos a crear una nueva plantilla para la
paginacin, todo lo que yo hice fue tomar el archivo localizado en:
Cdigo :
vendor/laravel/framework/src/Illuminate/Pagination/views/slider.
php


y modificarlo ligeramente:

app/views/pagination.php:
Cdigo :
<?php
$presenter = new
Illuminate\Pagination\BootstrapPresenter($paginator);
?>

<?php if ($paginator->getLastPage() > 1): ?>
<ul class="pagination">
<?php echo $presenter->render(); ?>
</ul>
<?php endif; ?>


Lo nico que hice fue eliminar un div que sobraba y ponerle la clase
pagination al UL, el PHP lo dej intacto, as que no se asusten, por
favor.

En la versin 3 de Laravel no se poda cambiar el HTML de la
paginacin, as que haba que modificar el CSS de Bootstrap para
conseguir para que fuera compatible con el primero

Bien, recarguemos nuestra lista (admin/users) y debera verse as:



Por supuesto querrn ir de la pgina 1 a la pgina 2, noten que
Laravel usa la misma URL slo que agrega una variable GET a la
URL si estamos en la pgina 2 en adelante:
Cdigo :
admin/users?page=2


Consulten la documentacin oficial para aprender ms sobre
la paginacin en Laravel.

Consultas, preguntas, dudas, felicitaciones al instructor, en los
comentarios por favor.

Stay tuned.


Bonus Track: Construye t mismo la accin / vista show

Hora de probar sus nuevas habilidades con Laravel: a veces la
mejor forma de aprender es intentando hacer las cosas uno mismo,
esto es lo que quiero que intenten ahora:

Crear la accin y vista show dinmicas (la ms sencilla en nuestro
mdulo CRUD)

Los ayudar con algunos tips que les harn falta:


Cmo traer un registro
Traer un (1) solo registro se hace a travs de la
funcin User::find($id), ejemplo:
Cdigo :
$user = User::find($id)


Esta funcin la necesitarn en los mtodos show, edit y update, que
adems reciben el ID numrico de cada registro, dicho id es el
primer parmetro de User::find y permite decirle a Laravel cual de
los registros queremos obtener.


Cmo lanzar errores 404
Si el registro no es encontrado la variable $user contendr el valor
NULL, si ese es el caso deberamos abortar la operacin y lanzar
un error 404, en Laravel lo ltimo se puede hacer as:
Cdigo :
App::abort(404);



Pasar y mostrar datos en la vista
Recuerden pasar el usuario $user a la vista, y recuerden que en ella
cada columna es una propiedad del objeto, ejemplo:
Cdigo :
$user->full_name


Tal como vimos hace un momento.


Crear enlaces entre las diferentes vistas
Por ltimo, sera simptico que cada registro de la lista tuviese un
botn a la ruta mostrar, la ruta se construye as:
Cdigo :
{{ route(admin.users.show, array($user->id) }}


De igual forma, sera buena idea agregar un botn a volver a la
lista desde la accin show.

En el prximo tutorial publicar un posible resultado de este
ejercicio, pero, si ustedes se animan, pueden publicar su progreso,
dudas o preguntas en los comentarios. Intenten avanzar lo ms que
puedan por ustedes mismos. Suerte!
3.1 - Mdulo de usuarios (VI): Editar
un registro con Laravel
Falta poco para terminar nuestro mdulo. Si es tu primera vez en
esta serie de tutoriales, todava ests a tiempo de aprender a crear
un mdulo con Laravel, paso a paso. Hoy veremos cmo editar
registros con Laravel.

Este tutorial es muy trivial, lo haremos basado en el progreso que
hemos hecho hasta ahora, copiando, no, ms bien reusando parte
del cdigo que ya producimos para crear la accin create.

Primero regresemos a la lista de usuarios:

app/views/admin/users/list.blade.php

All vamos a agregar una columna adicional para agregar un botn a
la accin editar usuarios:
Cdigo :
<table class="table table-striped" style="width: 900px">
<tr>
<th>Nombre completo</th>
<th>Correo electr&oacute;nico</th>
<th>Acciones</th>
</tr>
@foreach ($users as $user)
<tr>
<td>{{ $user->full_name }}</td>
<td>{{ $user->email }}</td>
<td>
<a href="{{ route('admin.users.show', $user->id) }}"
class="btn btn-info">
Ver
</a>
<a href="{{ route('admin.users.edit', $user->id) }}"
class="btn btn-primary">
Editar
</a>
</td>
</tr>
@endforeach
</table>




Esto nos permitir acceder a la opcin de editar fcilmente. Ahora,
de vuelta en:

app/controllers/admin/UsersController.php
Cdigo :
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return Response
*/
public function edit($id)
{
return 'Aqui editamos el usuario: ' . $id;
}


Lo vamos a reemplazar por:
Cdigo :
public function edit($id)
{
$user = User::find($id);
if (is_null ($user))
{
App::abort(404);
}

return View::make('admin/users/form')->with('user', $user);
}


Vean lo simple del cdigo:
Cdigo :
$user = User::find($id);


Nos trae el usuario que corresponde a la id numrica almacenada
en la variable $id

Noten que antes le pasamos dicha ID a la ruta edit:
Cdigo :
<a href="{{ route('admin.users.edit', $user->id) }}">


En caso de que la ID no corresponda a ningn usuario vlido,
User::find devolver NULL, por lo tanto:
Cdigo :
if (is_null ($user))
{
App::abort(404);
}


Si el usuario no existe se aborta la operacin con un error 404. Por
ltimo se le pasa el usuario a la vista, como ya hemos hecho antes.

Al darle clic a editar en cualquiera de sus usuarios, vern el mismo
formulario usado para crear pero con los campos llenos

A m me gusta evitar tener 2 vistas con casi el mismo HTML
repetido, en este caso se puede hacer que el mismo formulario sirva
tanto para create como para edit de esta forma:
Cdigo :
@extends ('admin/layout')

<?php

if ($user->exists):
$form_data = array('route' =>
array('admin.users.update', $user->id), 'method' => 'PATCH');
$action = 'Editar';
else:
$form_data = array('route' => 'admin.users.store',
'method' => 'POST');
$action = 'Crear';
endif;

?>

@section ('title') {{ $action }} Usuarios @stop

@section ('content')

<h1>{{ $action }} Usuarios</h1>

<p>
<a href="{{ route('admin.users.index') }}" class="btn btn-
info">Lista de usuarios</a>
</p>

{{ Form::model($user, $form_data, array('role' => 'form')) }}

@include ('admin/errors', array('errors' => $errors))

<div class="row">
<div class="form-group col-md-4">
{{ Form::label('email', 'Direccin de E-mail') }}
{{ Form::text('email', null, array('placeholder' =>
'Introduce tu E-mail', 'class' => 'form-control')) }}
</div>
<div class="form-group col-md-4">
{{ Form::label('full_name', 'Nombre completo') }}
{{ Form::text('full_name', null, array('placeholder' =>
'Introduce tu nombre y apellido', 'class' => 'form-control'))
}}
</div>
</div>
<div class="row">
<div class="form-group col-md-4">
{{ Form::label('password', 'Contrasea') }}
{{ Form::password('password', array('class' => 'form-
control')) }}
</div>
<div class="form-group col-md-4">
{{ Form::label('password_confirmation', 'Confirmar
contrasea') }}
{{ Form::password('password_confirmation', array('class'
=> 'form-control')) }}
</div>
</div>
{{ Form::button($action . ' usuario', array('type' =>
'submit', 'class' => 'btn btn-primary')) }}

{{ Form::close() }}

@stop


En las primeras lneas definimos el ttulo Crear o Editar y la ruta y
mtodo que se le va a pasar al form, dependiendo si el usuario
existe o no.

Tambin se puede lograr lo mismo pasando la data desde el
controlador a la vista:
Cdigo :
public function edit($id)
{
$user = User::find($id);
if (is_null ($user))
{
App::abort(404);
}

$form_data = array('route' =>
array('admin.users.update', $user->id), 'method' => 'PATCH');
$action = 'Editar';

return View::make('admin/users/form', compact('user',
'form_data', 'action'));
}


Lo importante es evitar duplicar cdigo de acuerdo al
principio DRY (Dont repeat yourself), por ejemplo, para el HTML de
errores, dado que va a ser muy comn a todos los mdulos, lo
separ en otra vista y ahora slo hay que incluirlo:
Cdigo :
@include ('admin/errors', array('errors' => $errors))


De esta manera se vuelve ms reusable:

app/views/admin/errors.blade.php:
Cdigo :
@if ($errors->any())
<div class="alert alert-danger">
<button type="button" class="close" data-
dismiss="alert">&times;</button>
<strong>Por favor corrige los siguentes errores:</strong>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif



Completando la accin update

Si se detienen a pensar unos momentos, este mtodo update se
completa de manera similar a store, la diferencia es que ac no
crearemos un nuevo usuario, sino que cargaremos uno tal como
hicimos en el mtodo edit hace un momento, adems tenemos que
cambiar la redireccin en caso de datos no vlidos a la ruta
admin.users.edit. El cdigo resultante quedara as:
Cdigo :
public function update($id)
{
// Creamos un nuevo objeto para nuestro nuevo usuario
$user = User::find($id);

// Si el usuario no existe entonces lanzamos un error
404 :(
if (is_null ($user))
{
App::abort(404);
}

// Obtenemos la data enviada por el usuario
$data = Input::all();

// Revisamos si la data es vlido
if ($user->isValid($data))
{
// Si la data es valida se la asignamos al usuario
$user->fill($data);
// Guardamos el usuario
$user->save();
// Y Devolvemos una redireccin a la accin show
para mostrar el usuario
return Redirect::route('admin.users.show',
array($user->id));
}
else
{
// En caso de error regresa a la accin edit con los
datos y los errores encontrados
return Redirect::route('admin.users.edit', $user-
>id)->withInput()->withErrors($user->errors);
}
}


Con esto ya debera funcionar a medias la funcin de actualizar,
sin embargo, si intento actualizar mi propio usuario recibo un error:
Cdigo :
El email ya ha sido utilizado


Esto es por la regla unique definida en app/models/User.php,
adems que editar la clave debera ser opcional.

Corrijamos el mtodo isValid:
Cdigo :
public function isValid($data)
{
$rules = array(
'email' => 'required|email|unique:users',
'full_name' => 'required|min:4|max:40',
'password' => 'min:8|confirmed'
);

// Si el usuario existe:
if ($this->exists)
{
//Evitamos que la regla unique tome en cuenta el
email del usuario actual
$rules['email'] .= ',email,' . $this->id;
}
else // Si no existe...
{
// La clave es obligatoria:
$rules['password'] .= '|required';
}

$validator = Validator::make($data, $rules);

if ($validator->passes())
{
return true;
}

$this->errors = $validator->errors();

return false;
}


Noten el IF extra para configurar algunas reglas dependiendo si el
usuario ya existe o no

De esta forma, gracias a la propiedad $this->exists de los modelos
de Laravel y un poco de astucia, podemos reusar tanto el mtodo
isValid como nuestro formulario.


Guardar contraseas con Laravel

Como hemos visto, al actualizar un registro la contrasea queda
como campo opcional (para no obligar al usuario a cambiar su
contrasea cada vez que quiera editar otro dato), sin embargo
tenemos que prevenir que Laravel grabe una contrasea vaca en la
base de datos, adems, tambin tenemos que encriptar las
contraseas no vacas. Todo este lo se soluciona muy fcil, dentro
del modelo (app/models/User.php) agregando el siguiente mtodo:
Cdigo :
public function setPasswordAttribute($value)
{
if ( ! empty ($value))
{
$this->attributes['password'] = Hash::make($value);
}
}


Cada vez que se intenta acceder a un atributo, Laravel intenta ver si
el modelo tiene un mtodo llamado get[nombre del atributo en
camelCase]Attribute, as mismo cada vez que se intenta guardar un
atributo dentro del modelo, se intenta llamar set[nombre del atributo
en camelCase]Attribute, que permiten modificar el comportamiento
por defecto. No me creen? Agreguen lo siguiente al modelo,
temporalmente:
Cdigo :
public function getFullNameAttribute()
{
return strtoupper($this->attributes['full_name']);
}


Ahora todos, todos, TODOS los atributos full_name de todos los
usuarios se imprimirn siempre en maysculas, al menos que
borremos o cambiemos el mtodo getFullNameAttribute.

Eloquent tiene muchos mtodos interesantes que se escapan,
lamentablemente, del alcance de este tutorial


El mtodo validAndSave (haciendo que todo se vea an ms limpio y
mejor)

An:
Cdigo :
// Revisamos si la data es vlido
if ($user->isValid($data))
{
// Si la data es valida se la asignamos al usuario
$user->fill($data);
// Guardamos el usuario
$user->save();
}


Parece mucho cdigo, adems hay el mismo cdigo repetido en
store y update, Cierto?

Que tal si en el modelo (app/models/User.php) agregamos un nuevo
mtodo:

Cdigo :
public function validAndSave($data)
{
// Revisamos si la data es vlida
if ($this->isValid($data))
{
// Si la data es valida se la asignamos al usuario
$this->fill($data);
// Guardamos el usuario
$this->save();

return true;
}

return false;
}


Ahora en la accin update podramos escribir, solamente:
Cdigo :
// Revisamos si la data es vlida y guardamos en ese
caso
if ($user->validAndSave($data))
{
// Y Devolvemos una redireccin a la accin show
para mostrar el usuario
return Redirect::route('admin.users.show',
array($user->id));
}
else
{
// En caso de error regresa a la accin create con
los datos y los errores encontrados
return Redirect::route('admin.users.edit', $user-
>id)->withInput()->withErrors($user->errors);
}


La accin store podramos simplificarla tambin de la misma
manera Cmo quedara?



Con esto finalizamos la accin de editar, espero les haya gustado.

P.D. Terminaron la accin show? Si la respuesta es no, todava
tienen un poco de tiempo antes que se publique el prximo y ltimo
tutorial, donde veremos la accin destroy y algo de AJAX!




















3.2 - Mdulo de usuarios (VII):
Eliminar un registro con Laravel
Esta es la ltima entrega sobre la serie cmo crear un mdulo
CRUD de usuarios, y en este ltimo captulo veremos cmo borrar
un registro con Laravel, adems usaremos jQuery y AJAX.

En los captulos previos vimos:Cmo crear las rutas y el controlador
Cmo integrar un layout de Twitter Bootstrap
Crear un formulario
Validar y guardar un formulario
Listar y paginar registros
Editar registros


Para hacer ms sencillo este tutorial y en general casi cualquier
problema, vamos a separar el proceso por partes. Primero vamos a
aprender cmo borrar un registro sin AJAX.

En nuestro formulario de usuarios vamos a colocar lo siguiente:

app/view/admin/users/form.blade.php
Cdigo :
@if ($action == 'Editar')
{{ Form::model($user, array('route' =>
array('admin.users.destroy', $user->id), 'method' => 'DELETE',
'role' => 'form')) }}
<div class="row">
<div class="form-group col-md-4">
{{ Form::submit('Eliminar usuario', array('class' =>
'btn btn-danger')) }}
</div>
</div>
{{ Form::close() }}
@endif




Fjense que como yo uso la misma plantilla para crear y para editar
debo agregar el @if para que la opcin de eliminar se muestre slo
si el usuario est trabajando sobre un registro existente.

El resto es similar a lo que ya hemos visto. Slo que para construir
la ruta se usa admin.users.destroy (destroy no delete) y el mtodo
es DELETE en vez de POST o PATCH.

Tambin les he comentado que los navegadores no soportan sino
los mtodos GET y POST, pero Laravel y otros frameworks como
Symfony (en realidad la idea viene de Symfony) emulan estos
mtodos usando un campo oculto _method por ejemplo. Siempre
pueden ver cdigo fuente (control + u en Chrome) para ver qu les
generan los helper del framework que estn usando.

Al hacer click sobre este botn no vern nada. Pero si vamos al
controlador app/controllers/admin/UsersController.php y
agregamos lo siguiente al mtodo destroy:
Cdigo :
public function destroy($id)
{
return "Eliminando el registro $id";
}


Entonces al cliquear eliminar vern un mensaje. Eso quiere decir
que ya nuestra vista funciona. Ahora veamos cmo hacer para que
el registro se borre realmente.

Hay 2 formas:
Cdigo :
public function destroy($id)
{
$user = User::find($id);

if (is_null ($user))
{
App::abort(404);
}

$user->delete();

return Redirect::route('admin.users.index');
}


Nos traemos el registro, verificamos que exista y por ltimo
llamamos al mtodo delete.

La segunda es ms sencilla:
Cdigo :
public function destroy($id)
{
User::destroy($id);

return Redirect::route('admin.users.index');
}


Este mtodo ms simple slo acepta como parmetro la ID de un
registro, en este caso un usuario y borra el mismo.

A m me gusta ms el primer mtodo porque es ms orientado a
objetos. Quizs adems de borrar al usuario necesitemos borrar
algunas imgenes asociadas a ste o hacer otra operacin, en ese
caso es ms conveniente el primer mtodo.

Si hacemos click en el botn eliminar seremos redireccionados a la
lista pero veremos cmo el registro seleccionado antes fue
eliminado.


Agregar la opcin de eliminar a la lista

En views/admin/users/list.blade.php vamos a agregar un link que
nos servir para llamar el javascript para eliminar un registro:
Cdigo :
<a href="#" data-id="{{ $user->id }}" class="btn btn-
danger btn-delete">
Eliminar
</a>


Este link lo van a agregar al lado del botn editar, de forma que
quede as:



Ahora vamos a agregar al final de la misma plantilla, justo antes del
@stop lo siguiente:
Cdigo :
{{ Form::open(array('route' => array('admin.users.destroy',
'USER_ID'), 'method' => 'DELETE', 'role' => 'form', 'id' =>
'form-delete')) }}
{{ Form::close() }}


Esto nos va a dar un form oculto que servir para llamar a la accin
de delete como en el ejemplo anterior, pero esta vez con javascript.

Noten que ac el ID lo dej como un texto USER_ID, luego lo
reemplazar por el ID correcto, tambin con Javascript.

Ahora vamos a crear un nuevo archivo
en public/assets/js/admin.js con lo siguiente:
Cdigo :
$(window).ready(function () {

if ( $ ('.btn-delete').length)
{
$('.btn-delete').click(function () {
var id = $(this).data('id');
$(this).parents('tr').fadeOut(1000);
});
}

});


Y por supuesto tenemos que llamar al script, para ellos
agreguemos:
Cdigo :
{{ HTML::script('assets/js/admin.js') }}


En app/views/admin/layout.blade.php justo antes del </body>.

Si recargamos la lista y hacemos clic en el botn eliminar de
cualquier usuario de la lista veremos cmo dicha fila se desvanece,
esto gracias al jQuery, pero si presionamos F5 veremos que el
usuario an no ha sido eliminado, esto es porque an falta:


Hacer la peticin AJAX para eliminar el usuario

Primero vamos a adaptar nuestra accin de eliminar
en app/controllers/admin/UsersController.php para que est
preparada para el AJAX:
Cdigo :
public function destroy($id)
{
$user = User::find($id);

if (is_null ($user))
{
App::abort(404);
}

$user->delete();

if (Request::ajax())
{
return Response::json(array (
'success' => true,
'msg' => 'Usuario ' . $user->full_name . '
eliminado',
'id' => $user->id
));
}
else
{
return Redirect::route('admin.users.index');
}
}


Las primeras lneas quedan igual, pero al final vamos a decidir que
si la peticin es AJAX if (Request::ajax()) vamos a devolver
un JSON usando el mtodoResponse::json de Laravel, como
parmetro vemos un array asociativo de PHP con alguna
informacin que podra resultar til para el frontend.

Luego vamos a cambiar nuestro script de admin.js por lo siguiente:
Cdigo :
$(window).ready(function() {

if ($('.btn-delete').length) {
$('.btn-delete').click(function() {
var id = $(this).data('id');
var form = $('#form-delete');
var action = form.attr('action').replace('USER_ID',
id);
var row = $(this).parents('tr');

row.fadeOut(1000);

$.post(action, form.serialize(), function(result) {
if (result.success) {
setTimeout (function () {
row.delay(1000).remove();
alert(result.msg);
}, 1000);
} else {
row.show();
}
}, 'json');
});
}

});


ste no es un tutorial de Javascript sin embargo les voy a explicar
un poco qu hace el nuevo cdigo de admin.js

Primero obtenemos el ID del registro que es muy importante, ste
estaba en un atributo data del link para eliminar colocado en la lista
anteriormente:
Cdigo :
<a ... data-id="{{ $user->id }}" >


Segundo obtenemos el objeto form con Jquery, al que se le asign
un ID de HTML form-delete anteriormente.
Cdigo :
{{ Form::open(array(..., 'id' => 'form-delete')) }}


Luego usando este objeto form para obtener el valor del atributo
action que nos dar la URL que tenemos que invocar para eliminar
el registro, PERO recuerden que estbamos usando un
placeholder USER_ID por eso lo reemplazamos por el ID real que
queremos eliminar, obtenido previamente:
Cdigo :
var action = form.attr('action').replace('USER_ID', id);


A continuacin se obtiene la fila del registro en cuestin:
Cdigo :
var row = $(this).parents('tr')


$(this), en este caso corresponde al botn eliminar y el mtodo
parents de Jquery nos trae finalmente la fila donde se encuentra
dicho botn, que es la fila (<tr>) del mismo usuario.

Luego desaparecemos la fila usando un efecto atractivo de jQuery:
Cdigo :
row.fadeOut(1000);


Y abajo, el tan esperado mtodo para eliminar la fila con AJAX:
Cdigo :
$.post(action, form.serialize(), function (result) { // },
'json');


Vean que:Como primer parmetro usamos la variable action que ya tendr la URL
correcta para eliminar el registro.
Como segundo parmetro serializamos los valores del form-delete (eso nos
permite enviar los campos ocultos _method y el _csrf_token, necesarios para que
la peticin a Laravel sea vlida).
El tercer parmetro es un callback que se ejecutar una vez que la llamada al
servidor haya finalizado con xito.
El cuarto parmetro le dice a Jquery que esperamos que la data obtenida de
regreso est en formato JSON.


Este callback tiene algo de cdigo interesante que realmente no hace mucha falta,
pero quiero que vean qu se puede hacer con la informacin retornada:
Cdigo :
function(result) {
if (result.success) {
setTimeout(function() {
alert(result.msg);
row.delay(1000).remove();
}, 1000);
} else {
alert (El registro + result.id + no pudo ser
eliminado);
row.show();
}
});


Podramos por ejemplo tener un escenario donde el registro no sea eliminado (por
falta de permisos o algo as), en ese caso podemos hacer que si result.success
es falso, la fila vuelva a aparecer en la lista y se muestre un mensaje de error.

Si result.success es verdadero entonces tambin podemos mostrar un mensaje de
xito y eliminamos el HTML de la fila del cdigo.

Lo importante es notar que podemos usar los datos de JSON que devolvimos
desde nuestro controlador para alterar la vista, mostrar un mensaje etc.

En los prximos das publicar un ltimo tutorial con el indice de esta serie de
tutoriales y adems el cdigo final completo.


Bonus track: la accin show para mostrar el usuario




Para quienes hicieron el ejercicio anterior, aqu tienen un ejemplo de cmo podra
quedar la accin show:
Cdigo :
/**
* Display the specified resource.
*
* @param int $id
* @return Response
*/
public function show($id)
{
$user = User::find($id);

if (is_null($user)) App::abort(404);

return View::make('admin/users/show', array('user' =>
$user));
}


Y la vista app/views/admin/users/show.blade.php:
Cdigo :
@extends ('admin/layout'







3.3 - POO: Inyeccin de
dependencias
Los juegos de estrategia y de rol me ayudaron a entender la programacin
orientada a objetos y ciertos patrones de diseo. En Warcraft cada unidad (ej: un
arquero) es un objeto que interacta con otras unidades (objetos), el mapa en s
es un objeto que encapsula todos los objetos anteriores.

Una barraca es tambin un objeto que implementa el patrn Factory porque
produce otros objetos (soldados). Un hroe podra implementar el patrn
singleton dado que es nico en cada partida.

As que para aprender fcilmente qu es la inyeccin de dependencias
imaginemos que estamos construyendo el backend de un juego:

Cdigo :
<?php

class Bow {
// Code here
}

class Elf extends Unit {
protected $bow

public function __construct()
{
$this->bow = new Bow;
}

public function shoot($target)
{
return $this->bow->shoot($target);
}
}

class Orc extends Unit {
//Code here
}

$elf = new Elf;
$elf->setName('Legolas');

$orc = new Orc;

$elf->shoot($orc);


Cada elfo es un objeto que tiene una dependencia en otro objeto (en este caso un
arco), adems, a medida que el elfo aumente de nivel necesitar de otros arcos
ms potentes.

Con nuestro cdigo actual cmo podemos hacer eso? Respuesta: no podemos.
Nuestro heroe est atado a usar un slo tipo de arco y a medida que sus
enemigos se vuelvan ms fuertes y numerosos no podr contra ellos y morir, y
ser tu culpa.
Inyeccin de dependencias al rescate

Refactoricemos:

Cdigo :
<?php

interface BowInterface {
public function shoot($target);
}

class Bow implements BowInterface {
public function shoot($target)
{
// I don't know how to shoot arrows with PHP yet
}
}

class Elf extends Unit {
protected $bow

/**
* Dependency injection using the class constructor
*/
public function __construct(BowInterface $bow = null)
{
if (is_null($bow))
{
$this->bow = new Bow;
}
else
{
$this->bow = $bow;
}
}

/**
* Dependency injection using a setter method
*/
public function setBow(BowInterface $bow)
{
$this->bow = $bow;
}

public function shoot($target)
{
return $this->bow->shoot($target);
}
}


Ahora la clase Elf recibe el arco como parmetro a travs del constructor de la
clase, es decir que cuando creemos un elfo podemos inyectar un arco diferente:

Cdigo :
$elf = new Elf(new LongBow);


Tambin podemos cambiar de arco en cualquier momento usando el mtodo
setter, otra forma de inyectar una dependencia:

Cdigo :
$elf->setBow(new LongBow);

Uso de interfaces

Una interfaz nos permite crear implementaciones de forma segura. En nuestro
ejemplo siempre que LongBow o cualquier arco que creemos implemente la
interfaz "BowInterface" podr ser usada por el objeto Elf sin problemas:

Cdigo :
class LongBow implements BowInterface {
public function shoot($target)
{
// A long bow should have more range and be more
powerful
}
}

En una interfaz slo definimos los headers de cada mtodo que
sea necesario implementar, ejemplo: public function
shoot($target) las clases que implementen una interfaz deben
definir cada uno de esos mtodo con su correspondiente
implementacin de cdigo.
Conclusin

La inyeccin de dependencias es el fondo un concepto sencillo que
har tus objetos mucho ms flexibles y menos dependientes unos
de otros.

En un prximo tutorial veremos este concepto con el
framework Laravel.













3.4 - POO: Inyeccin de
dependencias (II)
En mi artculo anterior aprendimos inyeccin de dependencias en
Laravel, un concepto bsico de la POO, que permite a unos objetos
interactuar con otros sin crear una dependecia como tal, la cual se
inyecta a travs del constructor o de un mtodo setter. Veamos un
ejemplo:

Cdigo :
<?php

$db = new MysqlDatabase($host, $user, $password, $options);
$user = new User($db);

$users = $user->selectAll();


Usamos un objeto para conectarnos a una base de datos MySQL y
luego lo inyectamos a un objeto User. Si luego quisiramos usar
Oracle en teora slo bastara inyectar un objeto OracleDatabase
(con la misma interface de MysqlDatabase). Por lo tanto el manejo
de usuarios no est "atado" a MySQL sino que en teora funcionara
con otras bases de datos.

Si no has ledo el artculo anterior hazlo ahora, no te preocupes que
el equipo secreto de Cristalab mantendr el servidor
funcionando mientras vuelves


El Problema de la inyeccin de dependencias

Lo anterior parece genial, pero Cul es el truco? Imagina un
sistema con 50 tablas distintas y tener que hacer esto cada vez que
quieras usar un objeto del ORM:

Cdigo :
// Muy dificil instanciar un objeto
$db = new MySQLDatabase($host, $user, $password, $options);
$posts = new Post($db);



Contenedores de inyeccin de dependencia o DIC (siglas en ingls)

Si ya el nombre inyeccin de dependencias da miedo, es probable
que contenedor de inyeccin de dependencias te haga saltar de la
silla y huir del susto, pero en realidad es muy sencillo, tan sencillo
que escribir uno en cinco minutos.

Treinta minutos despus...

En un contenedor, usualmente cada clase/objeto es representado
por un alias o nombre que es diferente del nombre de la clase
original. Por ejemplo el alias de MysqlDatabase u OracleDatabase
sera slo db. La clase User podra ser user (en minsculas) y
as


Para instanciar una clase usando el contenedor haremos algo
como esto

Cdigo :
$app->make('db'); // O esto:
$app->make('user');


En vez de esto:
Cdigo :
$db = new MysqlDatabase($host, $user, $password, $options);
$user = new User($db);


El contenedor se encargar de resolver el objeto por nosotros (en
este caso instanciar -si hace falta- y pasar el objeto de base de
datos al usuario).

Por supuesto hay que ensear a nuestro contenedor cmo
hacerlo, pero la ventaja es que slo le enseas una vez.


Ensear al contenedor cmo resolver un objeto



A travs de una closure

Esta opcin me parece la ms flexible, tienes un bloque de cdigo
para indicarle a PHP cmo debe instanciar la clase (configurar
parmetros, etc.) El cdigo dentro de la closure slo ser ejecutado
si llamas a $app->make para el alias en cuestin.

Cdigo :
$app->bind('db', function (Container $app, $options) {
return new MysqlDatabase('local', 'user', 'password',
array('engine' => 'innodb'));
});

// Si no se llama a app->make('db') MysqlDatabase nunca se
instanciara:
$db = $app->make('db');



Indicando directamente el nombre de la clase

En este caso, al momento de hacer la clase con $app->make
tendramos que pasar el array con los parmetros del constructor,
til si cada instanciacin es diferente (aunque en mi contenedor la
opcin del closure tambin acepta parmetros).

Cdigo :
$app->bind('db', 'MysqlDatabase');
//Crea una instancia de la base de datos, el array seran los
parametros pasados al constructor de MysqlDatabase en este caso:
$db = $app->make('db', array('local', 'user', 'password',
array('engine' => 'innodb')));
var_dump($db);



Construyendo un objeto fuera del constructor

Menos ptima ya que tenemos que instanciar el objeto slo para
pasarlo al contenedor, haga falta o no en la aplicacin como tal:

Cdigo :
$app->instance('db', new MysqlDatabase('local', 'user',
'password', array('engine' => 'innodb')));
$db = $app->make('db');
var_dump($db);



Una instancia singleton

Si necesitamos asegurarnos que un objeto se instancie una sola
vez, entonces en vez del mtodo bind usamos el mtodo
singleton con los mismos parmetros, ejemplo:

Cdigo :
$app->singleton('db', function (Container $app, $options) {
return new MysqlDatabase('local', 'user', 'password',
array('engine' => 'innodb'));
});


En resumen tenemos 4 mtodos. bind instance y
singleton que permiten atar un objeto al contenedor,
y make que permite resolverlo y que usaremos cada vez que
necesitemos dicho objeto. Adems recuerden que en el contenedor
todos los objetos tendrn un alias, aunque usemos otra clase los
alias siempre sern los mismos, lo cual es muy conveniente.

La clase la hice con una interfaz similar a la de Laravel a propsito,
aunque sta es ms sencilla y la intencin no es que la usen en sus
proyectos sino que vean cun simple puede ser un contenedor, por
otro lado si no la entienden del todo no hay problema, ms abajo les
dejo ejemplos de su implementacin (que s me interesa que
aprendan):

Cdigo :
<?php

class Container {

protected $singleton = array();
protected $bindings = array();

/**
* Bind an object to the container
* @param $name string alias of the class inside the
container
* @param $resolver string or closure use to create a new
class
* @param bool $singleton whether you need only one instance
of the object or several instances
*/
public function bind($name, $resolver, $singleton = false)
{
$this->bindings[$name] = array(
'resolver' => $resolver,
'singleton' => $singleton
);
}

/**
* Alias of the bind method using the singleton option
* @param $name string alias of the class inside the
container
* @param $resolver string or closure use to create a new
class
*/
public function singleton($name, $resolver)
{
$this->bind($name, $resolver, true);
}

/**
* Bind an instance of an object to our container
* @param $name string alias of the class inside the
container
* @param $object object to be bound
*/
public function instance($name, $object)
{
$this->singleton[$name] = $object;
}

/**
* Create or get an object from the container
* It may be resolved or retrieved from the singleton array
* @param $name string alias of the class inside the
container
* @param array $options options to instantiate a new class
* @return object or null
*/
public function make($name, $options = array())
{
if (isset ($this->singleton[$name]))
{
return $this->singleton[$name];
}

if ( ! isset ($this->bindings[$name]))
{
return null;
}

$resolver = $this->bindings[$name]['resolver'];

if (is_string($resolver))
{
$reflection = new ReflectionClass($resolver);
$object = $reflection->newInstanceArgs($options);
}
elseif ($resolver instanceof Closure)
{
$object = $resolver($this, $options);
}

if ($this->bindings[$name]['singleton'])
{
$this->singleton[$name] = $object;
}

return $object;
}

}


Ahora creemos algunos objetos tontos slo para poder hacer uso
del contenedor:

Cdigo :
class MysqlDatabase {

protected $connection;

public function __construct($host, $user, $password,
$options)
{
$this->connection = compact('host', 'user', 'password',
'options');
}
}

class User {
protected $db;
public function __construct($db)
{
$this->db = $db;
}
}


Ok, ahora hagamos el ejemplo del inicio de este post pero usando
nuestro contenedor.

1. Instanciamos:

Cdigo :
$app = new Container();


2. Le explicamos al contenedor cmo resolver el alias db:

Cdigo :
$app->singleton('db', function ($app) {
return new MysqlDatabase('local', 'me', 'pony123456',
array('engine' => 'innodb'));
});


3. Le explicamos al contenedor cmo resolver el alias user. Noten
que dentro del closure hacemos uso del mismo Container para
resolver la DB (dado que user necesita db):

Cdigo :
$app->bind('user', function ($app) {
$db = $app->make('db'); //devolver la DB almacenada en el
contenedor
return new User($db);
});


4. Por ltimo haremos (make) un usuario (user) y lanzamos un
var_dump:

Cdigo :
$user = $app->make('user');
var_dump($user);


Si corren el ejemplo vern que el objeto User fue creado y que
dentro de ste se encuentra el objeto MysqlDatabase!

Al usar un contenedor todas las dependencias de un objeto se
definen una vez y son reusables y si necesitas cambiar la forma
como es instanciado un objeto slo cambias en un lugar de tu
aplicacin y listo.


Cuando no usar un contenedor ni inyeccin de dependencias?

En el caso de que tu aplicacin sea muy sencilla es muy posible que
no te haga falta.


Al usar un contenedor mi aplicacin no depende ahora de ste?

Es irnico, la idea es eliminar dependencias y creamos otra, pero es
el menor de los males, con l todas las dems clases de nuestra
aplicacin quedan independientes y pueden ser reemplazadas
fcilmente.








3.5 - POO: Inyeccin de
dependencias en Laravel (III)
Este es el tercer tutorial de la serie sobre inyeccin de
dependencias. Antes de comenzar asegrate de haber ledo el
primero y el segundo tutorial de esta nueva entrega.

En la POO generalmente usamos el constructor de una clase para
definir sus dependencias. Ejemplo:

Cdigo :
class MysqlDatabase {

}

class UserRepo {
/**
* @var MysqlDatabase $db
*/
protected $db;

public function __construct(MysqlDatabase $db)
{
$this->db = $db;
}
}

class PostRepo {
/**
* @var MysqlDatabase $db
*/
protected $db;

public function __construct(MysqlDatabase $db)
{
$this->db = $db;
}
}

class PostsController {

protected $users;
protected $posts;

public function __construct(UserRepo $users, PostRepo
$posts)
{
$this->users = $users;
$this->posts = $posts;
}

}


UseRepo y PostRepo dependen de MysqlDatabase, y
PostsController depende de UserRepo y PostRepo. Slo para crear
un PostsController tendramos que hacer esto:

Cdigo :
$db = new MysqlDatabase();
$users = new UserRepo($db);
$posts = new PostRepo($db);
$controller = new PostsController($users, $posts);
var_dump($controller);


Mucho trabajo, no? Bueno, uno de los features que ms me gusta
de Laravel es que puede instanciar un objeto por nosotros, creando
todas las dependencias que hagan falta, como les mostr en este
artculo.


Inyeccin de dependencias en Laravel

Laravel usa las clases Reflection de PHP en su contenedor para
conocer qu dependencias tiene cada clase y las crea una a una,
recursivamente (como un rbol de dependencias). Aunque parezca
algo super complicado es tan fcil que voy a crearles un ejemplo en
tan slo cinco minutos

Otros 30 minutos despus (Los programadores somos demasiado
optimistas con los tiempos)

Veamos el cdigo y debajo los ejemplos:

Cdigo :
class Factory {

/**
* Store the alias between interfaces/parent classes and
concrete/child classes
* @var array
*/
protected $alias = array();

/**
* Bind an alias to a real class name. i.e.:
UserRepoInterface to UserRepo.
* Can be use to replace parent classes with child classes.
* (Be aware both classes would need the same interface).
* @param $alias
* @param $name
*/
public function bind($alias, $name)
{
$this->alias[$alias] = $name;
}

/**
* Get the real name used for a class, as indicated by the
bind method above
* Example: getRealName('UserRepoInterface') should return
'UserRepo'
* @param $name
* @return mixed
*/
public function getRealName($name)
{
if (isset ($this->alias[$name]))
{
$name = $this->alias[$name];
}

return $name;
}

/**
* Build a new object determines and instantiate its
dependencies automatically
* @param $name
* @return object
*/
public function build($name)
{
try
{
$name = $this->getRealName($name);

$reflection = new ReflectionClass($name);

if ( ! $reflection->isInstantiable())
{
throw new Exception($name . " is not
instantiable");
}

$constructor = $reflection->getConstructor();

if (is_null($constructor))
{
return new $name;
}

$parameters = $constructor->getParameters();

$args = array();

foreach ($parameters as $parameter)
{
$args[] = $this->build($parameter->getClass()-
>getName());
}

return $reflection->newInstanceArgs($args);
}
catch(Exception $e)
{
exit('Error trying to build "' . $name . '": ' . $e-
>getMessage());
}
}

}


Ahora para crear un PostsController slo hacemos esto:

Cdigo :
$factory = new Factory;

$posts = $factory->build('PostsController');

var_dump($posts);


Vean de nuevo cmo la nueva clase Factory instancia por nosotros
el controlador y sus dependencias y las dependencias de las
dependencias: PostController -> UserRepo -> MysqlDatabase, etc.

Pero la mejor prctica es no atar una implementacin a una clase
concreta sino usar interfaces, veamos esto ltimo. Primero las
clases e interfaces dummies para crear el ejemplo:

Cdigo :
interface DatabaseInterface {
}

class MysqlDatabase implements DatabaseInterface {
}

interface UserRepoInterface {

}

interface PostRepoInterface {

}

class UserRepo implements UserRepoInterface {
/**
* @var DatabaseInterface $db
*/
protected $db;

public function __construct(DatabaseInterface $db)
{
$this->db = $db;
}
}

class PostRepo implements PostRepoInterface {
/**
* @var DatabaseInterface $db
*/
protected $db;

public function __construct(DatabaseInterface $db)
{
$this->db = $db;
}
}

class PostsController {

protected $users;
protected $posts;

public function __construct(UserRepoInterface $users,
PostRepoInterface $posts)
{
$this->users = $users;
$this->posts = $posts;
}

}


Noten que PostsController ahora necesita "UserRepoInterface" en
vez de "UserRepo" y UserRepo necesita de DatabaseInterface en
vez de MysqlDatabase, esto hace nuestras clases mucho ms
flexibles (podramos tener diferentes repositorios y bases de datos),
pero si ahora procedemos como antes:

Cdigo :
$factory = new Factory;

$controller = $factory->build('PostsController');
var_dump($controller);


Boom! Error trying to build "UserRepoInterface": UserRepoInterface
is not instantiable Por qu? No se puede instanciar una interface, y
la clase Factory no sabe qu hacer. Ac s necesita instrucciones
adicionales pero es muy fcil:

Cdigo :
$factory = new Factory;

$factory->bind('DatabaseInterface', 'MysqlDatabase');
$factory->bind('UserRepoInterface', 'UserRepo');
$factory->bind('PostRepoInterface', 'PostRepo');

$controller = $factory->build('PostsController');

var_dump($controller);


Laravel hace esto, al instanciar controladores usa el IoC que permite
instanciar de manera automtica todas las dependencias. Similar a
lo que programamos aqu.

Por ltimo quiero aclarar que mi clase es slo con fines educativos,
hara falta integrarla con el Container del artculo pasado, crear Unit
Tests, etc. Mi intencin en este tutorial es como el mago que revela
los trucos, al entender cmo funcionan los frameworks por dentro se
hacen mejores programadores y la prxima vez que alguien les
hable de Dependency injection y Automatic resolution no se
sentirn intimidados.

Вам также может понравиться