定制 nyholm/sunflower 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

nyholm/sunflower

Composer 安装命令:

composer require nyholm/sunflower

包简介

The best Kernel for simple applications.

README 文档

README

Sunflower is a super small application kernel that is used to build a dependency injection container. This kernel is useful for microservices and applications that dont use HTTP. Say; reading from a queue or application invoked by AWS Lambda.

With this kernel you can use normal Symfony service definition with auto wiring and all. It even supports Symfony bundles!

The main difference from using symfony/http-kernel and Symfony FrameworkBundle is that Sunflower does not use symfony/event-dispatcher, symfony/console, symfony/security, symfony/cache and symfony/router.

Performance

Below is a table of requests per second using a "hello world" application with different frameworks. The exact numbers are not relevant, they depend on the machine the tests was running on. But one should consider how the numbers change between frameworks since all test ran on the same machine.

Framework Req/s
Sunflower 2.548
Symfony 6.0 1.819
Symfony 5.4 1.804
Slim 4 1.380
Mezzio 3 985
Laravel 8 421

Using a "hello world" comparison has some drawbacks. It does show performance for small applications with only a few hundreds lines of code, but it does not tell how large applications preform. It also does not give you any indication how fast you can write and maintain your application.

The table above is interesting if you are planning to build a small microservice that are similar to "hello world". Using the Sunflower Kernel is also very interesting if you are familiar with Symfony dependency injections, config and third party bundles.

Install

composer require nyholm/sunflower

Use

// src/Kernel.php
namespace App;

use Nyholm\SunflowerKernel;

class Kernel extends SunflowerKernel
{
   /**
    * Optionally override the configureContainer()
    */
   protected function configureContainer(ContainerConfigurator $container): void
    {
        $container->import('../config/{packages}/*.yaml');
        $container->import('../config/{packages}/'.$this->environment.'/*.yaml');
        $container->import('../config/{packages}/'.$this->environment.'/*.php');

        if (\is_file(\dirname(__DIR__).'/config/services.yaml')) {
            $container->import('../config/services.yaml');
            $container->import('../config/{services}_'.$this->environment.'.yaml');
        } else {
            $container->import('../config/{services}.php');
        }
    }
}
use App\Kernel;
use App\Service\MyService;

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

$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
$kernel->getContainer()->get(MyService::class)->run();

Use with HTTP

A short example using HTTP and a simple switch-router. This example is using runtime/psr-nyholm.

// public/index.php

use Nyholm\Psr7;

require_once dirname(__DIR__).'/vendor/autoload_runtime.php';

return function (array $context) {
    $kernel = new \App\Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
    $container = $kernel->getContainer();

    // This is an example router
    $urlPath = $context['REQUEST_URI'];
    switch ($urlPath) {
        case '/':
        case '':
            // This is an RequestHandlerInterface
            return $container->get(\App\Controller\Startpage::class);
        case '/foobar':
            return $container->get(\App\Controller\Foobar::class);
        default:
            return new Psr7\Response(404, [], 'The route does not exist');
    }
};
# config/services.yaml

services:
    _defaults:
        autowire: true
        autoconfigure: true

    _instanceof:
        Psr\Http\Server\RequestHandlerInterface:
            public: true

    App\:
        resource: '../src/'
        exclude:
            - '../src/Kernel.php'

Use with Bref

To create apps that works with Bref you will need the runtime/bref package. Create microservices, SQS readers or react to S3 events etc.

// src/Kernel.php

namespace App;

use Nyholm\SunflowerKernel;

class Kernel extends SunflowerKernel
{
    public function isLambda(): bool
    {
        return false !== \getenv('LAMBDA_TASK_ROOT');
    }

    public function getCacheDir(): string
    {
        if ($this->isLambda()) {
            return '/tmp/cache/'.$this->environment;
        }

        return parent::getCacheDir();
    }

    public function getLogDir(): string
    {
        if ($this->isLambda()) {
            return '/tmp/log/';
        }

        return parent::getLogDir();
    }

    public function getProjectDir(): string
    {
        return \dirname(__DIR__);
    }
}
// bin/container.php

use App\Kernel;

require_once dirname(__DIR__).'/vendor/autoload_runtime.php';

return function (array $context) {
    $kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);

    return $kernel->getContainer();
};
# config/services.yaml

services:
    _defaults:
        autowire: true
        autoconfigure: true

    _instanceof:
        Bref\Event\Handler:
            public: true

    App\:
        resource: '../src/'
        exclude:
            - '../src/Kernel.php'
 # serverless.yml

  functions:
      app:
          handler: bin/container.php:App\Service\MyHandler

Use with CLI

// bin/console
#!/usr/bin/env php
<?php

use App\Kernel;
use Symfony\Component\Console\Application;

require_once dirname(__DIR__).'/vendor/autoload_runtime.php';

return function (array $context) {
    $kernel = new Kernel($context['APP_ENV'], (bool)$context['APP_DEBUG']);
    $container = $kernel->getContainer();

    $app = new Application();
    // Register all your commands here
    $app->add($container->get(\App\Command\HelloCommand::class));

    return $app;
};
declare(strict_types=1);

namespace App\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(name: 'app:debug:hello')]
class HelloCommand extends Command
{
    protected function configure()
    {
        $this->setDescription('Test print hello.');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $output->writeln('Hello');

        return Command::SUCCESS;
    }
}
# config/services.yaml

services:
    _defaults:
        autowire: true
        autoconfigure: true

    _instanceof:
        Symfony\Component\Console\Command\Command:
            public: true

    App\:
        resource: '../src/'
        exclude:
            - '../src/Kernel.php'

History

The Sunflower project was open sourced in 2021. The very first version of the project was created back in 2015. A few private applications was created around the concept of using Symfony's Dependency Injection component but not use the FrameworkBundle or HttpKernel.

The first public version of the project was SuperSlim. That version was a opinionated framework to show what the FrameworkBundle actually did for you behind the scenes. With some more private iterations and many more applications created, we finally removed all unnecessary things and ended up with just the one Kernel.

统计信息

  • 总下载量: 21.82k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 20
  • 点击次数: 2
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 20
  • Watchers: 1
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2021-09-03

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固