Aplicación CRUD en Laravel
Creación de una aplicación ToDo en Laravel
1. Creación del VPS
Servidor VPS en DigitalOcean.com: LEMP
Getting started after deploying LEMP
In addition to the package installation, the 1-Click also:
- Enables the UFW firewall to allow only SSH (port
22
, rate limited), HTTP (port80
), and HTTPS (port443
) access. - Sets the MySQL root password and runs
mysql_secure_installation
. - Sets up the
debian-sys-maint
user in MySQL so the system’s init scripts for MySQL will work without requiring the MySQLroot
user password.
After you create a LEMP 1-Click Droplet:
- You can view the LEMP instance immediately by visiting the Droplet’s IP address in your browser.
- You can log into the Droplet as
root
using either the password you set when you created the Droplet or with an SSH key, if you added one during creation. - The MySQL root password is in
/root/.digitalocean_password
. - The web root is
/var/www/html
. - You can get information about the PHP installation by logging into the Droplet and running
php -i
.
2. Configuración del servidor
Conexión al droplet por ssh
ssh root@alumnoportada.com.es adduser usuario usermod -aG sudo usuario apt install mc
Actualizar PHP a la versión 8:
apt install software-properties-common add-apt-repository ppa:ondrej/php apt update apt install php8.0-fpm php -v systemctl status php8.0-fpm apt install php8.0-mysql php8.0-mbstring php8.0-xml php8.0-bcmath
Cómo instalar Node.js en Ubuntu 20.04
# Using Ubuntu curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt-get install -y nodejs node -v npm -v
Server Requirements
El servidor VPS debe tener instalada la versión mínima de PHP y estas extensiones:
- PHP >= 8.0
- BCMath PHP Extension
- Ctype PHP Extension
- cURL PHP Extension
- DOM PHP Extension
- Fileinfo PHP Extension
- JSON PHP Extension
- Mbstring PHP Extension
- OpenSSL PHP Extension
- PCRE PHP Extension
- PDO PHP Extension
- Tokenizer PHP Extension
- XML PHP Extension
How to install all required PHP extensions for Laravel 8?
sudo apt install openssl php-common php-curl php-json php-mbstring php-mysql php-xml php-zip
Installation of PHP Extensions for Laravel 9
sudo apt install php8.0-common php8.0-mysql php8.0-xml php8.0-xmlrpc php8.0-curl php8.0-gd php8.0-imagick php8.0-cli php8.0-dev php8.0-imap php8.0-mbstring php8.0-opcache php8.0-soap php8.0-zip php8.0-intl -y
Conexión al droplet con un usuario diferente a root:
ssh usuario@alumnoportada.com.es
3. Instalación de Composer y node.js
Composer 2: How to Install in Ubuntu 20.04 LTS
curl -sS https://getcomposer.org/installer -o composer-setup.php sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer composer -V
Cómo instalar Node.js en Ubuntu 20.04
# Using Ubuntu curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt-get install -y nodejs node -v npm -v
4. Instalación de Laravel
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Usando el instalador de Laravel
composer global require laravel/installer laravel new todo
O usando composer
composer create-project laravel/laravel todo cd todo
Error en el droplet con 1 Gb de RAM (son necesarios 2 Gb de RAM, como mínimo):Redimensionar el droplet con 2 Gb de memoria RAM (cuando se termine la instalación se puede volver a redimensionar a 1 Gb):
5. Base de datos
Crear la base de datos todoDB, el usuario todoUser y la password malaga20*
mysql -u root -p CREATE DATABASE todoDB; CREATE USER 'todoUser'@'localhost' IDENTIFIED BY 'malaga20*'; GRANT ALL PRIVILEGES ON todoDB.* TO 'todoUser'@'localhost'; FLUSH PRIVILEGES; exit
Modificar el fichero .env:
nano .env
Información de conexión a la base de datos:
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=todoDB DB_USERNAME=todoUser DB_PASSWORD=malaga20*
Montar en el equipo local el sistema de ficheros remoto
Nota: Estos comandos se ejecutan en el equipo local, no en el droplet
mkdir servidor sshfs usuario@alumno.xyz:/home/usuario/todo/ servidor -p 22
Para desmontarlo:
fusermount -u servidor
6. MVC en Laravel
Using HTTP Methods for RESTful Services
7. Creación de la aplicación Todo
CRUD To-do Application in Laravel
Aviso: ejecutar 2 veces el comando
npm install && npm run dev
Resultado final:
Laravel Mix v6.0.43 ✔ Compiled Successfully in 3666ms ┌───────────────────────────────────────────────────────────────────┬──────────┐ │ File │ Size │ ├───────────────────────────────────────────────────────────────────┼──────────┤ │ /js/app.js │ 694 KiB │ │ css/app.css │ 48.4 KiB
Rutas:
php artisan route:list
Create Layout Using Laravel Blade Templating Engine
8. Permisos en la carpeta storage
Poner permiso de escritura para www-data en carpeta storage o cambiar el propietario/grupo de la carpeta:
cd todo sudo chown -R www-data:www-data storage
How to set up file permissions for Laravel?
9. Modificación de la página principal
fichero public/css/styles.css (obtenido de welcome.blade.php)
nano public/css/styles.css
Contenido del fichero:
html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f7fafc;background-color:rgba(247,250,252,var(--bg-opacity))}.border-gray-200{--border-opacity:1;border-color:#edf2f7;border-color:rgba(237,242,247,var(--border-opacity))}.border-t{border-top-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.text-center{text-align:center}.text-gray-200{--text-opacity:1;color:#edf2f7;color:rgba(237,242,247,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#e2e8f0;color:rgba(226,232,240,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#a0aec0;color:rgba(160,174,192,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#4a5568;color:rgba(74,85,104,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#1a202c;color:rgba(26,32,44,var(--text-opacity))}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--bg-opacity:1;background-color:#2d3748;background-color:rgba(45,55,72,var(--bg-opacity))}.dark\:bg-gray-900{--bg-opacity:1;background-color:#1a202c;background-color:rgba(26,32,44,var(--bg-opacity))}.dark\:border-gray-700{--border-opacity:1;border-color:#4a5568;border-color:rgba(74,85,104,var(--border-opacity))}.dark\:text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.dark\:text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}}
Añadir Bootstrap
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
fichero resources/views/welcome.blade.php
<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Laravel</title> <!-- Fonts --> <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet"> <!-- Bootstrap --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> <!-- Styles --> <!-- normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css --> <link rel="stylesheet" href="css/styles.css"> <!-- <link rel="stylesheet" href="https://raw.githubusercontent.com/necolas/normalize.css/master/normalize.css"> --> <style> body { font-family: 'Nunito', sans-serif; } </style> </head> <body class="antialiased"> <div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center py-4 sm:pt-0"> @if (Route::has('login')) <div class="hidden fixed top-0 right-0 px-6 py-4 sm:block"> @auth <a href="{{ url('/dashboard') }}" class="text-sm text-gray-700 underline">Dashboard</a> @else <a href="{{ route('login') }}" class="text-sm text-gray-700 underline">Log in</a> @if (Route::has('register')) <a href="{{ route('register') }}" class="ml-4 text-sm text-gray-700 underline">Register</a> @endif @endauth </div> @endif <div class="max-w-4xl mx-auto sm:px-6 lg:px-4"> <div class="flex justify-center text-primary"> <h1>Todo Tasks</h1> </div> <div class="flex justify-center text-success"> <h3>Manage your tasks online</h3> </div> <div class="flex justify-center text-secondary"> <h4>info@alumnoportada.com.es</h4> </div> <div class="flex justify-center"> <div class="ml-4 text-center text-sm text-gray-500"> Laravel v{{ Illuminate\Foundation\Application::VERSION }} (PHP v{{ PHP_VERSION }}) </div> </div> </div> </div> </body> </html>
10. Limpiar la caché de Laravel
sudo php artisan cache:clear sudo php artisan config:clear sudo php artisan route:clear sudo php artisan view:clear
11. Comprobar el funcionamiento
12. Validación de datos
Validation Tutorial : Laravel To-Do Part 2
13. Instalación de Telescope y Toolbar
Introducción a Laravel Telescope
sudo chmod 777 storage/logs/laravel.log
#carpeta del proyecto de Laravel composer require laravel/telescope --dev php artisan telescope:install php artisan migrate
Fichero de configuración: config/telescope.php
nano config/telescope.php
Acceso:
todo.alumnoportada.com.es/telescope
composer require fruitcake/laravel-telescope-toolbar --dev php artisan vendor:publish --provider="Fruitcake\\TelescopeToolbar\\ToolbarServiceProvider"
La barra se mostrará por defecto en la pate inferior del navegador cuando Telescope esté habilitado y AP_DEBUG sea True.
Otra herramienta de depuración:
Repositorio de Debugbar en GitHub
__________________________________________
Ejemplo de plantillas con Blade en Laravel 9:
Laravel 9 Bootstrap Auth Scaffolding Tutorial
Laravel 9 CRUD Application Tutorial Example
CSRF Protection in Laravel
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.