Maison  >  Article  >  développement back-end  >  À propos de l'analyse du plug-in de pipeline PHP League\Pipeline

À propos de l'analyse du plug-in de pipeline PHP League\Pipeline

不言
不言original
2018-07-10 14:30:582507parcourir

Cet article présente principalement l'analyse du plug-in de pipeline PHP LeaguePipeline. Il a une certaine valeur de référence. Maintenant, je le partage avec tout le monde. Les amis dans le besoin peuvent s'y référer

Modèle de conception de pipeline

.

Si la conduite d'eau est trop longue, elle fuira si une partie est cassée, et elle n'est pas propice à la flexion et à la rotation dans des environnements complexes. Par conséquent, nous diviserons les conduites d'eau en tuyaux très courts, puis maximiserons la taille des tuyaux pour avoir différentes fonctions, nous adapterons aux conditions locales et les assemblerons pour répondre à une variété de besoins différents.

Cela conduit au modèle de conception de Pipeline, qui consiste à découper des processus complexes et longs en petits processus et tâches. Chaque tâche minimalement quantifiée peut être réutilisée pour former des processus complexes et diversifiés en assemblant différentes petites tâches.

Enfin, introduisez "l'entrée" dans le pipeline, exploitez (traitez, filtrez) l'entrée en fonction de chaque petite tâche, et enfin sortez les résultats qui répondent aux besoins.

Aujourd'hui, j'apprendrai principalement "Pipeline". D'ailleurs, je vous conseille un plug-in PHP : league/pipeline.

gulp

La première fois que j'ai découvert le concept de "pipe", c'est grâce à l'utilisation de gulp.

À propos de lanalyse du plug-in de pipeline PHP League\Pipeline

gulp est un exécuteur de tâches automatique basé sur NodeJS Il peut automatiquement terminer les tests de Javascript, sass, less et d'autres fichiers. Vérifiez, fusionnez, compressez, formatez, actualisez automatiquement le navigateur, générez des fichiers de déploiement et surveillez les fichiers pour répéter les étapes spécifiées après les modifications. En termes de mise en œuvre, elle s'inspire de l'idée de pipe du système d'exploitation Unix La sortie du niveau précédent devient directement l'entrée du niveau suivant, ce qui rend l'opération très simple.

var gulp = require('gulp');
var less = require('gulp-less');
var minifyCSS = require('gulp-csso');
var concat = require('gulp-concat');
var sourcemaps = require('gulp-sourcemaps');

gulp.task('css', function(){
  return gulp.src('client/templates/*.less')
    .pipe(less())
    .pipe(minifyCSS())
    .pipe(gulp.dest('build/css'))
});

gulp.task('js', function(){
  return gulp.src('client/javascript/*.js')
    .pipe(sourcemaps.init())
    .pipe(concat('app.min.js'))
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('build/js'))
});

gulp.task('default', [ 'html', 'css', 'js' ]);

Les deux task ci-dessus sont principalement utilisés pour analyser, compresser, sortir et autres opérations de processus pour less et tous les js fichiers, puis les enregistrer dans le dossier correspondant à chaque étape ; de l'opération La sortie est l'entrée pour l'opération suivante, tout comme le débit de l'eau dans un tuyau.

IlluminatePipeline

Le middleware du framework Laravel est implémenté à l'aide de IlluminatePipeline Je voulais à l'origine écrire sur mon interprétation du code source du "Middleware Laravel", mais j'ai trouvé qu'il y en avait déjà. beaucoup en ligne L'article l'a déjà expliqué, cet article parlera donc simplement de la façon d'utiliser IlluminatePipeline.

Écrire une démo

public function demo(Request $request)
{
    $pipe1 = function ($payload, Closure $next) {
        $payload = $payload + 1;
        return $next($payload);
    };

    $pipe2 = function ($payload, Closure $next) {
        $payload = $payload * 3;
        return $next($payload);
    };

    $data = $request->input('data', 0);

    $pipeline = new Pipeline();

    return $pipeline
        ->send($data)
        ->through([$pipe1, $pipe2])
        ->then(function ($data) {
            return $data;
        });
}


À propos de lanalyse du plug-in de pipeline PHP League\Pipeline

À propos de lanalyse du plug-in de pipeline PHP League\Pipeline

Pour l'analyse de ce code source, vous pouvez recommander la lecture de cet article, l'analyse est assez approfondie :

Implémentation du composant Laravel Pipeline https://www.insp.top/article/realization-of-pipeline -component -for-laravel

LeaguePipeline

La simple utilisation de gulp et IlluminatePipeline ci-dessus nous indique simplement que "Pipeline" est largement utilisé. Si on nous demandait d'écrire nous-mêmes un plug-in similaire, je pense que ce ne serait pas difficile.

Permettez-moi maintenant de jeter un œil au code source du plug-in LeaguePipeline pour voir comment il est implémenté.

Brève description

Ce package fournit une implémentation plug and play du Pipeline Pattern. C'est un modèle architectural qui encapsule des processus séquentiels. Lorsqu'il est utilisé, il vous permet de mélanger. et faire correspondre les opérations et les pipelines pour créer de nouvelles chaînes d'exécution. Le modèle de pipeline est souvent comparé à une ligne de production, où chaque étape effectue une certaine opération sur une charge utile/un sujet donné. Les étapes peuvent agir, manipuler, décorer ou même remplacer. la charge utile.

Si vous vous retrouvez à transmettre des résultats d'une fonction à une autre pour effectuer une série de tâches sur un sujet donné, vous souhaiterez peut-être le convertir en pipeline.

https://pipeline. thephpleague.com/

Installer le plug-in

composer require league/pipeline

Écrire une démo

use League\Pipeline\Pipeline;

// 创建两个闭包函数
$pipe1 = function ($payload) {
    return $payload + 1;
};

$pipe2 = function ($payload) {
    return $payload * 3;
};

$route->map(
    'GET',
    '/demo',
    function (ServerRequestInterface $request, ResponseInterface $response
    ) use ($service, $pipe1, $pipe2) {
        $params = $request->getQueryParams();

        // 正常使用
        $pipeline1 = (new Pipeline)
            ->pipe($pipe1)
            ->pipe($pipe2);

        $callback1 = $pipeline1->process($params['data']);

        $response->getBody()->write("<h1>正常使用</h1>");
        $response->getBody()->write("<p>结果:$callback1</p>");

        // 使用魔术方法
        $pipeline2 = (new Pipeline())
            ->pipe($pipe1)
            ->pipe($pipe2);

        $callback2 = $pipeline2($params['data']);

        $response->getBody()->write("<h1>使用魔术方法</h1>");
        $response->getBody()->write("<p>结果:$callback2</p>");

        // 使用 Builder
        $builder = new PipelineBuilder();
        $pipeline3 = $builder
            ->add($pipe1)
            ->add($pipe2)
            ->build();

        $callback3 = $pipeline3($params['data']);

        $response->getBody()->write("<h1>使用 Builder</h1>");
        $response->getBody()->write("<p>结果:$callback3</p>");
        return $response;
    }
);

Résultats d'exécution

À propos de lanalyse du plug-in de pipeline PHP League\Pipeline

À propos de lanalyse du plug-in de pipeline PHP League\Pipeline

Interprétation du code source

Voilà pour tout le fichier du plug-in :

À propos de lanalyse du plug-in de pipeline PHP League\Pipeline

PipelineInterface

<?php declare(strict_types=1);

namespace League\Pipeline;

interface PipelineInterface extends StageInterface
{
    /**
     * Create a new pipeline with an appended stage.
     *
     * @return static
     */
    public function pipe(callable $operation): PipelineInterface;
}

interface StageInterface
{
    /**
     * Process the payload.
     *
     * @param mixed $payload
     *
     * @return mixed
     */
    public function __invoke($payload);
}

Cette interface utilise principalement l'idée de programmation en chaîne pour ajouter continuellement des tuyaux », puis ajoutez une méthode magique pour faire fonctionner les paramètres entrants.

Jetons un coup d'œil à ce que fait cette méthode magique :

mixed __invoke ([ $... ] )
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。

如:

<?php class CallableClass 
{
    function __invoke($x) {
        var_dump($x);
    }
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>

返回结果:

int(5)
bool(true)

Pipeline

<?php declare(strict_types=1);

namespace League\Pipeline;

class Pipeline implements PipelineInterface
{
    /**
     * @var callable[]
     */
    private $stages = [];

    /**
     * @var ProcessorInterface
     */
    private $processor;

    public function __construct(ProcessorInterface $processor = null, callable ...$stages)
    {
        $this->processor = $processor ?? new FingersCrossedProcessor;
        $this->stages = $stages;
    }

    public function pipe(callable $stage): PipelineInterface
    {
        $pipeline = clone $this;
        $pipeline->stages[] = $stage;

        return $pipeline;
    }

    public function process($payload)
    {
        return $this->processor->process($payload, ...$this->stages);
    }

    public function __invoke($payload)
    {
        return $this->process($payload);
    }
}

其中核心类 Pipeline 的作用主要就是两个:

  1. 添加组装各个管道「pipe」;

  2. 组装后,引水流动,执行 process($payload),输出结果。

Processor

接好各种管道后,那就要「引水入渠」了。该插件提供了两个基础执行类,比较简单,直接看代码就能懂。

// 按照 $stages 数组顺利,遍历执行管道方法,再将结果传入下一个管道,让「水」一层层「流动」起来
class FingersCrossedProcessor implements ProcessorInterface
{
    public function process($payload, callable ...$stages)
    {
        foreach ($stages as $stage) {
            $payload = $stage($payload);
        }

        return $payload;
    }
}

// 增加一个额外的「过滤网」,经过每个管道后的结果,都需要 check,一旦满足则终止,直接输出结果。
class InterruptibleProcessor implements ProcessorInterface
{
    /**
     * @var callable
     */
    private $check;

    public function __construct(callable $check)
    {
        $this->check = $check;
    }

    public function process($payload, callable ...$stages)
    {
        $check = $this->check;

        foreach ($stages as $stage) {
            $payload = $stage($payload);

            if (true !== $check($payload)) {
                return $payload;
            }
        }

        return $payload;
    }
}

interface ProcessorInterface
{
    /**
     * Process the payload using multiple stages.
     *
     * @param mixed $payload
     *
     * @return mixed
     */
    public function process($payload, callable ...$stages);
}

我们完全也可以利用该接口,实现我们的方法来组装管道和「过滤网」。

PipelineBuilder

最后提供了一个 Builder,这个也很好理解:

class PipelineBuilder implements PipelineBuilderInterface
{
    /**
     * @var callable[]
     */
    private $stages = [];

    /**
     * @return self
     */
    public function add(callable $stage): PipelineBuilderInterface
    {
        $this->stages[] = $stage;

        return $this;
    }

    public function build(ProcessorInterface $processor = null): PipelineInterface
    {
        return new Pipeline($processor, ...$this->stages);
    }
}

interface PipelineBuilderInterface
{
    /**
     * Add an stage.
     *
     * @return self
     */
    public function add(callable $stage): PipelineBuilderInterface;

    /**
     * Build a new Pipeline object.
     */
    public function build(ProcessorInterface $processor = null): PipelineInterface;
}

总结

无论是对不同技术的横向理解,还是基于 Laravel 或者某些开源插件,我们都能学习到技术之上的通用原理和方法。再将这些原理和方法反作用于我们的实际代码开发中。

最近闲来没事,自己参考 Laravel 去写个简易框架,也将League\Pipeline 引入到框架中使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

关于PHP开发中遇到的一些错误的解决方法

关于利用Vue-laravel前端和后端分离写一个博客的方法

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn