DIGHT เป็นกรอบ PHP น้ำหนักเบา สร้างเว็บแอปพลิเคชันที่มีประสิทธิภาพสูงได้อย่างง่ายดายและรวดเร็ว การกำหนดเส้นทางนอกกรอบฐานข้อมูลการแคชการจัดการข้อผิดพลาดการบันทึกและห้องสมุดการจัดตารางงาน มุ่งเน้นไปที่การสร้างโซลูชันสำหรับกระบวนการหลักของเว็บแอปพลิเคชัน ให้เรียบง่ายและขยายได้
| โครงการ | คำอธิบาย |
|---|---|
| ลง | เฟรมเวิร์กพื้นฐานการกำหนดเส้นทางในตัวฐานข้อมูลการแคช ฯลฯ |
| ติดกัน | ส่วนขยายของผู้ดูแลระบบเต็มรูปแบบตามไฟ ไม่จำเป็นต้องมีการเข้ารหัสส่วนหน้า |
| ลงโครงการ | เทมเพลตสำหรับผู้เริ่มต้นในการสร้างเว็บแอปพลิเคชันได้อย่างง่ายดายโดย 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 จะถูกนำเข้าจากไฟล์ '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 ' );หากคุณต้องการเรียกใช้รหัสทั่วไปก่อนที่ตัวจัดการเส้นทาง
// 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 );ไฟล์: แอพ/บริการ/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 โดยเว็บไซต์บุคคลที่สาม (หรือโครงการของคุณมีหลายโดเมน) คุณต้องส่งชุดส่วนหัว CORS ด้วยเหตุผลเฉพาะโปรดดูที่: เอกสาร Mozilla
// 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
การกำหนดค่า 'ฐานข้อมูล' ไปยัง 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 สำหรับรายละเอียดการใช้งาน
DIGHT รองรับไดรเวอร์แคชหลายตัวและอินเทอร์เฟซแคชหลายตัวด้วย 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 หรือ Redis สำหรับการใช้การแคชขั้นสูง:
$ memcached = Alight Cache:: memcached ( ' memcached ' );
$ memcached -> increment ( ' increment ' );
$ redis = Alight Cache:: redis ( ' redis ' );
$ redis -> lPush ( ' list ' , ' first ' );Symfony/Cache รองรับอะแดปเตอร์มากกว่า 10 ตัว แต่เรามีการใช้งานในตัว 3 ในตัวเช่นระบบไฟล์, Memcached, Redis หากคุณต้องการอะแดปเตอร์เพิ่มเติมคุณสามารถขยายได้ ตัวอย่างเช่น:
ไฟล์: config/app.php
<?php
return [
' app ' => [
' cacheAdapter ' => [ svc Cache::class, ' adapter ' ],
],
' cache ' => [
// ...
' apcu ' => [
' type ' => ' apcu '
],
' array ' => [
' type ' => ' array ' ,
' defaultLifetime ' => 3600
]
]
];ไฟล์: แอพ/บริการ/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 Cache Component สำหรับข้อมูลเพิ่มเติม
การจางหายไปทุกข้อผิดพลาดผ่าน AlightApp::start() เมื่อเปิด 'debug' ในการกำหนดค่าแอปข้อผิดพลาดจะถูกส่งออกใน HTML สวย (โดย FILP/WHOOPS ) หรือ JSON
ไฟล์: config/app.php
<?php
return [
' app ' => [
' debug ' => true ,
]
];เมื่อปิด 'debug' ในสภาพแวดล้อมการผลิตลงเพียงบันทึกข้อผิดพลาดไปยังสถานะไฟล์และเอาต์พุต HTTP คุณสามารถแทนที่พฤติกรรมเริ่มต้นเหล่านี้โดยการกำหนดค่าแอป ตัวอย่างเช่น:
ไฟล์: config/app.php
<?php
return [
' app ' => [
' errorHandler ' => [ svc Error::class, ' catch ' ],
' errorPageHandler ' => [ svc Error::class, ' page ' ],
]
];ไฟล์: แอพ/บริการ/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
]); ให้ AlightResponse::api() เพื่อสร้างมาตรฐานรูปแบบของการตอบสนอง 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": {}
// } ให้ AlightResponse::render() เพื่อแสดงเทมเพลตมุมมองเรียกใช้วิธีการเรนเดอร์ด้วยพา ธ ของไฟล์เทมเพลตและข้อมูลเทมเพลตเสริม:
ไฟล์: แอพ/คอนโทรลเลอร์/pages.php
namespace ctr ;
class Pages
{
public static function index ()
{
Alight Response:: render ( ' hello.php ' , [ ' name ' => ' Ben ' ]);
}
}ไฟล์: แอป/ดู/hello.php
<h1>Hello, <?= $ name ?> !</h1>ไฟล์: config/route/web.php
Alight Route:: get ( ' / ' , [ ctr Pages::class, ' index ' ]);เอาท์พุทหน้าแรกของโครงการจะเป็น:
Hello, Ben!นอกจากนี้ยังมีผู้ช่วยที่มีประโยชน์บางคนวางไว้ในเนมสเปซที่แตกต่างกัน กรุณาคลิกไฟล์เพื่อดูรายละเอียด:
| เนมสเปซ | ไฟล์ |
|---|---|
| ลง คำขอ | request.php |
| ลง response | response.php |
| ลง ยูทิลิตี้ | Utility.php |