Laravel y Tempus Dominus, un plugin javascript para escoger fecha y hora

Para escoger fechas en una página web no hace falta plugins, con código HTML es suficiente. Solo hay que poner un type=date:

    <div class="col-md-4">
        <label for="fecha" class="form-label">{{ __("Fecha") }}</label>
        <input type="date" id="fecha" name="fecha" class="form-control" aria-label="{{__("Fecha")}}" value="{{ old('fecha', $fecha) }}">
    </div>

Sin embargo, cuando es necesario tambien escoger una hora nos vemos obligados a usar un plugin como «Tempus Dominus» que nos deja escoger fecha y hora.

Para usarlo en Laravel vamos a enlazarlo en la cabecera de la página, junto con su traducción (locales), los estilos (css) y la libreria popper que es necesaria.

    <script src="{{ asset('popper.min.js')}}"></script>
    <script src="{{ asset('tempus-dominus-master/dist/js/tempus-dominus.min.js')}}"></script>
    <script src="{{ asset('tempus-dominus-master/dist/locales/es.js')}}"></script>
    <link href="{{ asset('tempus-dominus-master/dist/css/tempus-dominus.min.css') }}" rel="stylesheet"/>

Aquí voy a hacer una pequeña aclaración, para poder usar las traducciones he tenido que editar el archivo y dejar solo la constante «localization», por ejemplo en el caso del español, catalán, inglés y francés lo tenéis aquí ya modificado

Una vez enlazado en la cabecera lo presentaremos así en el HTML

    <div class="col-md-4">
        <label for="fecha" class="form-label">{{ __("Fecha") }}</label>
        <div class="input-group log-event" id="fechaDiv" data-td-target-input="nearest" data-td-target-toggle="nearest">
            <input id="fecha" type="text" class="form-control" data-td-target="#fechaDiv">
            <span class="input-group-text" data-td-target="#fechaDiv" data-td-toggle="datetimepicker">
                <i class="fas fa-calendar"></i>
            </span>
        </div>
    </div>

Y lo inicializaremos en javascript así

const datetimepicker1 = new tempusDominus.TempusDominus(document.getElementById('fechaDiv'),{
    localization: localization //nuestra constante en el archivo modificado de la cabecera
    ...
});

datetimepicker1.dates.setValue(tempusDominus.DateTime.convert(new Date()));

En el caso que debamos inicializar el plugin con una fecha que venga del PHP en lugar del javascript, cambiaremos la última línea con una variable de PHP que contenga un objeto Carbon, en los modelos es automático, por ejemplo, cambiaríamos la última línea por:

datetimepicker1.dates.setValue(tempusDominus.DateTime.convert( new Date('{{ $row->fecha->format("Y-m-d H:i:s") }}') ));

dónde «$row» es un registro de de la base de datos.

Recordar que hay que señalizarlo en el modelo:

protected $dates = ['fecha'];

Si no trabajamos con un modelo podemos obtener un objeto carbon directamente

use Carbon\Carbon;
...
class EjemploController extends Controller {

    public function index(Request $reques) {
        ...
        $fecha = Carbon::now();

Y hasta aquí llegamos

Actualizar la versión de PHP (de php 7.4 a php 8.2) en Ubuntu (Mint, etc)

Vamos a hablar de cambiar la versión de PHP, específicamente para actualizar la versión de php 7.4 a la 8.2, pero servirá casi totalmente para cambiar a cualquier versión. Ya sea para bajarla o subirla.

1. Lo primero es instalar la versión de PHP que quieres con las extensiones que necesites, en mi caso:

sudo apt install php8.2 php8.2-gd php8.2-intl php8.2-mcrypt php8.2-zip php8.2-mysql php8.2-mbstring php8.2-xml php8.2-curl 

2. Podríamos desinstalar la versión anterior de php, pero en mi caso la voy a dejar instalada por si necesito cambiar en algún otro momento. Por lo que no haré el paso siguiente:

sudo apt remove php7.4*

3. Lo que si vamos a hacer es deshabilitar el modulo de Apache anterior y habilitar el nuevo

sudo a2dismod php7.4 
sudo a2enmod php8.2 
sudo systemctl restart apache2

4. Y habilitar el php que queremos para la linea de comandos

sudo update-alternatives --config php

Como generar una clave nueva para nuestra app de Laravel (APP_KEY) a través de web sin usar la linea de comandos

Para generar una clave nueva para nuestra app de Laravel (APP_KEY) a través de web sin usar la linea de comandos podemos crear una ruta que llame a Artisan:
El comando para generar la clave es «key:generate» y para poner argumentos se pone en forma de array a continuación. Conseguimos la salida de Artisan con «Artisan::output()» a la que solo nos falta limpiar con rtrim.

Route::get('/generate-key', function() {
    Artisan::call('key:generate',['--show' => true]);
    $key = rtrim(Artisan::output());
    return $key;
});

Podemos hacer también que la escriba directamente, para esto debemos tener permisos de escritura en .env

Route::get('/write-key', function() {
    Artisan::call('key:generate');
});

Y si estamos en producción y queremos aún así generar y escribir la clave

Route::get('/force-write-key', function() {
    Artisan::call('key:generate',['--force' => true]);
});

Validación con Laravel, aclaración

Si quieres hacer una validación normal, por ejemplo de un formulario, que si falla vuelva a él, con los errores y los datos, usamos validator::make

Validator::make($request->all(), $rules)->validate();

Si queremos añadir una regla propia de validación, usamos esto mismo pero con after:

Validator::make($request->all(), $rules)->after(function ($validator) use ($request){
    if (session('captcha') != $request->input('captcha')) {
        $validator->errors()->add(
            'captcha', trans('Código incorrecto')
        );
    }
})->validate();

Y que pasa si cuando sucede un error y mostramos los errores, en vez de los nombres de los campos del formulario queremos poner otra cosa, como un nombre más descriptivo:

Validator::make($request->all(), $rules)->setAttributeNames(['idField' => trans('NOmbre más descripticvo del campo')])->validate();

Y si al mostrar los errores en vez de usar los mensajes por defecto queremos personalizar los mensajes de error:

$msg = [
    'required' => 'Es necesario que rellenes :attribute'
];
Validator::make($request->all(), $rules, $msg)->validate();

Si cuando falle, queremos hacer otra cosa, que no sea volver a la página anterior:

$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) { ... }

Reglas de validación aquí