开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

程序化表达

Enrico刚从phpDay回来,他在会上谈到了Expressive和即将推出的ZendFramework3。他带回的一条反馈与人们如何看待他们应该构建Expressive应用程序有关:许多人认为,根据我们的例子,它是完全配置驱动!

事实证明,这与事实相去甚远;我们开发了我们的API来模仿传统微框架的API,然后在其之上构建了一个配置层以允许进行替换。然而,混合搭配这两种想法不仅可行,而且非常有趣!

作为实验,我拿了自己网站的源代码,做了一些调整:

  • 我将中间件管道从我的config/autoload/middleware-pipeline.global.php文件导入到我的public/index.php中的programmaticdeclarations。
  • 我将路由中间件定义从我的config/autoload/routes.global.php文件导入到我的public/index.php中的编程声明中。

要记住的点点滴滴:

  • 使用完全限定的类名来引用您的中间件,就像您在配置中所做的那样。这允许Expressive从您仍在配置的容器中提取它们!
  • 在定义管道和定义路由时,操作顺序很重要。然而,管道和路由可以单独定义,我建议这样做;这样您就可以独立于路由定义查看整个应用程序管道。

这是我最终得到的结果。

首先,我的中间件管道配置只变成依赖项列表,以确保服务正确连接:

// config/autoload/middleware-pipeline.php
use Mwop\Auth\Middleware as AuthMiddleware;
use Mwop\Auth\MiddlewareFactory as AuthMiddlewareFactory;
use Mwop\Factory\Unauthorized as UnauthorizedFactory;
use Mwop\Redirects;
use Mwop\Unauthorized;
use Mwop\XClacksOverhead;

return [
    'dependencies' => [
        'invokables' => [
            Redirects::class       => Redirects::class,
            XClacksOverhead::class => XClacksOverhead::class,
        ],
        'factories' => [
            AuthMiddleware::class => AuthMiddlewareFactory::class,
            Helper\UrlHelperMiddleware::class => Helper\UrlHelperMiddlewareFactory::class,
            Unauthorized::class => UnauthorizedFactory::class,
        ],
    ],
];

同样,路由配置现在也只是服务配置:

// config/autoload/routes.global.php
use Mwop\Blog;
use Mwop\ComicsPage;
use Mwop\Contact;
use Mwop\Factory;
use Mwop\HomePage;
use Mwop\Job;
use Mwop\ResumePage;
use Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware;
use Zend\Expressive\Router\RouterInterface;
use Zend\Expressive\Router\FastRouteRouter;

return [
    'dependencies' => [
        'delegators' => [
            Blog\DisplayPostMiddleware::class => [
                Blog\CachingDelegatorFactory::class,
            ],
        ],
        'invokables' => [
            Blog\FeedMiddleware::class           => Blog\FeedMiddleware::class,
            Blog\Console\SeedBlogDatabase::class => Blog\Console\SeedBlogDatabase::class,
            BodyParamsMiddleware::class          => BodyParamsMiddleware::class,
            RouterInterface::class               => FastRouteRouter::class,
        ],
        'factories' => [
            Blog\DisplayPostMiddleware::class => Blog\DisplayPostMiddlewareFactory::class,
            Blog\ListPostsMiddleware::class   => Blog\ListPostsMiddlewareFactory::class,
            Contact\LandingPage::class        => Contact\LandingPageFactory::class,
            Contact\Process::class            => Contact\ProcessFactory::class,
            Contact\ThankYouPage::class       => Contact\ThankYouPageFactory::class,
            ComicsPage::class                 => Factory\ComicsPage::class,
            HomePage::class                   => Factory\PageFactory::class,
            Job\GithubFeed::class             => Job\GithubFeedFactory::class,
            ResumePage::class                 => Factory\PageFactory::class,
            'Mwop\OfflinePage'                => Factory\PageFactory::class,
        ],
    ],
];

最后,让我们看一下public/index.php。如前所述,Expressive定义了与其他微框架类似的API。这意味着您可以调用诸如$app->get()$app->post()等带有路由、要执行的中间件,并且在在Expressive的情况下,路由名称(用于应用程序中的URI生成)。这是完成后的样子:

// public/index.php
namespace Mwop;

use Zend\Expressive\Application;
use Zend\Expressive\Helper;

// Delegate static file requests back to the PHP built-in webserver
if (php_sapi_name() === 'cli-server'
    && is_file(__DIR__ . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH))
) {
    return false;
}

chdir(dirname(__DIR__));
require_once 'vendor/autoload.php';

$container = require 'config/container.php';
$app       = $container->get(Application::class);

// Piped middleware
$app->pipe(XClacksOverhead::class);
$app->pipe(Redirects::class);
$app->pipe('/auth', Auth\Middleware::class);
$app->pipeRoutingMiddleware();
$app->pipe(Helper\UrlHelperMiddleware::class);
$app->pipeDispatchMiddleware();
$app->pipe(Unauthorized::class);

// Routed middleware

// General pages
$app->get('/', HomePage::class, 'home');
$app->get('/comics', ComicsPage::class, 'comics');
$app->get('/offline', OfflinePage::class, 'offline');
$app->get('/resume', ResumePage::class, 'resume');

// Blog
$app->get('/blog[/]', Blog\ListPostsMiddleware::class, 'blog');
$app->get('/blog/{id:[^/]+}.html', Blog\DisplayPostMiddleware::class, 'blog.post');
$app->get('/blog/tag/{tag:php}.xml', Blog\FeedMiddleware::class, 'blog.feed.php');
$app->get('/blog/{tag:php}.xml', Blog\FeedMiddleware::class, 'blog.feed.php.also');
$app->get('/blog/tag/{tag:[^/]+}/{type:atom|rss}.xml', Blog\FeedMiddleware::class, 'blog.tag.feed');
$app->get('/blog/tag/{tag:[^/]+}', Blog\ListPostsMiddleware::class, 'blog.tag');
$app->get('/blog/{type:atom|rss}.xml', Blog\FeedMiddleware::class, 'blog.feed');

// Contact form
$app->get('/contact[/]', Contact\LandingPage::class, 'contact');
$app->post('/contact/process', Contact\Process::class, 'contact.process');
$app->get('/contact/thank-you', Contact\ThankYouPage::class, 'contact.thank-your');

// Zend Server jobs
$app->post('/jobs/clear-cache', Job\ClearCache::class, 'job.clear-cache');
$app->post('/jobs/comics', Job\Comics::class, 'job.comics');
$app->post('/jobs/github-feed', Job\GithubFeed::class, 'job.github-feed');

$app->run();

这种方法在定义中间件内联之间提供了一个很好的中间地带:

$app->get('/', function ($request, $response, $next) {
    // ... 
}, 'home');

和直接配置方法:

    'routes' => [
        [
            'path'            => '/',
            'middleware'      => HomePage::class,
            'allowed_methods' => ['GET'],
            'name'            => 'home',
        ],

        / * ... */

然而,它失去了一些灵活性:通过配置驱动的方法,我们可以轻松地定义一些只在开发中执行的路由或管道中间件,并确保它们发生的顺序——这是编程方法不容易做到的。

然而,本练习的主要目的是证明Expressive允许您选择自己的方法,这是该项目背后的指导原则。

未经允许不得转载:我爱分享网 » 程序化表达

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏