Alight는 가벼운 PHP 프레임 워크입니다. 고성능 편안한 웹 응용 프로그램을 쉽고 빠르게 구축합니다. 기본 내장 라우팅, 데이터베이스, 캐싱, 오류 처리, 로깅 및 작업 예약 라이브러리. 웹 애플리케이션의 핵심 프로세스를위한 솔루션 작성에 중점을 둡니다. 단순하고 확장 가능하게 유지하십시오.
| 프로젝트 | 설명 |
|---|---|
| 불타고 | 기본 프레임 워크 내장 라우팅, 데이터베이스, 캐싱 등 |
| Alight-Admin | Alight를 기반으로 한 완전한 관리자 패널 확장. 프론트 엔드 코딩이 필요하지 않습니다. |
| Alight-Project | 초보자가 Alight/Alight-Admin을 통해 웹 애플리케이션을 쉽게 만들 수있는 템플릿. |
PHP 7.4+
작곡가가 없습니까? 먼저 작곡가를 설치하십시오.
$ composer create-project juneszh/alight-project {PROJECT_DIRECTORY}프로젝트 템플릿에는 MVC 패턴에 적합한 공통 폴더 구조가 포함되어 있습니다. Alight-Project를 참조하십시오.
구성을 수정하여 폴더를 사용자 정의 할 수 있습니다. 그러나 다음 튜토리얼은 템플릿 구성을 기반으로합니다.
Nginx 예제 (Nginx 1.17.10, Php 7.4.3, Ubuntu 20.04.3) :
server {
listen 80 ;
listen [::]:80;
root /var/www/{PROJECT_DIRECTORY}/public;
index index.php;
server_name {YOUR_DOMAIN};
location / {
try_files $uri $uri / /index.php? $query_string ;
}
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
}Alight Framework의 모든 구성 옵션은 'config/app.php'파일에서 가져 오며 직접 작성해야합니다. 예를 들어:
파일 : config/app.php
<?php
return [
' app ' => [
' debug ' => false ,
' timezone ' => ' Europe/Kiev ' ,
' storagePath ' => ' storage ' ,
' domainLevel ' => 2 ,
' corsDomain ' => null ,
' corsHeaders ' => null ,
' corsMethods ' => null ,
' cacheAdapter ' => null ,
' errorHandler ' => null ,
' errorPageHandler ' => null ,
],
' route ' => ' config/route/web.php ' ,
' database ' => [
' type ' => ' mysql ' ,
' host ' => ' 127.0.0.1 ' ,
' database ' => ' alight ' ,
' username ' => ' root ' ,
' password ' => '' ,
],
' cache ' => [
' type ' => ' file ' ,
],
' job ' => ' config/job.php ' ,
]; <?php
Alight Config:: get ( ' app ' );
Alight Config:: get ( ' app ' , ' storagePath ' );자세한 내용은 config.php를 참조하십시오.
라우팅 규칙을 배우기 전에 먼저 라우팅 규칙을 저장하는 PHP 파일을 작성해야합니다. 라우팅 캐시가 업데이트되었는지 여부에 관계없이 라우팅 파일의 수정 시간을 기준으로합니다. 예를 들어:
파일 : config/route/web.php
Alight Route:: get ( ' / ' , ' Controller::index ' );파일 : config/app.php
<?php
return [
' route ' => ' config/route/web.php '
// Also supports multiple files
// 'route' => ['config/route/web.php', config/route/api.php']
];그건 그렇고, 경로 구성은 하위 도메인에 대한 지정된 파일 가져 오기를 지원합니다.
<?php
return [
' route ' => [
//Import on any request
' * ' => ' config/route/web.php ' ,
//Import when requesting admin.yourdomain.com
' admin ' => ' config/route/admin.php ' ,
//Import multiple files when requesting api.yourdomain.com
' api ' => [ ' config/route/api.php ' , ' config/route/api_mobile.php ' ],
]
]; Alight Route:: get ( $ pattern , $ handler );
// Example
Alight Route:: get ( ' / ' , ' Controller::index ' );
Alight Route:: get ( ' / ' , [ ' Controller ' , ' index ' ]);
// Or try this to easy trigger hints from IDE
Alight Route:: get ( ' / ' , [Controller::class, ' index ' ]);
// With default args
Alight Route:: get ( ' post/list[/{page}] ' , [Controller::class, ' list ' ], [ ' page ' => 1 ]);
// Common HTTP request methods
Alight Route:: options ( ' / ' , ' handler ' );
Alight Route:: head ( ' / ' , ' handler ' );
Alight Route:: post ( ' / ' , ' handler ' );
Alight Route:: delete ( ' / ' , ' handler ' );
Alight Route:: put ( ' / ' , ' handler ' );
Alight Route:: patch ( ' / ' , ' handler ' );
// Map for Custom methods
Alight Route:: map ([ ' GET ' , ' POST ' ], ' test ' , ' handler ' );
// Any for all common methods
Alight Route:: any ( ' test ' , ' handler ' ); // Matches /user/42, but not /user/xyz
Alight Route:: get ( ' user/{id:d+} ' , ' handler ' );
// Matches /user/foobar, but not /user/foo/bar
Alight Route:: get ( ' user/{name} ' , ' handler ' );
// Matches /user/foo/bar as well, using wildcards
Alight Route:: get ( ' user/{name:.+} ' , ' handler ' );
// The /{name} suffix is optional
Alight Route:: get ( ' user[/{name}] ' , ' handler ' );
// Root wildcards for single page app
Alight Route:: get ( ' /{path:.*} ' , ' handler ' );Nikic/Fast-Route는 라우팅 경로에서 모든 정규식을 처리합니다. 자세한 내용은 Fastroute 사용을 참조하십시오.
Alight Route:: group ( ' admin ' );
// Matches /admin/role/list
Alight Route:: get ( ' role/list ' , ' handler ' );
// Matches /admin/role/info
Alight Route:: get ( ' role/info ' , ' handler ' );
// Override the group
Alight Route:: group ( ' api ' );
// Matches /api/news/list
Alight Route:: get ( ' news/list ' , ' handler ' ); AlightRoute::any() 에 포함 된 메소드를 사용자 정의 할 수 있습니다.
Alight Route:: setAnyMethods ([ ' GET ' , ' POST ' ]);
Alight Route:: any ( ' only/get/and/post ' , ' handler ' );Route의 처리기 전에 공통 코드를 실행하려는 경우.
// For example log every hit request
Alight Route:: beforeHandler ([ svc Request::class, ' log ' ]);
Alight Route:: get ( ' test ' , ' handler ' );
Alight Route:: post ( ' test ' , ' handler ' );권장하지는 않지만 코드가 필요한 경우 :
// Effective in the current route file
Alight Route:: disableCache (); 모든 라우팅 옵션은 현재 파일에서만 적용되며 다음 파일을 가져 오기 전에 AlightRoute::init() 에 의해 자동 재설정됩니다. 예를 들어:
파일 : config/admin.php
Alight Route:: group ( ' admin ' );
Alight Route:: setAnyMethods ([ ' GET ' , ' POST ' ]);
// Matches '/admin/login' by methods 'GET', 'POST'
Alight Route:: any ( ' login ' , ' handler ' );파일 : config/web.php
// Matches '/login' by methods 'GET', 'POST', 'PUT', 'DELETE', etc
Alight Route:: any ( ' login ' , ' handler ' );수정되지 않은 데이터에 대한 액세스 속도를 최적화하기 위해 브라우저 및 공유 캐시 (CDN)의 캐싱을 제어하기 위해 캐시 제어 헤더를 보내십시오.
// Cache one day
Alight Route:: get ( ' about/us ' , ' handler ' )-> cache ( 86400 );
// Or force disable cache
Alight Route:: put ( ' user/info ' , ' handler ' )-> cache ( 0 );사용자 로그인 상태를 관리하기 위해 간단한 권한 부여 처리기를 제공합니다.
// Define a global authorization verification handler
Alight Route:: authHandler ([ svc Auth::class, ' verify ' ]);
// Enable verification in routes
Alight Route:: get ( ' user/info ' , ' handler ' )-> auth ();
Alight Route:: get ( ' user/password ' , ' handler ' )-> auth ();
// No verification by default
Alight Route:: get ( ' about/us ' , ' handler ' );
// In general, routing with authorization will not use browser cache
// So auth() has built-in cache(0) to force disable cache
// Please add cache(n) after auth() to override the configuration if you need
Alight Route:: get ( ' user/rank/list ' , ' handler ' )-> auth ()-> cache ( 3600 );파일 : app/service/auth.php
namespace svc ;
class Auth
{
public static function verify ()
{
// Some codes about get user session from cookie or anywhere
// Returns the user id if authorization is valid
// Otherwise returns 0 or something else for failure
// Then use Router::getAuthId() in the route handler to get this id again
return $ userId ;
}
}사용자가 제출 한 데이터는 여러 번 처리하는 데 시간이 걸리며 처리되기 전에 동일한 데이터를 수신하고 싶지 않습니다. 따라서 요청 재사용 대기 시간을 설정해야합니다. 쿨 다운 내에서 다시 요청할 때 사용자는 429 오류를 받게됩니다.
// Cooldown only takes effect when authorized
Alight Route:: put ( ' user/info ' , ' handler ' )-> auth ()-> cd ( 2 );
Alight Route:: post ( ' user/status ' , ' handler ' )-> auth ()-> cd ( 2 );API가 타사 웹 사이트 (또는 프로젝트에 여러 도메인이 있음)의 AJAX 요청에 API를 사용해야하는 경우 CORS 헤더 세트를 보내야합니다. 특정한 이유로 Mozilla Docs를 참조하십시오.
// Domains in config will receive the common cors header
Alight Route:: put ( ' share/config ' , ' handler ' )-> cors ();
// The specified domain will receive the common cors header
Alight Route:: put ( ' share/specified ' , ' handler ' )-> cors ( ' abc.com ' );
// The specified domain will receive the specified cors header
Alight Route:: put ( ' share/specified2 ' , ' handler ' )-> cors ( ' abc.com ' , ' Authorization ' , [ ' GET ' , ' POST ' ]);
// All domains will receive a 'Access-Control-Allow-Origin: *' header
Alight Route:: put ( ' share/all/http ' , ' handler ' )-> cors ( ' * ' );
// All domains will receive a 'Access-Control-Allow-Origin: [From Origin]' header
Alight Route:: put ( ' share/all/https ' , ' handler ' )-> cors ( ' origin ' );귀하의 웹 사이트에서 CDN을 사용하는 경우이 유틸리티를주의 깊게 사용하십시오. 헤더가 CDN에 의해 캐시 된 후에 요청 실패를 피하기 위해.
Alight는 '데이터베이스'구성을 Catfan/Medoo 에 직접 전달합니다. 특정 구성 옵션은 Medoo 시작을 참조하십시오. 예를 들어:
파일 : config/app.php
<?php
return [
' database ' => [
' type ' => ' mysql ' ,
' host ' => ' 127.0.0.1 ' ,
' database ' => ' alight ' ,
' username ' => ' root ' ,
' password ' => '' ,
],
// Multiple databases (The first database is default)
// 'database' => [
// 'main' => [
// 'type' => 'mysql',
// 'host' => '127.0.0.1',
// 'database' => 'alight',
// 'username' => 'root',
// 'password' => '',
// ],
// 'remote' => [
// 'type' => 'mysql',
// 'host' => '1.1.1.1',
// 'database' => 'alight',
// 'username' => 'root',
// 'password' => '',
// ],
// ]
]; AlightDatabase::init() 는 new MedooMedoo() 의 정적 및 단일 인스턴스 구현이므로 Medoo() 의 모든 기능을 상속합니다. 단일 인스턴스는 각 요청이 데이터베이스에 한 번만 연결되어 재사용하여 데이터베이스 연결 수를 효과적으로 줄입니다.
// Initializes the default database
$ db = Alight Database:: init ();
// Initializes others database with key
$ db2 = Alight Database:: init ( ' remote ' );
$ userList = $ db -> select ( ' user ' , ' * ' , [ ' role ' => 1 ]);
$ userInfo = $ db -> get ( ' user ' , ' * ' , [ ' id ' => 1 ]);
$ db -> insert ( ' user ' , [ ' name ' => ' anonymous ' , ' role ' => 2 ]);
$ id = $ db -> id ();
$ result = $ db -> update ( ' user ' , [ ' name ' => ' alight ' ], [ ' id ' => $ id ]);
$ result -> rowCount ();사용법 세부 사항은 Medoo 문서를 참조하십시오.
Alight는 Symfony/Cache 와 함께 여러 캐시 드라이버 및 여러 캐시 인터페이스를 지원합니다. 구성 옵션 'DSN'및 '옵션'은 캐시 어댑터로 전달됩니다. 자세한 내용은 사용 가능한 캐시 어댑터를 참조하십시오. 예를 들어:
파일 : config/app.php
<?php
return [
' cache ' => [
' type ' => ' file ' ,
],
// Multiple cache (The first cache is the default)
// 'cache' => [
// 'file' => [
// 'type' => 'file',
// ],
// 'memcached' => [
// 'type' => 'memcached',
// 'dsn' => 'memcached://localhost',
// 'options' => [],
// ],
// 'redis' => [
// 'type' => 'redis',
// 'dsn' => 'redis://localhost',
// 'options' => [],
// ],
// ]
]; 데이터베이스와 마찬가지로 AlightCache::init() 동시 요청 성능을 향상시키기 위해 캐시 클라이언트의 정적 및 단일 인스턴스 구현입니다.
// Initializes the default cache
$ cache = Alight Cache:: init ();
// Initializes others cache with key
$ cache2 = Alight Cache:: init ( ' redis ' );
// Use SimpleCache(PSR-16) interface
if (! $ cache -> has ( ' test ' )){
$ cache -> set ( ' test ' , ' hello world! ' , 3600 );
}
$ cacheData = $ cache -> get ( ' test ' );
$ cache -> delete ( ' test ' ); $ cache6 = Alight Cache:: psr6 ( ' memcached ' );
$ cacheItem = $ cache6 -> getItem ( ' test ' );
if (! $ cacheItem -> isHit ()){
$ cacheItem -> expiresAfter ( 3600 );
$ cacheItem -> set ( ' hello world! ' );
// Bind to a tag
$ cacheItem -> tag ( ' alight ' );
}
$ cacheData = $ cacheItem -> get ();
$ cache6 -> deleteItem ( ' test ' );
// Delete all cached items in the same tag
$ cache6 -> invalidateTags ( ' alight ' )
// Or symfony/cache adapter style
$ cacheData = $ cache6 -> get ( ' test ' , function ( $ item ){
$ item -> expiresAfter ( 3600 );
return ' hello world! ' ;
});
$ cache6 -> delete ( ' test ' );고급 캐싱을 사용하기위한 멤버 또는 레 디스 네이티브 인터페이스도 지원합니다.
$ memcached = Alight Cache:: memcached ( ' memcached ' );
$ memcached -> increment ( ' increment ' );
$ redis = Alight Cache:: redis ( ' redis ' );
$ redis -> lPush ( ' list ' , ' first ' );Symfony/Cache는 10 개 이상의 어댑터를 지원하지만 파일 시스템, Memcached, Redis와 같이 일반적으로 사용되는 3 개만 내장되어 있습니다. 더 많은 어댑터가 필요한 경우 확장 할 수 있습니다. 예를 들어:
파일 : config/app.php
<?php
return [
' app ' => [
' cacheAdapter ' => [ svc Cache::class, ' adapter ' ],
],
' cache ' => [
// ...
' apcu ' => [
' type ' => ' apcu '
],
' array ' => [
' type ' => ' array ' ,
' defaultLifetime ' => 3600
]
]
];파일 : app/service/cache.php
namespace svc ;
use Symfony Component Cache Adapter ApcuAdapter ;
use Symfony Component Cache Adapter ArrayAdapter ;
use Symfony Component Cache Adapter NullAdapter ;
class Cache
{
public static function adapter ( array $ config )
{
switch ( $ config [ ' type ' ]) {
case ' apcu ' :
return new ApcuAdapter ();
break ;
case ' array ' :
return new ArrayAdapter ( $ config [ ' defaultLifetime ' ]);
default :
return new NullAdapter ();
break ;
}
}
}자세한 내용은 Symfony 캐시 구성 요소를 참조하십시오.
Alight는 AlightApp::start() 를 통해 모든 오류를 포착합니다. 앱 구성에서 '디버그'를 켜면 Pretty HTML ( Filp/Whoops ) 또는 JSON에서 오류가 출력됩니다.
파일 : config/app.php
<?php
return [
' app ' => [
' debug ' => true ,
]
];프로덕션 환경에서 '디버그'를 끄면 파일에 오류를 기록하고 HTTP 상태를 출력합니다. 앱 구성을 통해 이러한 기본 동작을 무시할 수 있습니다. 예를 들어:
파일 : config/app.php
<?php
return [
' app ' => [
' errorHandler ' => [ svc Error::class, ' catch ' ],
' errorPageHandler ' => [ svc Error::class, ' page ' ],
]
];파일 : app/service/error.php
namespace svc ;
class Error
{
public static function catch ( Throwable $ exception )
{
// Some code like sending an email or using Sentry or something
}
public static function page ( int $ status )
{
switch ( $ status ) {
case 400 :
// Page code...
break ;
case 401 :
// Page code...
break ;
case 403 :
// Page code...
break ;
case 404 :
// Page code...
break ;
case 500 :
// Page code...
break ;
default :
// Page code...
break ;
}
}
}배경에서 PHP 스크립트를 주기적으로 실행 해야하는 경우.
$ sudo contab -e다음 줄에 다음을 추가하십시오.
* * * * * sudo -u www-data /usr/bin/php /var/www/{PROJECT_DIRECTORY}/app/scheduler.php >> /dev/null 2>&1파일 : config/job.php
Alight Job:: call ( ' handler ' )-> minutely ();
Alight Job:: call ( ' handler ' )-> hourly ();
Alight Job:: call ( ' handler ' )-> daily ();
Alight Job:: call ( ' handler ' )-> weekly ();
Alight Job:: call ( ' handler ' )-> monthly ();
Alight Job:: call ( ' handler ' )-> yearly ();
Alight Job:: call ( ' handler ' )-> everyMinutes ( 5 );
Alight Job:: call ( ' handler ' )-> everyHours ( 2 );
Alight Job:: call ( ' handler ' )-> date ( ' 2022-08-02 22:00 ' );각 핸들러는 한 번에 하나의 프로세스 만 실행하며 프로세스의 기본 최대 런타임은 1 시간입니다. 핸들러에 더 긴 런타임이 필요한 경우 timelimit ()를 사용하십시오.
Alight Job:: call ( ' handler ' )-> hourly ()-> timeLimit ( 7200 ); // 7200 seconds Alight는 AlightApp::root() 제공하여 프로젝트에서 파일 경로의 형식을 표준화합니다.
// Suppose the absolute path of the project is /var/www/my_project/
Alight App:: root ( ' public/favicon.ico ' ); // /var/www/my_project/public/favicon.ico
// Of course, you can also use absolute path files with the first character '/'
Alight App:: root ( ' /var/data/config/web.php ' ); 구성의 파일 경로는 모두 AlightApp::root() 를 기반으로합니다. 예를 들어:
Alight App:: start ([
' route ' => ' config/route/web.php ' , // /var/www/my_project/config/route/web.php
' job ' => ' config/job.php ' // /var/www/my_project/config/job.php
]); Alight는 API 응답 형식을 표준화하기 위해 AlightResponse::api() 제공합니다.
HTTP 200 OK
{
" error " : 0 , // API error code
" message ": " OK ", // API status description
" data": {} // Object data
}상태 정의 :
| HTTP 상태 | API 오류 | 설명 |
|---|---|---|
| 200 | 0 | 좋아요 |
| 200 | 1xxx | 일반적인 비즈니스 오류는 사용자에게만 표시됩니다 |
| 200 | 2xxx | 특수 비즈니스 오류, 사용자에 대한 다음 조치를 정의해야합니다. |
| 4xx | 4xx | 클라이언트 오류 |
| 5xx | 5xx | 서버 오류 |
예를 들어:
Alight Response:: api ( 0 , null , [ ' name ' => ' alight ' ]);
// Response:
// HTTP 200 OK
//
// {
// "error": 0,
// "message": "OK",
// "data": {
// "name": "alight"
// }
// }
Alight Response:: api ( 1001 , ' Invalid request parameter. ' );
// Response:
// HTTP 200 OK
//
// {
// "error": 1001,
// "message": "Invalid request parameter.",
// "data": {}
// }
Alight Response:: api ( 500 , ' Unable to connect database. ' );
// Response:
// HTTP 500 Internal Server Error
//
// {
// "error": 500,
// "message": "Unable to connect database.",
// "data": {}
// } Alight는 AlightResponse::render() 제공하여보기 템플릿을 표시하려면 템플릿 파일 및 선택적 템플릿 데이터로 렌더 메소드를 호출합니다.
파일 : 앱/컨트롤러/pages.php
namespace ctr ;
class Pages
{
public static function index ()
{
Alight Response:: render ( ' hello.php ' , [ ' name ' => ' Ben ' ]);
}
}파일 : app/view/hello.php
<h1>Hello, <?= $ name ?> !</h1>파일 : config/route/web.php
Alight Route:: get ( ' / ' , [ ctr Pages::class, ' index ' ]);프로젝트의 홈페이지 출력은 다음과 같습니다.
Hello, Ben!다른 네임 스페이스에 유용한 도우미가 배치되어 있습니다. 자세한 내용은 파일을 클릭하십시오.
| 네임 스페이스 | 파일 |
|---|---|
| Alight 요청 | request.php |
| Alight Response | 응답 .php |
| Alight 유틸리티 | 유틸리티 .php |