Primeros pasos con Laravel Nova

Claudio Vallejo
9 min readAug 23, 2018

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.

define tus variables de entorno para 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!

Escribe tu propio nombre, email y password

Ingresa con tus datos y podrás ver por primera vez Nova por dentro… :)

Ya tienes Laravel Nova funcionando!

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>
Puedes utilizar el estilo que desees… tailwindcss es extremadamente potente.

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:

--

--

Claudio Vallejo

Wine, programmer, diver & photographer lover. Agronomist Engineer. CEO/Founder of Intelvid.la — Cofounder Tradesfere.com More: cvallejo.me