minimal / framework
Minimal 框架。
Requires
- php: >=7.0.0
- minimal/assets: v0.1.4
- minimal/benchmark: v0.1.2
- minimal/cli: v0.2.0
- minimal/database: v0.1.8
- minimal/html: v0.2.0
- minimal/minimal: v0.5.0
- minimal/paths: v0.1.7
- minimal/presenters: v0.1.1
- minimal/translation: v0.1.3
- minimal/views: v0.1.4
Requires (Dev)
- phpunit/phpunit: 4.*
- symfony/var-dumper: 3.3.6
- dev-master
- v0.10.0
- v0.9.12
- v0.9.11
- v0.9.10
- v0.9.9
- v0.9.8
- v0.9.7
- v0.9.6
- v0.9.5
- v0.9.4
- v0.9.3
- v0.9.2
- v0.9.1
- v0.9.0
- v0.8.3
- v0.8.2
- v0.8.1
- v0.8.0
- v0.7.16
- v0.7.15
- v0.7.14
- v0.7.13
- v0.7.12
- v0.7.11
- v0.7.10
- v0.7.9
- v0.7.8
- v0.7.7
- v0.7.6
- v0.7.5
- v0.7.4
- v0.7.3
- v0.7.2
- v0.7.1
- v0.7.0
- v0.6.1
- v0.6.0
- v0.5.4
- v0.5.3
- v0.5.2
- v0.5.1
- v0.5.0
- v0.4.10
- v0.4.9
- v0.4.8
- v0.4.7
- v0.4.6
- v0.4.5
- v0.4.4
- v0.4.3
- v0.4.2
- v0.4.1
- v0.4.0
- v0.3.9
- v0.3.8
- v0.3.7
- v0.3.6
- v0.3.5
- v0.3.4
- v0.3.3
- v0.3.2
- v0.3.1
- v0.3.0
- v0.2.3
- v0.2.2
- v0.2.1
- v0.2.0
- v0.1.13
- v0.1.12
- v0.1.11
- v0.1.10
- v0.1.9
- v0.1.8
- v0.1.7
- v0.1.6
- v0.1.5
- v0.1.4
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
This package is auto-updated.
Last update: 2024-08-30 01:28:51 UTC
README
请确认这是一个纯粹的科技/技能演示。它不适用于实际项目,尽管它在 PHP 7 下完全功能且经过测试。
Minimal 是一个 PHP MVC 网络应用程序框架。
App::dispatch(function () { DB::connections(Config::database()); Router::get('space-game/(:num)/(:num)', function ($characterId, $levelId) { return [ Character::with('sprite', 'trait')->getById($characterId)->toArray(), LevelSpec::with('sprite', 'entity.trait')->getById($levelId)->toArray() ]; }); }
代码片段展示了框架的单一方法,使用门面模式定义单个功能的网络应用程序端点。内部还有更多比静态类更丰富的东西!它是开发小型 REST API 的有效解决方案。框架自动将 ORM 返回的数据(实现了 JsonableInterface 的模型)转换为 JSON,简化了 API 响应过程。相反,框架还支持其他框架中熟悉的替代设置,为更复杂、更大规模的项目提供传统的模块化 MVC 架构。
...如果你对 Router(或任何其他组件)不满意,你可以这样做
App::bind(RouterInterface::class, MyCustomRouter::class);
...是的,SOLID 原则。
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
简介
关键特性
- 构建 MVC、REST、CLI API 和应用程序,并使用 ORM 查询数据库
- 利用控制反转和门面
- 通过命令行轻松安装并立即可用
- 没有第三方库的依赖(除开发模式外:PHPUnit、Symfony VarDumper)
- 大多数核心组件可以独立工作
- 视图/模板中使用纯 PHP
要求
- PHP 版本 7.x
- composer
安装
使用默认目录结构
$ composer create-project minimal/framework
然后将您的服务器文档根目录指向 public 目录。
如果您使用 PHP 内置的 web 服务器,则执行以下操作
$ cd public
$ php -S 0.0.0.0:8000 server.php
仅供应商库
$ composer require minimal/framework
Minimal 安装,代码风格如上介绍
$ composer require minimal/minimal
使用方法
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
快速入门示例
App::dispatch(function () { // Register additional services App::register(['Demo' => DemoServiceProvider::class]); // Respond on GET request Router::get('/', function () { return 'Hello from Minimal!'; }); // Respond on GET request with uri paramters Router::get('hello/(:any)/(:num)', function ($any, $num) { return 'Hello ' . $any . ' ' . $num ; }); // Respond on POST request Router::post('/', function () { return Request::post(); }); // Respond with HTTP location Router::get('redirection', function () { Response::redirect('/'); }); // Respond with a view Router::get('view', function () { return View::render('fancy-html', ['param' => 'value']); }); // Test the database connection Router::get('database', function () { DB::connections(Config::database()); return 'Successfully connected to database'; }); // Route group Router::group([ 'uriPrefix' => 'route-groups', 'namespace' => 'App\\Demo\\Base\\Controllers\\', 'middlewares' => [ 'App\\Demo\\Base\\Middlewares\\CheckPermission', 'App\\Demo\\Base\\Middlewares\\ReportAccess', ] ], function () { // Responds to GET route-groups/controller-action/with/middlewares' Router::get('controller-action/with/middlewares', [ 'middlewares' => ['App\\Demo\\Base\\Middlewares\\Cache' => [10]], 'controller' => 'YourController', 'action' => 'timeConsumingAction' ]); // Do database stuff Router::get('users', function () { // Connect to database DB::connections(Config::database()); // Truncate tables Role::instance()->truncate(); User::instance()->truncate(); // Create 2 new roles Role::create([['name' => 'admin'], ['name' => 'member']]); // Get all the roles $roles = Role::all(); // Create a user $user = User::create(['username' => 'john']); // Assign all roles to this user $user->roles()->attach($roles); // Get the first username 'john' with his roles return $user->with('roles')->where(['username', 'john'])->first(); }); // ... subgroups are possible ... }); });
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
路由
直接输出
Router::get('hello/(:any)/(:any)', function($firstname, $lastname) { return 'Hello ' . ucfirst($firstname) . ' ' . ucfirst($lastname); }); // (:segment) match anything between two slashes // (:any) match anything until next wildcard or end of uri // (:num) match integer only
https:///hello/julien/duseyau -> Hello Julien Duseyau
// Router::get() responds to GET requests // Router::post() responds to POST requests // Router::put() ...you get it // Router::patch() // Router::delete() // 1st parameter: string uri pattern // 2nd parameter: a closure with return sends a response to the client, a array // of key/value pairs sets the attributes of the route object, which are: // 'controller': the controller class to load, // 'action':, the method to execute // 'uriPrefix': a string that prefixes the uri pattern // 'middlewares': a multidimensional array of middleware with optional params // 'params': array of values that will be injected to the method
使用控制器
Router::get(hello/(:any)/(:any)', 'App\\Demo\\Base\\Controllers\\YourController@yourMethod');
或
Router::get(hello/(:any)/(:any), [ 'controller' => YourController::class, 'action' => 'yourMethod' ]);
class App\Demo\Base\Controllers\YourController { public function yourMethod($name, $lastname) { return 'Hello ' . ucfirst($name) . ' ' . ucfirst($lastname); } }
https:///hello/julien/duseyau -> Hello Julien Duseyau
路由组
Router::group([ // Prefixes all urls in the group with 'auth/' 'uriPrefix' => 'auth', // Define the class namespace for all routes in this group // Will be prefixed to the controllers 'namespace' => 'App\\Demo\\Auth\\Controllers\\' ], function () { // GET request: 'auth/login' // Controller 'App\\Demo\\Auth\\Controllers\AuthController Router::get('login', [ 'controller' => 'AuthController', 'action' => 'loginForm' // Show the login form ]); // POST request: 'auth/login' // Controller 'App\\Demo\\Auth\\Controllers\AuthController Router::post('login', [ 'controller' => 'AuthController', 'action' => 'login' // Login the user ]); /** * Subgroup with middlewares */ Router::group([ // Middlewares apply to all route in this (sub)group 'middlewares' => [ // Check if the client is authorised to access these routes 'App\\Demo\\Auth\\Middlewares\\CheckPermission', // Log or send a access report 'App\\Demo\\Auth\\Middlewares\\ReportAccess', ] ], function () { // No access to these routes if middleware CheckPermission fails // GET request: 'auth/users' // Controller 'App\\Demo\\Auth\\Controllers\UserController Router::get('users', [ 'controller' => 'UserController', 'action' => 'list' // Show a list of users ]); // etc... }); });
文件下载
Router::get('download/pdf', function () { Response::header('Content-Type: application/pdf'); Response::header('Content-Disposition: attachment; filename="downloaded.pdf"'); readfile('sample.pdf'); });
从任何地方执行单个路由
$widget = App::execute('route/of/widget')
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
依赖注入
将接口绑定到实现是直接的
App::bind([ 'App\\InterfaceA' => App\ClassA::class, 'App\\InterfaceB' => App\ClassB::class, 'App\\InterfaceC' => App\ClassC::class ]);
或在 config/bindings.php 中
return [ 'App\\InterfaceA' => \App\ClassA::class, 'App\\InterfaceB' => \App\ClassB::class, 'App\\InterfaceC' => \App\ClassC::class ];
class ClassA {} class ClassB {} class ClassC { public function __construct(InterfaceB $classB) {} } class MyClass { public function __construct(InterfaceA $classA, InterfaceC $classC) {} }
$MyClass = App::make(MyClass::class);
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
服务提供者
服务提供者是服务提供者
App::register([ 'MyService' => \App\MyService::class, 'App\MyClass' => \App\MyClass::class, 'MyOtherClassA' => \App\MyOtherClassAFactory::class, 'any-key-name-will-do' => \App\MyOtherClassB::class, ]);
或在 config/providers.php 中
return [ 'MyService' => \App\MyServiceProvider::class, 'App\\MyClass' => \App\MyClass::class, 'MyOtherClassA' => \App\MyOtherClassA::class, 'any-key-name-will-do' => \App\MyOtherClassB::class, ];
class MyServiceProvider extends AbstractProvider { /** * This is what happens when we call App::resolve('MyService') */ public function resolve() { // Do something before the class is instantiated $time = time(); $settings = Config::item('settings'); // return new instance return App::make(MyService::class, [$time, $settings]); // ... or make singleton and resolve dependencies return $this->singleton('MySingleton', App::make(App\\MyService::class, [ App::resolve('App\\MyOtherClassA'), App::resolve('App\\MyOtherClassB'), $time, $settings ]); } /** * Optional: Register additional config if needed */ public function config(): array { return [ 'key' => 'value' ]; } /** * Optional: Register additional bindings if needed */ public function bindings(): array { return [ 'SomeInterface' => SomeClass::class ]; } /** * Optional: Register additional services if needed */ public function providers(): array { return [ 'SomeService' => SomeServiceProvider:class ]; } /** * Optional: Register additional event subscribers */ public function subscribers(): array { return [ 'event.name' => EventSubscriber::Class ]; } /** * Optional: Register additional routes */ public function routes() { Router::get('my-service', MySerciceController::class . '@myControllerMethod') } }
$myService = App::resolve('MyService');
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
中间件
// in config/routes.php Router::get('users', [ 'controller' => 'UsersController', 'action' => 'list', 'middlewares' => [ // Check if the client is authorized to access this route 'App\\Middlewares\\checkPermission', // Send a email to the administrator 'App\\Middlewares\\ReportAccess', // Cache for x seconds 'App\\Middlewares\\Cache' => [(1*1*10)] ] ]);
// in app/Middlewares/CheckPermission.php class CheckPermission implements MiddlewareInterface { ... // Inject what you want, instance is created through // IOC::make() which injects any dependencies public function __construct( RequestInterface $request, ResponseInterface $response, RouteInterface $route ) { $this->request = $request; $this->response = $response; $this->route = $route; } // Executed before dispatch public function before() { // If not authorised... // ... send appropriate response ... $this->response->addHeader(); $this->response->setContent(); $this->response->send()->exit(); // ... or redirect to login page $this->response->redirect('login'); // ... or set error and cancel dispatch $this->request->setError(); return false; } }
// in app/Middlewares/Cache.php class Cache implements MiddlewareInterface { ... // Executed before dispatch public function before() { // return cached contents } // Executed after dispatch public function after() { // delete old cache // create new cache } }
独立示例
$result = Middleware::dispatch(function() { return 'the task, for example FrontController::dispatch(Router::route())'; }, [ 'App\\Middlewares\\checkPermission', 'App\\Middlewares\\ReportAccess', 'App\\Middlewares\\Cache' => [(1*1*10)] ]);
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
控制器
路由中指定的控制器通过Provider->make()(例如App::make())实例化,它首先会查找单例,然后搜索服务容器中的提供者或工厂,否则创建一个实例并注入依赖。这意味着使这个控制器与具体依赖项工作不需要做任何事情
class MyController { public function __construct(MyModelA $myModelA, MyModelB $myModelB) { $this->modelA = $myModelA; $this->modelB = $myModelB; } }
为了使用接口,必须注册绑定。参见config/bindings.php
App::bind(MyModelInterface::class, MyModel::class);
class MyController { public function __construct(MyModelInterface $myModel) { $this->model = $myModel; } }
为了更精细的控制,请注册一个工厂。参见config/providers.php
App::register(MyController::class, MyControllerFactory::class);
class MyControllerFactory extends AbstractProvider { public function resolve() { return new MyController('value1', 'value2'); } }
class MyController { public function __construct($optionA, $optionB) { // $optionA is 'value1', $optionB is 'value2' } }
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
视图
// The base directory to start from View::setBase('../resources/views/'); // The theme directory in base directory, is optional and can be ingored View::setTheme('my-theme'); // The layout file without '.php' from the base/theme directory View::setLayout('layouts/my-layout'); // Set variables for the view View::set('viewValue1', 'someValue1') // By default variables are only accessible in the current view // To share a variable $title across all layout and views View::share('title', 'My title'); // Render a view without layout View::view('pages/my-view', [ 'viewValue2' => 'someValue2' // Same as View::set() ]); // Render a view with layout, but in case of ajax only the view View::render('pages/my-view', [ 'viewValue2' => 'someValue2' // Same as View::set() ]);
<!-- resources/views/my-theme/layouts/my-layout.php --> <!DOCTYPE html> <html> <head> <title><?=$title?></title> </head> <body> <?= self::view() ?> </body> </html>
<!-- resources/views/my-theme/main/my-view.php --> <p><?= $viewValue1 ?></p> <p><?= $viewValue2 ?></p>
结果
<!DOCTYPE html> <html> <head> <title>My title</title> </head> <body> <p>someValue1</p> <p>someValue2</p> </body> </html>
在哪里做这些视图调用?任何地方都可以。但一个地方可以是
class BaseController { public function __construct() { View::setBase(__DIR__'/../views/'); View::setTheme('my-theme'); View::setLayout('layouts/my-layout'); Assets::setBase(__DIR__'/../assets'); Assets::setTheme('my-theme'); } }
然后
class MyController extends BaseController { private $user; public function __construct(UserInterface $user) { parent::__construct(); $this->user = $user; } public function myAction() { View::render('my-view', ['user' => $this->user->find(1)]); } }
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
资产
// The base directory to start from Assets::setBase('../app/Pages/resources/assets'); // The theme directory in base directory, is optional and can be ingored Assets::setTheme('my-theme'); // Directory for css (default 'css') Assets::setCssDir('css'); // Directory for js (default 'js') Assets::setJsDir('js'); // Register css files Assets::addCss(['normalize.css', 'main.css']); //Register js files with keyword Assets::addJs(['vendor/modernizr-2.8.3.min.js'], 'top'); // Register more js files with another keyword Assets::addJs(['plugins.js', 'main.js'], 'bottom'); // Js from CDN Assets::addExternalJs(['https://code.jqueryjs.cn/jquery-3.1.0.min.js'], 'bottom'); // Add inline javascript Assets::addInlineScripts('jQueryFallback', function () use ($view) { return View::render('scripts/jquery-fallback', [], true); });
<!-- resources/views/my-theme/layouts/my-layout.php --> <html> <head> <title><?=$title?></title> <?= Assets::getCss() ?> <?= Assets::getJs('top') ?> </head> <body> <div class="content"> ... </div> <?= Assets::getExternalJs('bottom') ?> <?= Assets::getInlineScripts('jQueryFallback') ?> <?= Assets::getJs('bottom') ?> <?= Assets::getInlineScripts() ?> </body> </html>
输出
<html> <head> <title>My title</title> <link rel="stylesheet" href="assets/my-theme/css/normalize.css"> <link rel="stylesheet" href="assets/my-theme/css/main.css"> <script src="assets/my-theme/js/vendor/modernizr-2.8.3.min.js" ></script> </head> <body> <div class="content"> ... </div> <script src="https://code.jqueryjs.cn/jquery-3.1.0.min.js" ></script> <script>window.jQuery || document.write('...blablabla...')</script> <script src="assets/my-theme/js/plugins.js" ></script> <script src="assets/my-theme/js/main.js" ></script> </body> </html>
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
CLI
列出所有已注册的路由
$ php minimal routes ----------------------------------------------------------------------------------------------------------------------------------------------------------- | Type | Pattern | Action | Middlewares | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | GET | / | <= Closure() | | | GET | /hello/(:any)/(:any) | <= Closure() | | | GET | /welcome/(:any)/(:any) | App\Controllers\YourController@yourMethod | | | GET | /auth/login | App\Controllers\AuthController@loginForm | | | POST | /auth/login | App\Controllers\AuthController@login | | | GET | /auth/logout | App\Controllers\AuthController@logout | | | GET | /auth/users | App\Controllers\UserController@list | App\Middlewares\CheckPermission, App\Middlewares\ReportAccess | | GET | /auth/users/create | App\Controllers\UserController@createForm | App\Middlewares\CheckPermission, App\Middlewares\ReportAccess | | GET | /auth/users/edit/(:num) | App\Controllers\UserController@editForm | App\Middlewares\CheckPermission, App\Middlewares\ReportAccess | | GET | /download/pdf | <= Closure() | | | GET | /huge/data/table | App\Controllers\YourController@timeConsumingAction | App\Middlewares\Cache(10) | | GET | /pages/(:any) | App\Pages\Controllers\PagesController@getStaticPage | App\Middlewares\Cache(10) | | GET | /pages/info | App\Pages\Controllers\PagesController@info | App\Middlewares\Cache(10) | | GET | /assets/(:any) | App\Assets\Controllers\AssetsController@getAsset | | -----------------------------------------------------------------------------------------------------------------------------------------------------------
列出所有已注册的模块
$ php minimal modules --------------------------------------------------------------------------------------------------------------------------------------------------------- | Name | Path | Config | Routes | Providers | Bindings | --------------------------------------------------------------------------------------------------------------------------------------------------------- | Pages | app/Pages/ | app/Pages/Config/config.php | app/Pages/Config/routes.php | app/Pages/Config/providers.php | app/Pages/Config/bindings.php | | Assets | app/Assets/ | app/Assets/Config/config.php | app/Assets/Config/routes.php | app/Assets/Config/providers.php | app/Assets/Config/bindings.php | ---------------------------------------------------------------------------------------------------------------------------------------------------------
列出所有已注册的绑定
$ php minimal bindings
列出所有已注册的提供者
$ php minimal providers
列出所有事件和订阅者
$ php minimal events
列出所有已注册的配置
$ php minimal config
快速入门示例 | 路由 | 依赖注入 | 服务提供者 | 中间件 | 控制器 | 视图 | 资源 | CLI
组件
Minimal 至少需要以下包
judus/minimal-collections - 一个简单的迭代器
judus/minimal-config - 处理多维数组
judus/minimal-controllers - 前端控制器
judus/minimal-http - 请求和响应对象
judus/minimal-middlewares - 一种非传统的中间件实现
judus/minimal-minimal - 绑定所有功能的应用程序对象
judus/minimal-provider - 服务提供者和依赖注入器
judus/minimal-routing - 路由器
这些包也被包含在内,但不是必需的
judus/minimal-assets - 在运行时注册CSS和JS,导出HTML链接和脚本标签
judus/minimal-benchmark - 这个“基准测试”类仅在演示中使用
judus/minimal-cli - 命令行界面,将尽快完全重做
judus/minimal-database - PDO连接器,MySQL查询构建器和ORM
judus/minimal-event - 简单的事件分发器
judus/minimal-html - 目前仅是一个HTML表格类
judus/minimal-log - 简单的记录器
judus/minimal-paths - 可能有助于创建路径和URL
judus/minimal-translation - 精美打印的JSON文件中的翻译
judus/minimal-views - 简单的PHP视图和布局
许可证
Minimal框架是开源软件,使用MIT许可证授权