- 框架初始化
 - 安装插件
 - 修复PHP8.4报错
This commit is contained in:
2025-04-19 17:21:20 +08:00
commit c6a4e1f5f6
5306 changed files with 967782 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
/tests export-ignore
/.github export-ignore

View File

@@ -0,0 +1,4 @@
/vendor/
composer.lock
*.cache
*.log

View File

@@ -0,0 +1,92 @@
<?php
$header = <<<'EOF'
This file is part of Hyperf.
@link https://www.hyperf.io
@document https://hyperf.wiki
@contact group@hyperf.io
@license https://github.com/hyperf/hyperf/blob/master/LICENSE
EOF;
return (new PhpCsFixer\Config())
->setRiskyAllowed(true)
->setRules([
'@PSR2' => true,
'@Symfony' => true,
'@DoctrineAnnotation' => true,
'@PhpCsFixer' => true,
'header_comment' => [
'comment_type' => 'PHPDoc',
'header' => $header,
'separate' => 'none',
'location' => 'after_declare_strict',
],
'array_syntax' => [
'syntax' => 'short'
],
'list_syntax' => [
'syntax' => 'short'
],
'concat_space' => [
'spacing' => 'one'
],
'blank_line_before_statement' => [
'statements' => [
'declare',
],
],
'general_phpdoc_annotation_remove' => [
'annotations' => [
'author'
],
],
'ordered_imports' => [
'imports_order' => [
'class', 'function', 'const',
],
'sort_algorithm' => 'alpha',
],
'single_line_comment_style' => [
'comment_types' => [
],
],
'yoda_style' => [
'always_move_variable' => false,
'equal' => false,
'identical' => false,
],
'phpdoc_align' => [
'align' => 'left',
],
'multiline_whitespace_before_semicolons' => [
'strategy' => 'no_multi_line',
],
'constant_case' => [
'case' => 'lower',
],
'class_attributes_separation' => true,
'combine_consecutive_unsets' => true,
'declare_strict_types' => true,
'linebreak_after_opening_tag' => true,
'lowercase_static_reference' => true,
'no_useless_else' => true,
'no_unused_imports' => true,
'not_operator_with_successor_space' => true,
'not_operator_with_space' => false,
'ordered_class_elements' => true,
'php_unit_strict' => false,
'phpdoc_separation' => false,
'single_quote' => true,
'standardize_not_equals' => true,
'multiline_comment_opening_closing' => true,
])
->setFinder(
PhpCsFixer\Finder::create()
->exclude('bin')
->exclude('public')
->exclude('runtime')
->exclude('vendor')
->in(__DIR__)
)
->setUsingCache(false);

View File

@@ -0,0 +1,6 @@
<?php
namespace PHPSTORM_META {
// Reflect
override(\Psr\Container\ContainerInterface::get(0), map('@'));
}

View File

@@ -0,0 +1,42 @@
language: php
sudo: required
matrix:
include:
- php: 7.2
env: SW_VERSION="4.4.17"
- php: 7.3
env: SW_VERSION="4.4.17"
- php: 7.4
env: SW_VERSION="4.4.17"
- php: master
env: SW_VERSION="4.4.17"
allow_failures:
- php: master
services:
- mysql
- redis-server
- docker
before_install:
- export PHP_MAJOR="$(`phpenv which php` -r 'echo phpversion();' | cut -d '.' -f 1)"
- export PHP_MINOR="$(`phpenv which php` -r 'echo phpversion();' | cut -d '.' -f 2)"
- echo $PHP_MAJOR
- echo $PHP_MINOR
install:
- cd $TRAVIS_BUILD_DIR
- bash ./tests/swoole.install.sh
- phpenv config-rm xdebug.ini || echo "xdebug not available"
- phpenv config-add ./tests/ci.ini
before_script:
- cd $TRAVIS_BUILD_DIR
- composer config -g process-timeout 900 && composer update
script:
- composer analyse
- composer test

View File

@@ -0,0 +1,195 @@
# Pimple Container
[![Build Status](https://travis-ci.org/hyperf-cloud/pimple-integration.svg?branch=master)](https://travis-ci.org/hyperf-cloud/pimple-integration)
`hyperf/pimple` 是基于 `pimple/pimple` 实现的轻量级符合 `PSR11 规范` 的容器组件。可以减少其他框架使用 Hyperf 组件时的成本。
## 安装
```
composer require "hyperf/pimple:1.1.*"
```
## 使用
```php
<?php
use Hyperf\Pimple\ContainerFactory;
$container = (new ContainerFactory())();
```
### `EasySwoole` 接入 `hyperf/translation`
因为 `EasySwoole` 的容器组件暂时并没有实现 `PSR11` 规范,所以无法直接使用。
1. 首先引入相关组件
```
composer require "hyperf/translation:1.1.*"
composer require "hyperf/config:1.1.*"
```
2. 添加 国际化相关的 Provider
```php
<?php
declare(strict_types=1);
namespace App\Provider;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\ContainerInterface;
use Hyperf\Contract\TranslatorLoaderInterface;
use Hyperf\Pimple\ProviderInterface;
use Hyperf\Translation\FileLoader;
use Hyperf\Utils\Filesystem\Filesystem;
class TranslatorLoaderProvider implements ProviderInterface
{
public function register(ContainerInterface $container)
{
$container->set(TranslatorLoaderInterface::class, function () use ($container) {
$config = $container->get(ConfigInterface::class);
$files = $container->get(Filesystem::class);
$path = $config->get('translation.path');
return make(FileLoader::class, compact('files', 'path'));
});
}
}
```
```php
<?php
declare(strict_types=1);
namespace App\Provider;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\ContainerInterface;
use Hyperf\Contract\TranslatorInterface;
use Hyperf\Contract\TranslatorLoaderInterface;
use Hyperf\Pimple\ProviderInterface;
use Hyperf\Translation\Translator;
class TranslatorProvider implements ProviderInterface
{
public function register(ContainerInterface $container)
{
$container->set(TranslatorInterface::class, function () use ($container) {
$config = $container->get(ConfigInterface::class);
$locale = $config->get('translation.locale');
$fallbackLocale = $config->get('translation.fallback_locale');
$loader = $container->get(TranslatorLoaderInterface::class);
$translator = make(Translator::class, compact('loader', 'locale'));
$translator->setFallback((string) $fallbackLocale);
return $translator;
});
}
}
```
3. `EasySwoole` 事件注册器在 `EasySwooleEvent.php` 中,所以我们需要在 `initialize()` 中初始化我们的容器和国际化组件。
> 以下 Config 组件,可以自行封装,这里方便起见直接配置。
```php
<?php
declare(strict_types=1);
namespace EasySwoole\EasySwoole;
use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\EasySwoole\Swoole\EventRegister;
use EasySwoole\Http\Request;
use EasySwoole\Http\Response;
use Hyperf\Config\Config;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Pimple\ContainerFactory;
use App\Provider\TranslatorProvider;
use App\Provider\TranslatorLoaderProvider;
class EasySwooleEvent implements Event
{
public static function initialize()
{
date_default_timezone_set('Asia/Shanghai');
$container = (new ContainerFactory([
TranslatorProvider::class,
TranslatorLoaderProvider::class,
]))();
$container->set(ConfigInterface::class, new Config([
'translation' => [
'locale' => 'zh_CN',
'fallback_locale' => 'en',
'path' => EASYSWOOLE_ROOT . '/storage/languages',
],
]));
}
}
```
4. 修改控制器,使用国际化组件
```php
<?php
declare(strict_types=1);
namespace App\HttpController;
use EasySwoole\Http\AbstractInterface\Controller;
use Hyperf\Contract\TranslatorInterface;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Codec\Json;
class Index extends Controller
{
public function index()
{
$container = ApplicationContext::getContainer();
$translator = $container->get(TranslatorInterface::class);
$data = [
'message' => $translator->trans('message.hello', ['name' => 'Hyperf']),
];
$this->response()->write(Json::encode($data));
}
}
```
5. 添加国际化配置
```php
// storage/languages/en/message.php
return [
'hello' => 'Hello :name',
];
// storage/languages/zh_CN/message.php
return [
'hello' => '你好 :name',
];
```
6. 测试
```
$ curl http://127.0.0.1:9501/
{"message":"你好 Hyperf"}
```

View File

@@ -0,0 +1,53 @@
{
"name": "hyperf/pimple",
"type": "library",
"license": "MIT",
"keywords": [
"php",
"hyperf",
"container",
"psr11"
],
"description": "Pimple Container",
"autoload": {
"psr-4": {
"Hyperf\\Pimple\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"HyperfTest\\": "tests"
}
},
"require": {
"php": ">=7.4",
"doctrine/instantiator": "^1.0",
"hyperf/utils": "^2.2|^3.0",
"pimple/pimple": "^3.3"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"mockery/mockery": "^1.3",
"phpstan/phpstan": "^1.0",
"phpunit/phpunit": ">=7.0"
},
"minimum-stability": "dev",
"prefer-stable": true,
"config": {
"optimize-autoloader": true,
"sort-packages": true
},
"scripts": {
"test": "phpunit -c phpunit.xml --colors=always",
"analyse": "phpstan analyse --memory-limit 300M -l 0 ./src",
"cs-fix": "php-cs-fixer fix $1"
},
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
},
"hyperf": {
"config": "Hyperf\\Pimple\\ConfigProvider"
}
}
}

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php"
backupGlobals="false"
backupStaticAttributes="false"
verbose="true"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuite name="Testsuite">
<directory>./tests/</directory>
</testsuite>
</phpunit>

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Pimple;
class ConfigProvider
{
public function __invoke(): array
{
return [
'dependencies' => [
],
'commands' => [
],
'annotations' => [
'scan' => [
'paths' => [
__DIR__,
],
],
],
];
}
}

View File

@@ -0,0 +1,139 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Pimple;
use Hyperf\Contract\ContainerInterface;
use Hyperf\Pimple\Exception\InvalidDefinitionException;
use Hyperf\Pimple\Exception\NotFoundException;
use Hyperf\Pimple\Exception\NotSupportException;
use Pimple;
use Psr\Container\ContainerInterface as PsrContainerInterface;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use ReflectionParameter;
class Container implements ContainerInterface
{
/**
* @var Pimple\Container
*/
protected $pimple;
/**
* @var ReflectionClass[]
*/
protected $reflection = [];
public function __construct(Pimple\Container $pimple)
{
$this->pimple = $pimple;
$this->pimple[ContainerInterface::class] = $this;
$this->pimple[PsrContainerInterface::class] = $this;
}
public function get($id)
{
if ($this->has($id)) {
return $this->pimple[$id];
}
return $this->pimple[$id] = $this->make($id);
}
public function has($id): bool
{
return isset($this->pimple[$id]);
}
public function make(string $name, ?array $parameters = [])
{
if (! class_exists($name)) {
throw new NotFoundException("Entry {$name} is not found.");
}
$ref = $this->reflection[$name] ?? new ReflectionClass($name);
$constructor = $ref->getConstructor();
$args = [];
if ($constructor && $constructor->isPublic()) {
$args = $this->resolveParameters($constructor, $parameters);
}
$instance = new $name(...$args);
$this->reflection[$name] = $ref;
return $instance;
}
public function set(string $name, $entry): void
{
$this->pimple[$name] = $entry;
}
public function define(string $name, $definition): void
{
throw new NotSupportException('Method define is not support.');
}
public function unbind(string $name): void
{
$this->pimple[$name] = null;
}
protected function resolveParameters(ReflectionMethod $method, $parameters = [])
{
$args = [];
foreach ($method->getParameters() as $index => $parameter) {
if (array_key_exists($parameter->getName(), $parameters)) {
$value = $parameters[$parameter->getName()];
} elseif (array_key_exists($index, $parameters)) {
$value = $parameters[$index];
} elseif ($parameter->getType() && $this->has($parameter->getType()->getName())) {
$value = $this->get($parameter->getType()->getName());
} else {
if ($parameter->isDefaultValueAvailable() || $parameter->isOptional()) {
$value = $this->getParameterDefaultValue($parameter, $method);
} else {
throw new InvalidDefinitionException(sprintf(
'Parameter $%s of %s has no value defined or guessable',
$parameter->getName(),
$this->getFunctionName($method)
));
}
}
$args[] = $value;
}
return $args;
}
protected function getParameterDefaultValue(ReflectionParameter $parameter, ReflectionMethod $function)
{
try {
return $parameter->getDefaultValue();
} catch (ReflectionException $e) {
throw new InvalidDefinitionException(sprintf(
'The parameter "%s" of %s has no type defined or guessable. It has a default value, '
. 'but the default value can\'t be read through Reflection because it is a PHP internal class.',
$parameter->getName(),
$this->getFunctionName($function)
));
}
}
private function getFunctionName(ReflectionMethod $method): string
{
return $method->getName() . '()';
}
}

View File

@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Pimple;
use Hyperf\Utils\ApplicationContext;
use Pimple;
class ContainerFactory
{
protected $providers = [];
public function __construct(array $providers = [])
{
$this->providers = $providers;
}
public function __invoke()
{
$container = new Container(new Pimple\Container());
foreach ($this->providers as $provider) {
/** @var ProviderInterface $instance */
$instance = new $provider();
$instance->register($container);
}
return ApplicationContext::setContainer($container);
}
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Pimple\Exception;
use Psr\Container\ContainerExceptionInterface;
class InvalidDefinitionException extends \Exception implements ContainerExceptionInterface
{
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Pimple\Exception;
use Psr\Container\NotFoundExceptionInterface;
class NotFoundException extends \RuntimeException implements NotFoundExceptionInterface
{
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Pimple\Exception;
use Psr\Container\ContainerExceptionInterface;
class NotSupportException extends \Exception implements ContainerExceptionInterface
{
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Pimple;
use Hyperf\Contract\ContainerInterface;
interface ProviderInterface
{
public function register(ContainerInterface $container);
}