Spanish (Español) translation by Steven (you can also view the original English article)
En esta miniserie de Tuts+, construiremos una aplicación web desde cero, mientras nos sumergimos en un nuevo framework de PHP que está cogiendo rápidamente vapor, llamado Laravel.
En esta lección, trabajaremos en una parte integral de cualquier aplicación web: los modelos. En el camino, aprenderemos sobre la increíble implementación de ORM de Laravel: Eloquent.
Revisión
¡Bienvenido de nuevo a nuestra serie de aplicaciones web desde cero con Laravel! En el primer tutorial de la serie, aprendimos mucho sobre Laravel y su filosofía:
- Qué es Laravel
- Lo que diferencia a Laravel de otros frameworks PHP
- Dónde descargar Laravel
- Cómo configurar Laravel
- Cómo funciona el sistema de rutas de Laravel
- Algunas otras características del sistema de rutas de Laravel
- Cómo crear tu primer controlador en Laravel
- Algunas características adicionales con los controladores de Laravel
- Cómo crear tu primera Vista en Laravel
- Cómo utilizar el motor de plantillas blade de Laravel
Si aún no lo has leído, deberías echar un vistazo al tutorial anterior y darle una lectura - esto hará que sea más fácil entender la filosofía detrás de Laravel y la mayor parte de lo que hablaremos en este tutorial.
En esta segunda parte de la serie Laravel, crearemos una parte crucial de nuestra aplicación web de prueba, Instapics, que es la implementación del modelo. ¡Sin más preámbulos, empecemos!
¿Qué son los "Modelos"?
Ya he hablado un poco sobre lo que son los modelos en uno de mis artículos anteriores, Zend Framework desde cero - Modelos e Integrando Doctrine ORM, así que para evitar repetirlo, escribiré la esencia de lo que escribí antes aquí. Siéntete libre de referirte al otro tutorial y leer más acerca de qué modelos están allí.
Resumen:
- Los modelos son representaciones de la base de datos y deben estar donde reside toda la lógica de la empresa de una aplicación
- Los controladores se comunican con los Modelos y les piden que obtengan la información que necesitan
- Después, un controlador pasa esta información a la vista y se muestra
- Es muy raro que un modelo interactúe directamente con una vista, pero a veces puede suceder cuando es necesario
- Los modelos pueden hablar con otros modelos y no son autónomos. Tienen relaciones que se entrelazan entre sí
- Estas relaciones hacen que sea más fácil y rápido para un Controlador obtener información, ya que no tiene que interactuar con diferentes Modelos - los Modelos pueden hacerlo entre ellos
Los modelos en Laravel, o en la mayoría de los frameworks, se desarrollan de la misma manera. La diferencia es que Laravel nos da una manera fácil de construir estos modelos, proporcionándonos métodos de uso general que la mayoría de los modelos necesitarían - el Eloquent de ORM.
El Eloquent de ORM
Un ORM es un mapeador relacional de objetos, ¡y Laravel tiene uno que te encantará! Se denomina "Eloquent", porque te permite trabajar con tus objetos de base de datos y las relaciones mediante una sintaxis elocuente y expresiva.
Eloquent ORM es la implementación ORM integrada de Laravel. En mi opinión, es una de las mejores implementaciones de ORM que he visto hasta ahora- rivalizando incluso con Doctrine ORM. Es increíblemente elegante, haciendo uso de las convenciones estándar de la industria para disminuir la configuración.
Convenciones
Por ejemplo, el uso de un modelo elocuente supone que la tabla que representa el modelo tiene un campo id
. El id
es la clave primaria para cualquier registro y lo utilizan la mayoría de los métodos de Eloquent.
Otra cosa que Eloquent asume correctamente es que el nombre de la tabla es la forma plural del modelo. Por ejemplo, el modelo User
hará referencia a la tabla users
. Como esto podría no ser siempre el estándar para algunos, Laravel proporciona una manera de invalidar esto: simplemente utiliza el indicador $table
:
1 |
class User extends Eloquent { |
2 |
public static $table = 'my_users'; |
3 |
}
|
Esto indicará a Laravel que no use la convención y, en su lugar, use una tabla especificada.
Por último, Laravel también puede automatizar la creación y actualización de las marcas de tiempo para nosotros. Para ello, agrega una columna created_at
y/o updated_at
en la tabla y establece la marca $timestamp
en el modelo:
1 |
class User extends Eloquent { |
2 |
public static $timestamps = true; |
3 |
}
|
Eloquent verá la marca y establecerá automáticamente el campo created_at
en la creación y actualizará el campo updated_at
cada vez que se actualice un registro. Bastante bueno, ¿no?
Recuperación rápida
Recuperar registros es muy fácil con los métodos de recuperación de Eloquent. Por ejemplo, ¿necesitas encontrar un registro de usuario específico? Sólo haz:
1 |
$user = User::find($user_id); |
¡Esto devuelve un modelo User
en el que puedes realizar operaciones! ¿Necesitas usar condicionales? Imaginemos que deseas obtener un usuario por su dirección de correo electrónico. Para llevar a cabo esta tarea, puedes hacer algo como:
1 |
$user = User::where('email', '=', $email)->first(); |
Alternativamente, podrías utilizar los métodos dinámicos de Laravel:
1 |
$user = User::where_email($email)->first(); |
Inserciones fáciles & Actualizaciones
La inserción y actualización de modelos mediante Eloquent se puede realizar en tres pasos.
- Paso 1 - Obtener/Crear el modelo.
1
$user = new User();
2
//or get an existing user
3
$user = User::get($user_id);
- Paso 2 - Establecer los datos
1
$user->email = 'nikko@instapics.com';
2
$user->password = 'test1234';
- Paso 3 - Guardar
1
$user->save();
- ¡Listo!
Y finalmente, definir relaciones.
Eloquent hace que el proceso de definición de relaciones y recuperación de modelos relacionados sea simple e intuitivo.
¡Maldita sea! Eloquent admite tres tipos de relaciones:
- Uno a uno
- Uno a muchos
- Muchos a muchos
Para definir una relación entre modelos, deberás crear un método en ambos modelos que "describa" sus relaciones. Por ejemplo, supongamos que User
has_one
User_Profile
. Puedes hacerlo definiendo un método user_profile
en el modelo User
:
1 |
class User extends Eloquent { |
2 |
public function user_profile() |
3 |
{
|
4 |
return $this->has_one('User_Profile'); |
5 |
}
|
6 |
}
|
Dado que User
es nuestro modelo "dominante" aquí (es decir, un usuario tiene un perfil, y no un perfil tiene un usuario), definimos que User_Profile
belongs_to
(pertenece a un usuario) User
:
1 |
class User_Profile extends Eloquent { |
2 |
public function user() |
3 |
{
|
4 |
return $this->belongs_to('User'); |
5 |
}
|
6 |
}
|
Una vez que hayamos definido estas relaciones, entonces podemos hacer lo siguiente:
1 |
/*
|
2 |
Get the User_Profile object of a User
|
3 |
This executes two SQL queries:
|
4 |
|
5 |
SELECT * FROM `users` WHERE `id` = $user_id
|
6 |
SELECT * FROM `user_profiles` WHERE `user_id` = $user_id
|
7 |
*/
|
8 |
$user = User::find($user_id); |
9 |
$user_profile = $user->user_profile; |
10 |
|
11 |
/*
|
12 |
We can also do it the other way around
|
13 |
*/
|
14 |
$user_profile = User_Profile::where('user_id', '=', $user_id)->first(); |
15 |
$user = $user_profile->user; |
Una cosa que vale la pena señalar aquí es otra convención: Eloquent asume que la clave externa utilizada en User_Profile
es el nombre +_id
de la tabla a la que se hace referencia. Una vez más, si deseas cambiar este comportamiento, puedes anularlo:
1 |
class User extends Eloquent { |
2 |
public function user_profile() |
3 |
{
|
4 |
return $this->has_one('User_Profile', 'user_profile_user_id'); |
5 |
}
|
6 |
}
|
Supongamos que queremos definir la relación entre User
y Photo
(sus fotos subidas). Esta es una relación de uno a muchos One-to-Many, a diferencia de la relación User Profile
a User
que era uno a uno One-to-One. Sabemos que User
has_many
Photo
, por lo cual:
1 |
class User extends Eloquent { |
2 |
public function photos() |
3 |
{
|
4 |
return $this->has_many('Photo'); |
5 |
}
|
6 |
}
|
7 |
...
|
8 |
...
|
9 |
...
|
10 |
class Photo extends Eloquent { |
11 |
public function user() |
12 |
{
|
13 |
return $this->belongs_to('User'); |
14 |
}
|
15 |
}
|
La principal diferencia aquí con has_one
es que la función que usaremos para recuperar las fotos de un usuario ahora devolverá una matriz de objetos del modelo Photo
. Por lo tanto, si quisiéramos traer todas las fotos de un usuario, podríamos hacer lo siguiente:
1 |
$photos = User::find($user_id)->photos; |
2 |
foreach($photos as $photo) { |
3 |
...
|
4 |
...
|
5 |
...
|
6 |
}
|
No, referirse a photos
como una propiedad no es un error tipográfico. Laravel nos da ese sabor dulce. También podríamos hacer:
1 |
$photos = User::find($user_id)->photos()->get(); |
Relaciones de muchos a muchos - Mant-to-Many
Este es un poco complicado, pero una vez implementado, hace que sea fácil manejar las relaciones de muchos a muchos entre los modelos. Imaginemos, por ejemplo, que, de nuevo, tienes un modelo User
y cada uno de estos usuarios puede tener varios grupos y para eso usamos el modelo Group
. Un grupo también puede tener varios usuarios. Usaremos tres tablas para representar estas relaciones particulares:
- Users - tabla donde están todos nuestros usuarios
- Groups - tabla donde están todos nuestros grupos
- Group User - tabla que enumera todos los usuarios de un grupo
La convención de estructura de tabla que Eloquent buscará será algo como esto:
- users
- id
- ... otras columnas
- groups
- id
- ... otras columnas
- group_user
- id
- user_id
- group_id
- ... otras columnas
Otra convención a tener en cuenta aquí es que la tabla intermedia, group_user
, son los nombres singulares de las dos tablas que estás conectando, organizados alfabéticamente con un carácter de subrayado. Como siempre, somos libres de anular esto.
Así es como se verá el código dentro de cada uno de los modelos para estas tres tablas:
1 |
class User extends Eloquent { |
2 |
public function groups() |
3 |
{
|
4 |
//if we wanted to override the default naming convention
|
5 |
//for the intermediate table, we can do it like so:
|
6 |
//return $this->has_many_and_belongs_to('Group', 'group_listings');
|
7 |
|
8 |
return $this->has_many_and_belongs_to('Group'); |
9 |
}
|
10 |
}
|
11 |
...
|
12 |
...
|
13 |
...
|
14 |
class Group extends Eloquent { |
15 |
public function users() |
16 |
{
|
17 |
//if we wanted to override the default naming convention
|
18 |
//for the intermediate table, we can do it like so:
|
19 |
//return $this->has_many_and_belongs_to('User', 'group_listings');
|
20 |
|
21 |
return $this->has_many_and_belongs_to('User'); |
22 |
}
|
23 |
}
|
24 |
...
|
25 |
...
|
26 |
...
|
27 |
class Group_User extends Eloquent { |
28 |
public function group() |
29 |
{
|
30 |
return $this->has_one('Group'); |
31 |
}
|
32 |
|
33 |
public function user() |
34 |
{
|
35 |
return $this->has_one('User'); |
36 |
}
|
37 |
}
|
Con esto en su lugar, podemos aprovechar las funciones de relación de Eloquent:
1 |
//Get a user's groups
|
2 |
$groups = User::find($user_id)->groups; |
3 |
|
4 |
//Get all users in a group
|
5 |
$users = Group::find($group_id)->users; |
Paso 1 - Creación de la base de datos Instapics

Continuando con nuestra aplicación web, Instapics, comencemos creando la base de datos de nuestra aplicación. Para ello, vamos a anotar las funcionalidades deseadas de la aplicación:
- Los usuarios pueden iniciar sesión y registrarse para obtener una cuenta
- Los usuarios pueden seguir a otros usuarios para ver las fotos que han subido
- Los usuarios pueden subir su propia foto y aplicar un filtro a ella
- Los usuarios pueden comentar y darle me gusta a otras fotos
Para esto, podemos deducir las tablas de base de datos que necesitaremos:
- users
- id (uno a uno con user_profiles.user_id, muchos a muchos usando la misma tabla relationships.follower_id y followed_id, uno a muchos con photos.user_id y photo_comments.user_id)
- password
- created_at
- updated_at
- user_profiles
- id
- user_id (uno a uno con users.id)
- name
- profile_photo
- relationships
- id
- follower_id (uno a uno con users.id)
- followed_id (uno a uno con users.id)
- created_at
- updated_at
- photos
- id (uno a muchos con photo_comments.user_id)
- user_id (uno a uno con users.id)
- location
- description
- created_at
- updated_at
- photo_comments
- id
- user_id (uno a uno con users.id)
- photo_id (uno a uno con photos.id)
- message
- created_at
- updated_at
Vamos a continuar y vamos crear estas tablas. Para este proyecto, usaré MySQL; no dudes en copiar y pegar estos comandos.
1 |
CREATE DATABASE `instapics`; |
2 |
USE `instapics`; |
3 |
|
4 |
CREATE TABLE `instapics`.`users` ( |
5 |
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, |
6 |
`email` VARCHAR(100) NOT NULL, |
7 |
`password` VARCHAR(100) NOT NULL, |
8 |
`created_at` DATETIME NOT NULL, |
9 |
`updated_at` DATETIME NOT NULL, |
10 |
PRIMARY KEY (`id`), |
11 |
UNIQUE INDEX `Index_email`(`email`) |
12 |
)
|
13 |
ENGINE = InnoDB |
14 |
CHARACTER SET utf8 COLLATE utf8_general_ci; |
15 |
|
16 |
CREATE TABLE `instapics`.`user_profiles` ( |
17 |
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, |
18 |
`user_id` INTEGER UNSIGNED NOT NULL, |
19 |
`name` TEXT NOT NULL, |
20 |
`profile_photo` TEXT NOT NULL, |
21 |
PRIMARY KEY (`id`), |
22 |
UNIQUE INDEX `Index_user_id`(`user_id`), |
23 |
CONSTRAINT `FK_user_profiles_user_id` FOREIGN KEY `FK_user_profiles_user_id` (`user_id`) |
24 |
REFERENCES `users` (`id`) |
25 |
ON DELETE CASCADE |
26 |
ON UPDATE CASCADE |
27 |
)
|
28 |
ENGINE = InnoDB |
29 |
CHARACTER SET utf8 COLLATE utf8_general_ci; |
30 |
|
31 |
CREATE TABLE `instapics`.`relationships` ( |
32 |
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, |
33 |
`follower_id` INTEGER UNSIGNED NOT NULL, |
34 |
`followed_id` INTEGER UNSIGNED NOT NULL, |
35 |
`created_at` DATETIME NOT NULL, |
36 |
`updated_at` DATETIME NOT NULL, |
37 |
PRIMARY KEY (`id`), |
38 |
UNIQUE INDEX `Index_follower_id_followed_id`(`follower_id`, `followed_id`), |
39 |
CONSTRAINT `FK_relationships_follower_id` FOREIGN KEY `FK_relationships_follower_id` (`follower_id`) |
40 |
REFERENCES `users` (`id`) |
41 |
ON DELETE CASCADE |
42 |
ON UPDATE CASCADE, |
43 |
CONSTRAINT `FK_relationships_followed_id` FOREIGN KEY `FK_relationships_followed_id` (`followed_id`) |
44 |
REFERENCES `users` (`id`) |
45 |
ON DELETE CASCADE |
46 |
ON UPDATE CASCADE |
47 |
)
|
48 |
ENGINE = InnoDB |
49 |
CHARACTER SET utf8 COLLATE utf8_general_ci; |
50 |
|
51 |
CREATE TABLE `instapics`.`photos` ( |
52 |
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, |
53 |
`user_id` INTEGER UNSIGNED NOT NULL, |
54 |
`location` TEXT NOT NULL, |
55 |
`description` TEXT NOT NULL, |
56 |
`created_at` DATETIME NOT NULL, |
57 |
`updated_at` DATETIME NOT NULL, |
58 |
PRIMARY KEY (`id`), |
59 |
CONSTRAINT `FK_photos_user_id` FOREIGN KEY `FK_photos_user_id` (`user_id`) |
60 |
REFERENCES `users` (`id`) |
61 |
ON DELETE CASCADE |
62 |
ON UPDATE CASCADE |
63 |
)
|
64 |
ENGINE = InnoDB |
65 |
CHARACTER SET utf8 COLLATE utf8_general_ci; |
66 |
|
67 |
CREATE TABLE `instapics`.`photo_comments` ( |
68 |
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, |
69 |
`user_id` INTEGER UNSIGNED NOT NULL, |
70 |
`photo_id` INTEGER UNSIGNED NOT NULL, |
71 |
`message` TEXT NOT NULL, |
72 |
`created_at` DATETIME NOT NULL, |
73 |
`updated_at` DATETIME NOT NULL, |
74 |
PRIMARY KEY (`id`), |
75 |
CONSTRAINT `FK_photo_comments_user_id` FOREIGN KEY `FK_photo_comments_user_id` (`user_id`) |
76 |
REFERENCES `users` (`id`) |
77 |
ON DELETE CASCADE |
78 |
ON UPDATE CASCADE, |
79 |
CONSTRAINT `FK_photo_comments_photo_id` FOREIGN KEY `FK_photo_comments_photo_id` (`photo_id`) |
80 |
REFERENCES `photos` (`id`) |
81 |
ON DELETE CASCADE |
82 |
ON UPDATE CASCADE |
83 |
)
|
84 |
ENGINE = InnoDB |
85 |
CHARACTER SET utf8 COLLATE utf8_general_ci; |
Alternativamente, podrías usar las migraciones, pero las revisaremos en una lección futura.
Paso 2 - Configurar la base de datos de Laravel
Antes de hacer nada con los modelos Laravel, necesitamos configurar la base de datos de nuestra instalación de Laravel. Abre application/config/database.php, para encontrar algunos de estos ajustes:
- profile - establecer esto en
true
registrará todas las horas de las consultas en SQL en los registros de Laravel. Deja esto comotrue
por ahora. - fetch - el tipo de datos devueltos de PDO. El valor predeterminado es
PDO::FETCH_CLASS
y debe dejarse así. - default - este es el nombre de la configuración de conexión utilizada por la aplicación. El nombre hace referencia al índice de la matriz
$connections
justo debajo - connections: una matriz asociativa de las posibles conexiones para la aplicación.
- driver: el tipo de servidor de base de datos. Puede ser
pgsql
,sqlite
,mysql
osqlsrv
- host - el nombre de host del servidor de tu base de datos
- database - el nombre de la base de datos
- username - nombre de usuario para usar en el servidor de la base de datos
- password - contraseña para usar en el servidor de la base de datos
- charset - El tipo de charset para usar en el servidor de la base de datos
- prefix - prefijo de tabla en la base de datos, si hay
- driver: el tipo de servidor de base de datos. Puede ser
- redis: si planeas utilizar la biblioteca
Redis
de Laravel, puedes configurar la información del servidor aquí.
Para los fines de este tutorial, usaremos MySQL. Tu archivo database.php debería tener un aspecto similar al siguiente (eliminé los comentarios, pero deberías dejarlos):
1 |
return array( |
2 |
'profile' => true, |
3 |
'fetch' => PDO::FETCH_CLASS, |
4 |
'default' => 'mysql', |
5 |
'connections' => array( |
6 |
'mysql' => array( |
7 |
'driver' => 'mysql', |
8 |
'host' => 'localhost', |
9 |
'database' => 'instapics', |
10 |
'username' => 'root', |
11 |
'password' => '(yourpassword)', |
12 |
'charset' => 'utf8', |
13 |
'prefix' => '', |
14 |
),
|
15 |
),
|
16 |
'redis' => array( |
17 |
'default' => array( |
18 |
'host' => '127.0.0.1', |
19 |
'port' => 6379, |
20 |
'database' => 0 |
21 |
),
|
22 |
)
|
23 |
);
|
Paso 3 - Creación de tu primer modelo en laravel
Comienza creando un modelo de Laravel dentro de la carpeta application/models. Crea user.php dentro y añade el siguiente código:
1 |
class User extends Eloquent { |
2 |
|
3 |
}
|
Ahora, sobre la base de nuestra revisión de cuáles son las relaciones de User
, necesitamos codificar los métodos de las relaciones para todas ellas:
1 |
class User extends Eloquent { |
2 |
|
3 |
//setting $timestamp to true so Eloquent
|
4 |
//will automatically set the created_at
|
5 |
//and updated_at values
|
6 |
public static $timestamps = true; |
7 |
|
8 |
public function user_profile() |
9 |
{
|
10 |
return $this->has_one('User_Profile'); |
11 |
}
|
12 |
|
13 |
public function followers() |
14 |
{
|
15 |
return $this->has_many_and_belongs_to('User', 'relationships', 'followed_id', 'follower_id'); |
16 |
}
|
17 |
|
18 |
public function following() |
19 |
{
|
20 |
return $this->has_many_and_belongs_to('User', 'relationships', 'follower_id', 'followed_id'); |
21 |
}
|
22 |
|
23 |
public function photos() |
24 |
{
|
25 |
return $this->has_many('Photo'); |
26 |
}
|
27 |
|
28 |
public function photo_comment() |
29 |
{
|
30 |
return $this->has_many('Photo_Comment'); |
31 |
}
|
32 |
}
|
Notablemente, hacemos uso de algunas funciones avanzadas de muchos a muchos aquí, debido a la estructura de la tabla de nuestro modelo 'follower' (es decir, la tabla users
hace referencia a la tabla relationships
, la cual hace referencia a la tabla users
de nuevo). La función has_many_and_belongs_to
tiene la siguiente firma de método:
1 |
/**
|
2 |
* Get the query for a many-to-many relationship.
|
3 |
*
|
4 |
* @param string $model
|
5 |
* @param string $table
|
6 |
* @param string $foreign
|
7 |
* @param string $other
|
8 |
* @return Relationship
|
9 |
*/
|
10 |
public function has_many_and_belongs_to($model, $table = null, $foreign = null, $other = null) |
Esto realmente nos permite crear un modelo que tiene una relación de muchos a muchos con sí mismo (es decir, los usuarios siguen a otros usuarios). Utilizamos followers
y following
como los nombres de los métodos en el modelo User
para permitirnos obtener seguidores de un usuario u obtener todos los usuarios que un solo usuario está siguiendo, respectivamente.
Siguiendo el ejemplo del modelo User
, crea los otros modelos. Cuando termines, debes tener:
- application/models/photo.php
- application/models/photo_comment.php
- application/models/relationship.php
- application/models/user.php
- application/models/user_profile.php
Estos archivos estarán en el repositorio Git del tutorial, por lo que si prefieres descargarlos, puedes encontrarlos aquí: https://github.com/nikkobautista/laravel-tutorial
Paso 4 - Crear las funciones del usuario para Instapics
Comencemos a usar nuestros modelos creando algunas de las funciones de usuario que necesitaremos en la aplicación. En primer lugar: registro de usuarios. Desde el tutorial anterior, ya hemos creado un formulario de registro/inicio de sesión en la página de inicio. En este momento, esto no está haciendo nada, pero vamos a conectarlo a un controlador de User
, para que se pueda autenticar mediante la acción authenticate
. Crea un archivo en application/controllers/user.php con el siguiente código:
1 |
class User_Controller extends Base_Controller |
2 |
{
|
3 |
public function action_authenticate() |
4 |
{
|
5 |
|
6 |
}
|
7 |
}
|
Abre application/views/home/index.blade.php y busca el formulario de inicio de sesión. Actualiza el formulario de la línea 18 para enviarlo al método action_authenticate()
:
1 |
<form class="well" method="POST" action="user/authenticate"> |
Volviendo al controlador User_Controller
, agreguemos un poco de código en action_authenticate()
:
1 |
class User_Controller extends Base_Controller |
2 |
{
|
3 |
public function action_authenticate() |
4 |
{
|
5 |
$email = Input::get('email'); |
6 |
$password = Input::get('password'); |
7 |
$new_user = Input::get('new_user', 'off'); |
8 |
|
9 |
if( $new_user == 'on' ) { |
10 |
try { |
11 |
$user = new User(); |
12 |
$user->email = $email; |
13 |
$user->password = Hash::make($password); |
14 |
$user->save(); |
15 |
Auth::login($user); |
16 |
|
17 |
return Redirect::to('dashboard/index'); |
18 |
} catch( Exception $e ) { |
19 |
echo "Faield to create new user!"; |
20 |
}
|
21 |
} else { |
22 |
$credentials = array( |
23 |
'username' => $email, |
24 |
'password' => $password |
25 |
);
|
26 |
if( Auth::attempt($credentials)) { |
27 |
return Redirect::to('dashboard/index'); |
28 |
} else { |
29 |
echo "Failed to login!"; |
30 |
}
|
31 |
}
|
32 |
}
|
33 |
}
|
Vamos a desglosar lo que hemos hecho aquí hasta ahora:
- Usamos la librería
Input
para obtener los datos del formulario enviado - Si se ha marcado el indicador
$new_user
, creamos un nuevo usuario, utilizando la bibliotecaHash
para generar una contraseña cifrada. - Inicia sesión en el nuevo usuario con la librería
Auth
- Si el indicador
$new_user
estaba desmarcado, creamos una matriz$credentials
y la usamos con la libreríaAuth
. - Si
Auth::attempt
es verdadero, significa que las credenciales eran correctas y hemos iniciado sesión - De lo contrario, significa que las credenciales estaban equivocadas.
- En ambos escenarios, redirigimos al controlador
Dashboard
, a la acciónindex
cuando se realice correctamente. Y mostraremos un mensaje de error en caso contrario.
La librería Input
La función básica de la librería Input
es habilitar la obtención de los datos del formulario. Por ejemplo, en el controlador del usuario, usamos Input::get('email');
para obtener el valor del correo electrónico del formulario. Es importante tener en cuenta que el método get
se utiliza para todos los tipos de solicitudes y no solo para la matriz $_GET.
Puedes leer más sobre la librería Input aquí: http://laravel.com/docs/input#input
La librería Auth
Laravel viene con su propio mecanismo de autenticación, la biblioteca Auth
. Puede hacer las siguientes características con respecto a la autenticación de usuario.
Crea una contraseña encriptada
Podemos hacer uso de la librería Hash
de la siguiente manera:
1 |
$password = Hash::make($plaintext_password); |
Este método crea una contraseña encriptada y segura para un usuario, utilizando la clave de cifrado que establecemos en el archivo de configuración. Para comprobar si un hash es correcto, puedes utilizar:
1 |
if( Hash::check($plaintext_password, $hashed_password) == true ) { |
2 |
echo 'Password is correct.'; |
3 |
}
|
Iniciar sesión en un usuario
Para ello, usamos el método attempt
de la librería Auth
. Antes de eso, sin embargo, construimos una matriz $credentials
, que es una matriz asociativa con los índices username
y password
:
1 |
$credentials = array( |
2 |
'username' => 'yourname@youremail.com', |
3 |
'password' => 'yourpassword' |
4 |
);
|
5 |
if( Auth::attempt($credentials) == true ) { |
6 |
echo 'User is logged in'; |
7 |
} else { |
8 |
echo 'Credentials failed'; |
9 |
}
|
Es importante tener en cuenta que una vez que un intento es "exitoso", el usuario inicia sesión automáticamente.
Hacer que un usuario inicie/cierre sesión
A veces, tendremos que iniciar sesión en un usuario sin usar el método attempt
(por ejemplo, al iniciar sesión en un usuario desde un enlace dentro de un correo electrónico o después del registro). Podemos hacerlo con el método Auth::login
:
1 |
Auth::login($user); //where $user is a User object |
2 |
Auth::login(42); //where 42 is the User's ID |
Por otro lado, también tenemos un método Auth::logout
para cerrar la sesión de los usuarios:
1 |
Auth::logout(); |
Esto terminará la sesión del usuario.
Recuperar los datos del usuario que ha iniciado sesión
El método Auth::user
nos permite recuperar el objeto de usuario que ha iniciado sesión, así como cualquier información adjunta a él:
1 |
$email = Auth::user()->email; |
2 |
$created_at = Auth::user()->created_at; |
Configuración de la librería Auth
La librería Auth
debe configurarse antes de usarla (aunque los valores predeterminados funcionarán con la mayoría de los proyectos, como este). Las variables de configuración son:
- driver - esto puede ser Eloquent o Fluent. Los desarrolladores pueden escribir sus propios controladores extendiendo la clase
Driver
en laravel/auth/drivers. - username: este es el nombre de la columna de lo que representa el "nombre de usuario" de tu usuario en la tabla de la base de datos.
- model - cuando se utiliza Eloquent, esta es la clase de modelo que utiliza la librería
Auth
- table - cuando se utiliza el controlador de autenticación Fluent, se determina la tabla de base de datos para los usuarios de la aplicación
Nuestro proyecto, Instapics, utiliza los valores predeterminados en el archivo de configuración auth.php, por lo que no necesitamos cambiar nada en él.
Volviendo al proyecto, ¡prueba las características de inicio de sesión/registro de Instapics! Bastante ingenioso, ¿no? Sin embargo, notarás que aún no tenemos nada en el controlador Dashboard
, así que vamos a trabajar en él a continuación.
Paso 5 - Crear el panel de Instapics
Lo primero que tenemos que hacer es crear el controlador Dashboard
, con la acción index
. Crea el archivo application/controllers/dashboard.php y coloca el siguiente código:
1 |
class Dashboard_Controller extends Base_Controller |
2 |
{
|
3 |
public function action_index() |
4 |
{
|
5 |
$photos = Auth::user()->photos()->order_by('created_at', 'desc')->order_by('id', 'desc')->get(); |
6 |
return View::make('dashboard.index', array('photos' => $photos)); |
7 |
}
|
8 |
}
|
Ahora necesitamos crear la página index.blade.php del panel. Crea application/views/dashboard/index.blade.php y añade lo siguiente:
1 |
@layout('layouts/main') |
2 |
|
3 |
@section('navigation') |
4 |
@parent |
5 |
<li><a href="user/logout">Logout</a></li> |
6 |
@endsection |
7 |
|
8 |
@section('content') |
9 |
<div class="row"> |
10 |
<div class="span3"> |
11 |
<div class="well sidebar-nav"> |
12 |
<ul class="nav nav-list"> |
13 |
<li class="nav-header">Followers</li> |
14 |
</ul>
|
15 |
<div style="margin-left: 10px"> |
16 |
@forelse (Auth::user()->followers as $follower) |
17 |
<div style="float: left; width: 30px; margin: 0px 3px 3px 5px;"> |
18 |
<img src="http://nettuts.s3.amazonaws.com/2069_laravel_2/http://gravatar.com/avatar/{{ md5(strtolower(trim($follower->email))) }}?s=25&d=retro" alt="Follower" title="{{ $follower->email }}" /> |
19 |
</div>
|
20 |
@empty |
21 |
<div>You have no followers.</div> |
22 |
@endforelse |
23 |
<div style="clear: both"></div> |
24 |
</div>
|
25 |
|
26 |
<ul class="nav nav-list"> |
27 |
<li class="nav-header">Following</li> |
28 |
</ul>
|
29 |
<div style="margin-left: 10px"> |
30 |
@forelse (Auth::user()->following as $following) |
31 |
<div style="float: left; width: 30px; margin: 0px 3px 3px 5px;"> |
32 |
<img src="http://nettuts.s3.amazonaws.com/2069_laravel_2/http://gravatar.com/avatar/{{ md5(strtolower(trim($following->email))) }}?s=25&d=retro" alt="Following" title="{{ $following->email }}" /> |
33 |
</div>
|
34 |
@empty |
35 |
<div>You are not following anybody.</div> |
36 |
@endforelse |
37 |
<div style="clear: both"></div> |
38 |
</div>
|
39 |
</div>
|
40 |
</div>
|
41 |
<div class="span9"> |
42 |
<h1>Your Photos</h1> |
43 |
@forelse ($photos as $photo) |
44 |
<div class="well" style="text-align: center"> |
45 |
<img src="http://nettuts.s3.amazonaws.com/2069_laravel_2/{{ $photo->location }}" alt="{{ $photo->description }}" title="{{ $photo->description }}" /> |
46 |
<p>{{ $photo->description }}</p> |
47 |
</div>
|
48 |
@empty |
49 |
<div class="alert alert-info"> |
50 |
<h4 class="alert-heading">Awww!</h4> |
51 |
<p>Seems like you don't have any photos yet. <a href="#">Upload a new one?</a></p> |
52 |
</div>
|
53 |
@endforelse |
54 |
</div>
|
55 |
</div>
|
56 |
@endsection |
Actualiza la página del panel, deberías ver esto:



¿Luce un poco vacío? Agrega esto al controlador Dashboard
y ejecútalo accediendo a dashboard/insert_test_data
en tu navegador:
1 |
public function action_insert_test_data() |
2 |
{
|
3 |
$logged_in_user = Auth::user(); |
4 |
|
5 |
for( $x = 0; $x < 10; $x++ ) { |
6 |
$email = rand().'@gmail.com'; |
7 |
$user = new User(); |
8 |
$user->email = $email; |
9 |
$user->password = Hash::make($email); |
10 |
$user->save(); |
11 |
|
12 |
$logged_in_user->followers()->attach($user->id); |
13 |
if( $x > 5 ) { |
14 |
$logged_in_user->following()->attach($user->id); |
15 |
}
|
16 |
}
|
17 |
|
18 |
$photos = array( |
19 |
array( |
20 |
'user_id' => $logged_in_user->id, |
21 |
'location' => 'http://farm6.staticflickr.com/5044/5319042359_68fb1f91b4.jpg', |
22 |
'description' => 'Dusty Memories, The Girl in the Black Beret (http://www.flickr.com/photos/cloudy-day/)' |
23 |
),
|
24 |
array( |
25 |
'user_id' => $logged_in_user->id, |
26 |
'location' => 'http://farm3.staticflickr.com/2354/2180198946_a7889e3d5c.jpg', |
27 |
'description' => 'Rascals, Tannenberg (http://www.flickr.com/photos/tannenberg/)' |
28 |
),
|
29 |
array( |
30 |
'user_id' => $logged_in_user->id, |
31 |
'location' => 'http://farm7.staticflickr.com/6139/5922361568_85628771cd.jpg', |
32 |
'description' => 'Sunset, Funset, Nikko Bautista (http://www.flickr.com/photos/nikkobautista/)' |
33 |
)
|
34 |
);
|
35 |
$logged_in_user->photos()->save($photos); |
36 |
}
|
Cuando actualices la página, verás cómo se ve con los datos de ejemplo insertados:



Conclusión
En la segunda parte de nuestra serie Laravel, aprendimos:
- Algunos antecedentes sobre lo que son los "Modelos"
- Qué es el Eloquent ORM
- Cómo configurar la base de datos de Laravel
- Cómo crear tu primer Modelo en Laravel
- Las funciones básicas de las librerías Auth y Input
- Hacer uso de Eloquent ORM en una vista
Eloquent realmente es una implementación ORM impresionante - es rápido y tiene un montón de características que hacen que las interacciones con la base de datos en cualquier aplicación sean tan simple como sea posible.
A continuación, en nuestra serie Aplicaciones web desde cero con Laravel, aprenderemos más sobre el uso de los filtros de Laravel, la librería Validation de Laravel, ¡y cómo trabajar con archivos en Laravel!
¿Qué opinas de Eloquent ORM de Laravel? ¿Es algo que te parece útil? ¡Avísame en los comentarios! Y, si eres miembro de Tuts+ Premium, ¡mantente atento a nuestro próximo curso de Laravel Essentials!