Primeros pasos con Laravel Nova
Sin duda hoy se marca un hito en la historia de Laravel. La nueva adición, Nova, irrumpe como una gran adición al ecosistema de Laravel.
He leído muchas publicaciones hoy, pero debo destacar la de Nick Basile en quién me baso para traducir y escribir este proyecto que nos permitirá ponernos en marcha con esta fantástica novedad… Laravel Nova (https://nova.laravel.com).
Laravel Nova es un hermoso panel de administración para aplicaciones hechas en Laravel. Por supuesto, la característica principal de Nova es su capacidad de administrar registros de la base de datos subyacentes utilizando Eloquent. Nova logra esto al permitir definir Nova como un “recurso” correspondiente a cada modelo Eloquent de tu aplicación.
He podido adquirir mi licencia hoy y me he ido dando cuenta de lo potente e intuitivo que Nova se ajusta a tus aplicaciones y flujo de trabajo de Laravel.
Como ejemplo, desarrollaremos un sistema muy simple de Blog para que veas como se configura y funciona Nova.
Pasos Iniciales
Para adquirir Nova, debes ingresar a su web y registrarte. Luego podrás comprar la licencia que más te acomode y posteriormente tendrás acceso al código de Nova.
Para mi caso, adquirí una licencia de desarrollador ‘solo developer’ por $99.00. También está la opción pro ‘Businesses & Teams’ por un precio de $199.00 .
Una vez registrado y adquirida tu licencia, podrás descargar un archivo comprimido con la versión que selecciones (al día de hoy existían 6, desde la v0.1.0 a la v1.0.3).
Instalación
Para comenzar, hay que realizar una instalación (como normalmente se realiza) de Laravel
laravel new blog-nova
Algo que me complicó en un principio fue entender dónde debía descomprimir todos los archivos de Nova. Luego de varios intentos, entendí que hay que descomprimirlos en la raíz de tu nuevo proyecto (en este caso dentro de la carpeta blog-nova que corresponde al proyecto que acabamos de crear).
La carpeta que crea hay que renombrarla a “nova” o al nombre que desees pero debes tener la precaución de escribirlo así en el nombre del repositorio (más adelante el código).
Esto se realiza producto que hay que asegurarse que los archivos ocultos de Nova se incluyan en el .gitignore
Configuración composer.json
Con el código en su lugar, hay que configurar el archivo composer.json
para que se reconozca Nova agregando el siguiente código:
"repositories": [
{
"type": "path",
"url": "./nova"
}
],
Luego hay que adicionar la siguiente sección:
"require": {
"php": "^7.1.3",
"fideloper/proxy": "^4.0",
"laravel/framework": "5.6.*",
"laravel/nova": "*"
},
Antes de continuar con los comandos de instalación hay que asegurarse de configurar correctamente los valores de entorno (.env) correspondiente a tu Base de Datos.
Una vez configurado tu archivo composer.json
y tu variables de entorno de tu base de datos, debes escribir el siguiente comando en tu terminal:
composer update
Finalmente, correr e comando nova:install
y migrate
la base de datos. El comando nova:install
instalará el service provider y assets public de Nova dentro de tu aplicación.
php artisan nova:install
php artisan migrate
Si llegaste hasta acá… y no hay errores, ya tienes instalado Nova. Felicitaciones!
Puedes ingresar a tu proyecto (en mi caso utilizo valet, por lo que la dirección será: blog-nova.dev/nova). Verás esta pantalla de inicio.
Agregar el primer usuario
Para poder ingresar, debes crear el primer usuario en tu proyecto. Para ello, Nova incluye un comando ‘out-of-the-box’ que permite hacerlo.
Escribe el siguiente comando:
php artisan nova:user
Completa los valores que solicita y tendrás tu primer usuario!
Ingresa con tus datos y podrás ver por primera vez Nova por dentro… :)
Construir tu Blog
Comencemos con los pasos, como para cualquier proyecto de Laravel. Para ello hay que crear un modelo, migración y controlador para Post. Laravel nos provee de una bandera muy útil -a
.
Escribe en tu terminal:
php artisan make:model Post -a
Este comando creará todo lo necesario para tu blog. Ahora hay que crear las columnas que tendrá la tabla posts en la base de datos, por lo que debes editar el último archivo que se haya generado en tu carpeta database/migrations/xxxx_xx_xxxx_create_posts_table.php
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->text('title');
$table->text('subtitle');
$table->text('body');
$table->dateTime('published_on');
$table->timestamps();
});
}
Ahora es momento de correr la migración para agregar esta tabla a la base de datos.
php artisan migrate
Después de ello, entra a tu modelo app/Post.php
y configura las relaciones con el modelo User.
Escribe:
class Post extends Model
{
protected $dates = [
'published_on',
]; public function user()
{
return $this->belongsTo('App\User');
}
}
Ahora hay que definir la relación inversa con el modelo User:
class User extends Authenticatable
{
use Notifiable; /**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
]; /**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
]; public function posts()
{
return $this->hasMany('App\Post');
}
}
Una vez configurados ambos modelos y relaciones, es momento de configurar nuestro proyecto Nova.
Nova
En Nova, el concepto que hay que entender es el de “recursos”. Cada modelo que tu desees manejar en Nova, debe tener su correspondiente recurso.
En este caso deberemos generar nuestro recurso Post. Para ello hay que escribir:
php artisan nova:resource Post
Ahora, ingresa al directorio app/Nova
y podrás ver nuestro primer recurso Post. Acá es donde debes configurar todo lo relacionado al manejo e interactividad que Nova permite para interacciones con modelo Post.
Lo primero es configurar el método fields()
en el recurso del Post. Acá hay que indicarle a Nova cómo debe interpretar y definir las columnas de nuestra tabla para nuestro modelo Post.
Nova tiene muchos campos para que poder utilizar. Te recomiendo que mires todas las opciones disponibles en Nova que puedan ajustarse de mejor manera a cada proyecto.
Por ahora, utilizaremos una configuración básica para nuestro Post (debes importar cada uno, BelongsTo, Text, Makdown y DateTime):
namespace App\Nova;use Laravel\Nova\Fields\ID;
use Illuminate\Http\Request;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\DateTime;
use Laravel\Nova\Fields\Markdown;
use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Http\Requests\NovaRequest;public function fields(Request $request)
{
return [
ID::make()->sortable(),
BelongsTo::make('User')->rules('required'),
Text::make('Title')->rules('required')->sortable(),
Text::make('Subtitle')->rules('required')->hideFromIndex(),
Markdown::make('Body')->rules('required'),
DateTime::make('Published On')->rules('required'),
];
}
Es importante entender un poco más en profundidad qué hace cada definición. Para ello miremos el subtitle.
Text::make('Subtitle')->rules('required')->hideFromIndex(),
La parte de Text::
nos indica el tipo de campo que estamos generando (de texto en este caso). Luego, la etiqueta que pasamos al método estático make
('Subtitle')
que corresponde al nombre de la columna de nuestra base de datos pero de tipo ‘snake’.
Por último se agrega algo de “magia” al añadir una regla de validación, en este caso indicamos que ‘Subtitle’ debe ser un campo required rules('required’)
.
Finalmente añadimos el método hideFromIndex()
. Esto previene que el campo sea mostrado en la página del listado. Algunos campos se manejan en forma ligeramente distinta como Markdown
. Sin embargo, en su mayor parte, si no especificas la opción de visualización, aparecerá en todas partes.
Al volver a tu sitio de Nova, podrás ver un nuevo elemento “Post” en tu sidebar.
Al hacer clic en Posts, iremos directamente a la página de nuestro Post.
Para realizar nuestra primera publicación, hacemos clic en el botón ‘create post’. Esto muestra el formulario para crear nuestra publicación.
Si intentas enviar el formulario, podremos ver la validación funcionando como debiera.
Una vez que hayamos completado todos los campos, veremos la publicación y toda su información.
Finalmente, podemos regresar a la página y ver nuestra publicación recién creada.
Con esto ya hemos creado lo necesario para nuestro blog. Ahora, mientras esto se ocupa del lado administrativo, necesitamos que nuestros mensajes sean visibles para nuestros usuarios a través de la vista general.
Terminando lo necesario en tu proyecto Laravel
Para finalizar el blog debemos ingresar a nuestro archivo app/Http/Controllers/PostController.php
y configurar nuestras vistas. En este caso solo utilizaremos los recursos index()
y show()
por lo que puedes borrar los demás métodos que creamos anteriormente (create(), store(), edit(), update(), destroy()).
Escribe lo siguiente:
class PostController extends Controller
{
public function index()
{
$posts = Post::orderByDesc('published_on')->get(); return view('posts.index', compact('posts'));
} public function show(Post $post)
{
return view('posts.show', compact('post'));
}
}
Por último, hay que especificar las rutas a nuestro archivo routes/web.php
:
Route::get('/', 'PostController@index');
Route::get('/posts/{post}', 'PostController@show');
Para la visualización adecuada del blog, instalaré Tailwindcss… lejos la mejor alternativa existente (gracias Adam Wathan!). Puedes utilizar el CDN con el CSS o seguir los 4 pasos y listo ;)
CDN tailwind.min.css:
<link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet">
Por último, creamos una carpeta dentro de resources/views/
con el nombre de /posts/
y crear ahí dos vistas index.blade.php
y show.blade.php
. El primer archivo, index.blade.php
debe contener el siguiente código:
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Blog - Nova</title>
<!-- Styles -->
<link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
<div class="flex mt-5">
<div class="w-1/5"></div>
<div class="w-3/5">
@foreach($posts as $post)
<div class="border-r border-b border-l border-t border-grey-light bg-white rounded-b p-4 flex flex-col leading-normal mb-5">
<div class="mb-4">
<div class="text-black font-bold text-xl mb-2">
<a href="/posts/{{$post->id}}" class="text-blue no-underline hover:bg-blue-lightest py-2">
{{$post->title}}
<svg class="h-4 w-4 fill-current text-red inline-block" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.78 7.77L10 18.78l8.39-8.4a5.5 5.5 0 0 0-7.78-7.77l-.61.61z"></path></svg>
</a>
</div>
<p class="text-grey-darker text-base">{{$post->body}}</p>
</div>
<div class="flex items-center">
<div class="text-xs">
<p class="text-grey-dark">{{$post->published_on}}</p>
</div>
</div>
</div>
@endforeach
</div>
<div class="w-1/5"></div>
</div>
</body>
</html>
Por último, el archivo ‘show.blade.php’ debe contener lo siguiente:
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Blog - Nova</title>
<!-- Styles -->
<link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
<div class="flex mt-5">
<div class="w-1/5"></div>
<div class="w-3/5">
<div class="rounded overflow-hidden shadow-lg">
<div class="px-6 py-4">
<div class="font-bold text-xl mb-2">{{$post->title}}</div>
<p class="text-grey-darker text-base">
{{$post->body}}
</p>
</div>
<div class="px-6 py-4">
<span class="py-1 text-sm text-grey mr-2">Written with
<svg class="h-3 w-3 fill-current text-red inline-block" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.78 7.77L10 18.78l8.39-8.4a5.5 5.5 0 0 0-7.78-7.77l-.61.61z"></path>
</svg> by {{$post->user->name}}
</span>
<p class="py-1 text-sm text-grey-light mr-2">on {{$post->published_on}}</p>
</div>
</div>
</div>
<div class="w-1/5"></div>
</div>
</body>
</html>
Ingresa en tu proyecto y podrás ver que ya tiene forma de blog. Bien hecho!
Si te ha gustado, ayudado o te parece útil, te agradecería mucho un “clap” y tu ayuda compartiendo esta publicación en twitter
Puedes seguirme en twitter también: