Creando su propio paquete para Laravel Nova: OptimalImage

Mientras trabajaba en un nuevo proyecto que Laravel Nova usa para administrar , lo probé con las herramientas para webmasters de Google. Resultó que algunas de las fotos en el recurso no estaban optimizadas, su tamaño podría reducirse significativamente. Los que están en el proyecto pueden procesarse al construir el proyecto usando node.js. Hay muchos paquetes listos para esto. Todavía hay imágenes cargadas por el usuario directamente desde el panel de administración del sitio. Por supuesto, puede optimizar cada imagen antes de subirla al sitio, pero ¿por qué no hacer que este procedimiento sea automático? Entonces nació la idea de hacer un paquete para Laravel Nova: OptimalImage.


El paquete es bastante simple y, por lo tanto, no pretende ser una guía completa para crear paquetes para Laravel Nova. No aborda un tema bastante extenso sobre el trabajo con el componente visual de los componentes. Si aparece una idea interesante de un componente, con un componente visual, escribiré un artículo sobre este tema.


Formulación del problema


Desea crear un paquete que agregue un nuevo campo. Este campo diferirá del
campo habitual con la carga de imágenes en que la optimización se realizará para la imagen cargada.


Instalación y configuración del entorno.


Para repetir todos los pasos de esta guía, necesitará un proyecto con Laravel y Laravel Nova. Laravel Nova es una herramienta de pago, pero en mi opinión, su precio es bastante asequible.


Solía ​​en el trabajo:


  1. PHP 7.3.16
  2. Laravel 7
  3. Laravel Nova 3.0

.


. — :


cd /path/to/nova/project
php artisan nova:field yarbala/optimal-image

. nova-components OptimalImage.


nova-components .gitignore git init


cd /path/to/nova/project/nova-components/OptimalImage
git init
git add .
git commit -m "First commit"
git remote add origin git@github.com:yarbala/nova-optimal-image-field.git
git push -u origin master


spatie/laravel-image-optimizer, require composer.json


"spatie/laravel-image-optimizer": "^1.6"

Laravel


composer update

.


:


nova-components/OptimalImage/dist
nova-components/OptimalImage/resources

:


nova-components/OptimalImage/webpack.mix.js
nova-components/OptimalImage/package.json
nova-components/OptimalImage/mix-manifest.json 

OptimalImage :


namespace Yarbala\OptimalImage;

use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Laravel\Nova\Fields\Image;

/**
 *       Image.  ,    
 *   ,      .
 *
 * Class OptimalImage
 * @package Yarbala\OptimalImage
 */
class OptimalImage extends Image
{
    /**
     *        Image 'Fields/File.php'.     
     *    optimizeImage  .
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string  $requestAttribute
     * @return string
     */
    protected function storeFile($request, $requestAttribute)
    {
        if (! $this->storeAsCallback) {
            $fileName = $request->file($requestAttribute)->store($this->getStorageDir(), $this->getStorageDisk());
            if ($fileName) {
                try {
                    $this->optimizeImage($fileName);
                } catch (FileNotFoundException $e) {
                }
            }

            return $fileName;
        }

        $fileName = $request->file($requestAttribute)->storeAs(
            $this->getStorageDir(), call_user_func($this->storeAsCallback, $request), $this->getStorageDisk()
        );

        if ($fileName) {
            try {
                $this->optimizeImage($fileName);
            } catch (FileNotFoundException $e) {
                //
            }
        }

        return $fileName;
    }

    /**
     *    
     *
     * @param $fileName
     * @throws FileNotFoundException
     */
    protected function optimizeImage($fileName)
    {
        // ...
    }
}

Laravel\Nova\Fields\Image.


public $component = 'optimal-image';

storeFile Laravel\Nova\Fields\File, Laravel\Nova\Fields\Image. . , optimizeImage .


optimizeImage:


namespace Yarbala\OptimalImage;

use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Laravel\Nova\Fields\Image;
use Spatie\ImageOptimizer\OptimizerChain as ImageOptimizer;
use Storage;

/**
 *       Image.  ,    
 *   ,      .
 *
 * Class OptimalImage
 * @package Yarbala\OptimalImage
 */
class OptimalImage extends Image
{
    // ...

    /**
     *    
     *
     * @param $fileName
     * @throws FileNotFoundException
     */
    protected function optimizeImage($fileName)
    {
        $needsUploadBack = false;
        $localDisk = 'local';
        $disk = $this->getStorageDisk();

        /*         Storage,  Spatie\ImageOptimizer    
                    
        */
        if (!Storage::disk($localDisk)->exists($fileName)) {
            Storage::disk($localDisk)->put($fileName, Storage::disk($disk)->get($fileName));
            $needsUploadBack = true;
        }

        //       
        $path = Storage::disk($localDisk)->path($fileName);

        //  
        app(ImageOptimizer::class)->optimize($path);

        //    ,   
        if ($needsUploadBack) {
            Storage::disk($disk)->put($fileName, Storage::disk($localDisk)->get($fileName));
            Storage::disk($localDisk)->delete($fileName);
        }
    }
}

Storage, Spatie\ImageOptimizer . - local.


:


class OptimalImage extends Image
{
    // ....

    public function localDisk(string $disk)
    {
        return $this->withMeta(['localDisk' => $disk]);
    }

    protected function getLocalDisk()
    {
        return $this->meta['localDisk'] ?? 'local';
    }
}

OptimalImage :


<?php

namespace Yarbala\OptimalImage;

use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Laravel\Nova\Fields\Image;
use Spatie\ImageOptimizer\OptimizerChain as ImageOptimizer;
use Illuminate\Support\Facades\Storage;

/**
 *       Image.  ,    
 *   ,      .
 *
 * Class OptimalImage
 * @package Yarbala\OptimalImage
 */
class OptimalImage extends Image
{
    /**
     *        Image 'Fields/File.php'.     
     *      optimizeImage  .
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string  $requestAttribute
     * @return string
     */
    protected function storeFile($request, $requestAttribute)
    {
        if (! $this->storeAsCallback) {
            $fileName = $request->file($requestAttribute)->store($this->getStorageDir(), $this->getStorageDisk());
            if ($fileName) {
                try {
                    $this->optimizeImage($fileName);
                } catch (FileNotFoundException $e) {
                }
            }

            return $fileName;
        }

        $fileName = $request->file($requestAttribute)->storeAs(
            $this->getStorageDir(), call_user_func($this->storeAsCallback, $request), $this->getStorageDisk()
        );

        if ($fileName) {
            try {
                $this->optimizeImage($fileName);
            } catch (FileNotFoundException $e) {
                //
            }
        }

        return $fileName;
    }

    /**
     *    
     *
     * @param $fileName
     * @throws FileNotFoundException
     */
    protected function optimizeImage($fileName)
    {
        $needsUploadBack = false;
        $localDisk = $this->getLocalDisk();
        $disk = $this->getStorageDisk();

        /*         Storage,  Spatie\ImageOptimizer    
                    
        */
        if (!Storage::disk($localDisk)->exists($fileName)) {
            Storage::disk($localDisk)->put($fileName, Storage::disk($disk)->get($fileName));
            $needsUploadBack = true;
        }

        //       
        $path = Storage::disk($localDisk)->path($fileName);

        //  
        app(ImageOptimizer::class)->optimize($path);

        //    ,   
        if ($needsUploadBack) {
            Storage::disk($disk)->put($fileName, Storage::disk($localDisk)->get($fileName));
            Storage::disk($localDisk)->delete($fileName);
        }
    }

    /**
     *      
     *
     * @param string $disk
     * @return OptimalImage
     */
    public function localDisk(string $disk)
    {
        return $this->withMeta(['localDisk' => $disk]);
    }

    /**
     *   
     * 
     * @return string
     */
    protected function getLocalDisk()
    {
        return $this->meta['localDisk'] ?? 'local';
    }
}

. , config/image-optimizer.php :


php artisan vendor:publish --provider="Spatie\LaravelImageOptimizer\ImageOptimizerServiceProvider"

, .


, readme .


, - . . .


.


El código fuente del proyecto está disponible y se distribuye bajo la licencia MIT.


Paquete embalador


Paquete Novapackages


All Articles