zend 开发php_Zend表达模块的快速开发

zend 开发php

I have learned a few tricks when writing Zend Expressive modules that I want to share with you.

在编写要与您共享的Zend Expressive模块时,我学到了一些技巧。

Please follow the previous post first to set up a proper working environment. I explained how to install and configure Zend Expressive with Doctrine, Gulp, and an abstract reflection factory – it’ll take a total of 10 minutes.

请先按照上一篇文章设置适当的工作环境。 我解释了如何使用Doctrine,Gulp和抽象反射工厂来安装和配置Zend Expressive,这总共需要10分钟。

In this tutorial, we’ll build a simple read-only blog module (a page listing blog posts from a database) in minutes, demonstrating the kind of rapid development one is capable of with Zend Expressive.

在本教程中,我们将在几分钟内构建一个简单的只读博客模块(列出数据库中博客文章的页面),以演示Zend Expressive能够进行的快速开发。

Zend expressive logo

模块设置 (Module Setup)

Run this command from your expressive app to get started:

从富有表现力的应用程序中运行以下命令以开始使用:

./vendor/bin/expressive module:create Blog

This will generate some base code for a Blog module and will register your module automatically with your application. It will also register your module with the Composer autoloader.

这将为Blog模块生成一些基本代码,并将模块自动注册到您的应用程序中。 它还会在Composer自动加载器中注册您的模块。

学说实体和数据库表 (Doctrine Entity and Database Table)

Let’s make our Blog entity and database tables. First, we need to let our application know that this module provides Doctrine entities.

让我们制作Blog实体和数据库表。 首先,我们需要让我们的应用程序知道该模块提供了Doctrine实体。

Open src/Blog/src/ConfigProvider.php and add the following:

打开src/Blog/src/ConfigProvider.php并添加以下内容:

public function __invoke()
{
    return [
        'dependencies' => $this->getDependencies(),
        'doctrine'     => $this->getDoctrine(),
        'templates'    => $this->getTemplates(),
    ];
}

/**
 * @return array
 */
public function getDoctrine(): array
{
    return [
        'driver' => [
            'orm_default' => [
                'drivers' => [
                    'Blog\Entity' => 'blog_entity',
                ],
            ],
            'blog_entity' => [
                'class' => \Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver::class,
                'cache' => 'array',
                'paths' => [
                    dirname(__DIR__) . '/config/doctrine' => 'Blog\Entity',
                ],
            ],
        ],
    ];
}

Create a blog post entity config at src/Blog/config/doctrine/BlogPost.orm.yml:

src/Blog/config/doctrine/BlogPost.orm.yml创建博客帖子实体配置:

---
Blog\Entity\BlogPost:
  type: entity
  table: blog_post
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    title:
      type: string
      length: 255
    content:
      type: string
      length: 16777215

Then, run ./vendor/bin/doctrine orm:generate-entities src.

然后,运行./vendor/bin/doctrine orm:generate-entities src

Sadly, Doctrine doesn’t and probably won’t support PSR-4 because the standard doesn’t force a directory structure.

可悲的是,Doctrine不支持PSR-4,因为它不会强制使用目录结构。

To get around this, we need to move src/Blog/Entity to src/Blog/src/Entity.

为了解决这个问题,我们需要将src/Blog/Entity移到src/Blog/src/Entity

Then, run this command to create your database table:

然后,运行以下命令来创建数据库表:

./vendor/bin/doctrine orm:schema-tool:create

Now, you can populate the database table by running the following SQL:

现在,您可以通过运行以下SQL来填充数据库表:

INSERT INTO expressive.blog_post VALUES 
(null, 'Post 1', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'),
(null, 'Post 2', 'Mauris in libero laoreet, euismod lorem eget, tincidunt justo.'),
(null, 'Post 3', 'Donec sed diam congue, ultrices tellus at, venenatis felis.');

路由 (Routing)

Modules in Expressive do not register their own routes. We can make them do so, however, with this handy trick. You don’t have to understand it. Just put the files in place and know that it works.

Expressive中的模块不会注册自己的路由。 但是,我们可以通过这个方便的技巧使他们这样做。 您不必了解它。 只需将文件放在适当的位置,然后知道它可以工作。

Create a src/Blog/src/Factory/RoutesDelegator.php with the following contents:

使用以下内容创建一个src/Blog/src/Factory/RoutesDelegator.php

<?php

namespace Blog\Factory;

use Blog\Action;
use Psr\Container\ContainerInterface;
use Zend\Expressive\Application;

class RoutesDelegator
{
    /**
     * @param ContainerInterface $container
     * @param string $serviceName Name of the service being created.
     * @param callable $callback Creates and returns the service.
     * @return Application
     */
    public function __invoke(ContainerInterface $container, $serviceName, callable $callback)
    {
        /** @var $app Application */
        $app = $callback();

        include __DIR__ . '/../../config/routes.php';

        return $app;
    }
}

In src/Blog/src/ConfigProvider.php, add this as a top level array key to the getDependencies() method:

src/Blog/src/ConfigProvider.php ,将此作为顶级数组键添加到getDependencies()方法中:

'delegators' => [
    \Zend\Expressive\Application::class => [
        Factory\RoutesDelegator::class,
    ],
],

Now you can create a src/Blog/config/routes.php file and start adding blog routes.

现在,您可以创建src/Blog/config/routes.php文件并开始添加博客路由。

<?php
/**
 * Setup routes with a single request method:
 * @var \Zend\Expressive\Application $app
 *
 * $app->post('/album', App\Action\AlbumCreateAction::class, 'album.create');
 * $app->put('/album/:id', App\Action\AlbumUpdateAction::class, 'album.put');
 * $app->patch('/album/:id', App\Action\AlbumUpdateAction::class, 'album.patch');
 * $app->delete('/album/:id', App\Action\AlbumDeleteAction::class, 'album.delete');
 *
 * Or with multiple request methods:
 *
 * $app->route('/contact', App\Action\ContactAction::class, ['GET', 'POST', ...], 'contact');
 *
 * Or handling all request methods:
 *
 * $app->route('/contact', App\Action\ContactAction::class)->setName('contact');
 *
 * or:
 *
 * $app->route(
 *     '/contact',
 *     App\Action\ContactAction::class,
 *     Zend\Expressive\Router\Route::HTTP_METHOD_ANY,
 *     'contact'
 * );
 */

use Blog\Action;

// Setup routes:
$app->get('/blog', Action\BlogPostListAction::class, 'blog_post_list');
$app->get('/blog/view/:blog_post_id', Action\BlogPostViewAction::class, 'blog_post_view');

动作 (Actions)

Then, we need to create an action to respond to each route.

然后,我们需要创建一个动作来响应每条路线。

Create src/Blog/src/Action/BlogPostListAction.php:

创建src/Blog/src/Action/BlogPostListAction.php

<?php

namespace Blog\Action;

use Blog\Entity\BlogPost;
use Doctrine\ORM\EntityManager;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response\HtmlResponse;
use Zend\Expressive\Router;
use Zend\Expressive\Template;

class BlogPostListAction implements ServerMiddlewareInterface
{
    /**
     * @var Template\TemplateRendererInterface
     */
    private $templateRenderer;
    /**
     * @var EntityManager
     */
    private $entityManager;

    public function __construct(
        EntityManager $entityManager,
        Template\TemplateRendererInterface $templateRenderer = null
    ) {
        $this->templateRenderer = $templateRenderer;
        $this->entityManager = $entityManager;
    }

    public function process(ServerRequestInterface $request, DelegateInterface $delegate)
    {
        $posts = $this->entityManager->getRepository(BlogPost::class)
            ->findAll();
        $data = [
            'posts' => $posts,
        ];

        return new HtmlResponse($this->templateRenderer->render('blog::list', $data));
    }
}

Create src/Blog/src/Action/BlogPostViewAction.php:

创建src/Blog/src/Action/BlogPostViewAction.php

<?php

namespace Blog\Action;

use Blog\Entity\BlogPost;
use Doctrine\ORM\EntityManager;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response\HtmlResponse;
use Zend\Expressive\Router;
use Zend\Expressive\Router\RouteResult;
use Zend\Expressive\Template;

class BlogPostViewAction implements ServerMiddlewareInterface
{
    /**
     * @var Router\RouterInterface
     */
    private $router;
    /**
     * @var Template\TemplateRendererInterface
     */
    private $templateRenderer;
    /**
     * @var EntityManager
     */
    private $entityManager;

    public function __construct(
        EntityManager $entityManager,
        Router\RouterInterface $router,
        Template\TemplateRendererInterface $templateRenderer = null
    ) {

        $this->router = $router;
        $this->templateRenderer = $templateRenderer;
        $this->entityManager = $entityManager;
    }

    public function process(ServerRequestInterface $request, DelegateInterface $delegate)
    {
        /** @var RouteResult $routeResult */
        $routeResult = $request->getAttribute(RouteResult::class);
        $routeMatchedParams = $routeResult->getMatchedParams();
        if (empty($routeMatchedParams['blog_post_id'])) {
            throw new \RuntimeException('Invalid route: "blog_post_id" not set in matched route params.');
        }
        $blogId = $routeMatchedParams['blog_post_id'];

        /** @var BlogPost $blogPost */
        $blogPost = $this->entityManager->find(BlogPost::class, $blogId);
        if (!$blogPost) {
            return new HtmlResponse($this->templateRenderer->render('error::404'), 404);
        }

        $data = [
            'post' => $blogPost,
        ];

        return new HtmlResponse($this->templateRenderer->render('blog::view', $data));
    }
}

范本 (Templates)

Open src/Blog/src/ConfigProvider.php. and update the getTemplates() method to this:

打开src/Blog/src/ConfigProvider.php 。 并将getTemplates()方法更新为此:

public function getTemplates()
{
    return [
        'paths' => [
            'blog'    => [__DIR__ . '/../templates/blog'],
        ],
    ];
}

Now we can make some quick templates:

现在我们可以制作一些快速模板:

Create src/Blog/templates/blog/list.html.twig:

创建src/Blog/templates/blog/list.html.twig

{% extends '@layout/default.html.twig' %}

{% block title %}Blog{% endblock %}

{% block content %}
    <div class="row">

    {% for post in posts %}

        <div class="col-md-4">
            <h2>
                <a href="/blog/view/{{ post.id }}">
                    <i class="fa fa-refresh"></i> {{ post.title }}
                </a>
            </h2>
            <p>
                {{ post.content }}
            </p>
        </div>
    {% endfor %}
    </div>

{% endblock %}

Create src/Blog/templates/blog/view.html.twig:

创建src/Blog/templates/blog/view.html.twig

{% extends '@layout/default.html.twig' %}

{% block title %}{{ post.title }} | Blog {% endblock %}

{% block content %}
    <div class="row">
        <div class="col-xs-12">
            <h1>{{ post.title }}</h1>
            <p>
                {{ post.content }}
            </p>
        </div>
    </div>

{% endblock %}

If you open the /blog URL, you’ll have a functional, database driven blog list and will be able to view pages.

如果打开/blog URL,将有一个功能强大的数据库驱动的博客列表,并且能够查看页面。

Blog

We’ll leave the implementation of create, edit, and delete functionality up to you as homework.

我们将把创建,编辑和删除功能的实现留给您作为作业。

结论 (Conclusion)

In this short tutorial, we saw how simple it was to implement a read-only blog module with Zend Expressive. In no more than a handful of files and 10 minutes of work, the list page could display our posts from the database and was ready for additional routes, like /edit, and /delete.

在这个简短的教程中,我们看到了使用Zend Expressive实现只读博客模块是多么简单。 列表页面只用了很少的文件和10分钟的工作,就可以显示我们数据库中的帖子,并准备使用其他路由,例如/edit/delete

Do you use Zend Expressive in your projects? What do you like/dislike about it? Let us know how you get on!

您在项目中使用Zend Expressive吗? 您喜欢/不喜欢什么? 让我们知道您的身体情况如何!

翻译自: https://www.sitepoint.com/rapid-development-zend-expressive-modules/

zend 开发php

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值