Learn/flight_vs_laravel
Flight pret Laravel
Kas ir Laravel?
Laravel ir pilnvērtīga ietvara sistēma ar visiem zvaniņiem un svilpēm un pārsteidzošu izstrādātājiem veltītu ekosistēmu, bet ar izmaksām veiktspējā un sarežģītībā. Laravel mērķis ir nodrošināt izstrādātājam augstāko produktivitātes līmeni un padarīt izplatītās uzdevumus vieglus. Laravel ir lieliska izvēle izstrādātājiem, kuri vēlas izveidot pilnvērtīgu, uzņēmējdarbības līmeņa tīmekļa lietojumprogrammu. Tas nāk ar dažām kompromisiem, īpaši veiktspējas un sarežģītības ziņā. Laravel pamatu apguve var būt viegla, bet prasmju iegūšana ietvarā var prasīt zināmu laiku.
Ir arī tik daudz Laravel moduļu, ka izstrādātāji bieži jūtas, ka vienīgais veids, kā atrisināt problēmas, ir caur šiem moduļiem, kad patiesībā varētu izmantot citu bibliotēku vai uzrakstīt savu kodu.
Priekšrocības salīdzinājumā ar Flight
- Laravel ir milzīga ekosistēma izstrādātājiem un moduļiem, kas var tikt izmantoti, lai atrisinātu izplatītās problēmas.
- Laravel ir pilnvērtīga ORM, kas var tikt izmantota, lai mijiedarbotos ar jūsu datubāzi.
- Laravel ir traka daudzuma dokumentācija un apmācības, kas var tikt izmantotas, lai apgūtu ietvaru. Tas var būt labs, lai iedziļinātos sīkumos, vai slikts, jo ir tik daudz, ko izpētīt.
- Laravel ir iebūvēta autentifikācijas sistēma, kas var tikt izmantota, lai nodrošinātu jūsu lietojumprogrammas drošību.
- Laravel ir podkāsti, konferences, sanāksmes, video un citi resursi, kas var tikt izmantoti, lai apgūtu ietvaru.
- Laravel ir paredzēts pieredzējušam izstrādātājam, kurš vēlas izveidot pilnvērtīgu, uzņēmējdarbības līmeņa tīmekļa lietojumprogrammu.
Trūkumi salīdzinājumā ar Flight
- Laravel zem virsmas notiek daudz vairāk nekā Flight. Tas nāk ar drastiskām izmaksām veiktspējas ziņā. Skatiet TechEmpower testus papildus informācijai.
- Flight ir paredzēts izstrādātājam, kurš vēlas izveidot vieglu, ātru un viegli lietojamu tīmekļa lietojumprogrammu.
- Flight ir paredzēts vienkāršībai un vieglai lietošanai.
- Viena no Flight kodolfunkcijām ir tā, ka tā cenšas saglabāt atpakaļsavietojamību. Laravel rada lielu frustrāciju starp galvenajām versijām.
- Flight ir domāts izstrādātājiem, kuri pirmo reizi dodas ietvaru pasaulē.
- Flight nav atkarību, savukārt Laravel ir briesmīgs atkarību daudzums
- Flight var veikt arī uzņēmējdarbības līmeņa lietojumprogrammas, bet tam nav tik daudz sagatavota koda kā Laravel. Tas arī prasīs lielāku disciplīnu no izstrādātāja puses, lai uzturētu lietas organizētas un labi strukturētas.
- Flight dod izstrādātājam lielāku kontroli pār lietojumprogrammu, savukārt Laravel aizkulisēs ir daudz maģijas, kas var būt frustrējoša.
Learn/migrating_to_v3
Migrēšana uz v3
Atpakaļsaderība lielākoties ir saglabāta, bet ir daži izmaiņas, par kurām jums jāzina, migrējot no v2 uz v3. Ir daži izmaiņas, kas pārāk daudz nonāca pretrunā ar dizaina modeļiem, tāpēc bija jāveic dažas korekcijas.
Izvades buferizācijas uzvedība
v3.5.0
Izvades buferizācija ir process, kurā PHP skripta ģenerētais izvade tiek saglabāts buferī (iekšēji PHP), pirms tas tiek nosūtīts klientam. Tas ļauj modificēt izvadi pirms tās nosūtīšanas klientam.
MVC lietojumprogrammā Kontrolētājs ir "vadītājs" un tas pārvalda, ko dara skats. Ja izvade tiek ģenerēta ārpus kontrolētāja (vai Flight gadījumā dažreiz anonīma funkcija), tas pārkāpj MVC modeli. Šī izmaiņa ir lai būtu vairāk saskaņota ar MVC modeli un lai padarītu ietvaru paredzamāku un vieglāk lietojamu.
v2 versijā izvades buferizācija tika apstrādāta tā, ka tā konsekventi neaizvēra savu izvades buferi, kas apgrūtināja vienības testēšanu un straumēšanu. Lielākajai daļai lietotāju šī izmaiņa var pat nebūt ietekme uz jums. Tomēr, ja jūs izvadat saturu ārpus izsaucamajām funkcijām un kontrolētājiem (piemēram, āķī), visticamāk, saskarsieties ar problēmām. Izvades satura āķos un pirms ietvara faktiskās izpildes varēja darboties iepriekš, bet tas nedarbosies turpmāk.
Kur var rasties problēmas
// index.php
require 'vendor/autoload.php';
// tikai piemērs
define('START_TIME', microtime(true));
function hello() {
echo 'Hello World';
}
Flight::map('hello', 'hello');
Flight::after('hello', function(){
// tas faktiski būs kārtībā
echo '<p>This Hello World phrase was brought to you by the letter "H"</p>';
});
Flight::before('start', function(){
// tādas lietas izraisīs kļūdu
echo '<html><head><title>My Page</title></head><body>';
});
Flight::route('/', function(){
// tas faktiski ir kārtībā
echo 'Hello World';
// Arī šis vajadzētu būt kārtībā
Flight::hello();
});
Flight::after('start', function(){
// tas izraisīs kļūdu
echo '<div>Your page loaded in '.(microtime(true) - START_TIME).' seconds</div></body></html>';
});
Ieslēgšana v2 renderēšanas uzvedībai
Vai jūs joprojām varat saglabāt savu veco kodu tāpat, kā tas ir, bez pārstrādes, lai tas darbotos ar v3? Jā, varat! Jūs varat ieslēgt v2 renderēšanas uzvedību, iestatot konfigurācijas opciju flight.v2.output_buffering uz true. Tas ļaus jums turpināt izmantot veco renderēšanas uzvedību, bet ieteicams to labot turpmāk. v4 versijā ietvarā tas tiks noņemts.
// index.php
require 'vendor/autoload.php';
Flight::set('flight.v2.output_buffering', true);
Flight::before('start', function(){
// Tagad tas būs kārtībā
echo '<html><head><title>My Page</title></head><body>';
});
// vairāk koda
Dispatcher izmaiņas
v3.7.0
Ja jūs tieši esat izsaukuši statiskas metodes Dispatcher klasei, piemēram, Dispatcher::invokeMethod(), Dispatcher::execute() utt., jums būs jāatjaunina jūsu kods, lai tieši neizsauktu šīs metodes. Dispatcher ir pārveidots, lai būtu vairāk objektorientēts, tāpēc atkarību injekcijas konteineri var tikt izmantoti vieglāk. Ja jums jāizsauc metode līdzīgi kā to darīja Dispatcher, jūs varat manuāli izmantot kaut ko līdzīgu $result = $class->$method(...$params); vai call_user_func_array().
halt() stop() redirect() un error() izmaiņas
v3.10.0
Noklusētā uzvedība pirms 3.10.0 bija notīrīt gan galvenes, gan atbildes ķermeni. Tas tika mainīts, lai notīrītu tikai atbildes ķermeni. Ja jums jānotīra arī galvenes, jūs varat izmantot Flight::response()->clear().
Learn/configuration
Konfigurācija
Pārskats
Flight nodrošina vienkāršu veidu, kā konfigurēt dažādus sistēmas aspektus atbilstoši jūsu lietojumprogrammas vajadzībām. Daži iestatījumi ir noteikti pēc noklusējuma, bet tos var pārrakstīt pēc nepieciešamības. Varat arī iestatīt savus mainīgos, ko izmantot visā lietojumprogrammā.
Skaidra, slāņveida konfigurācija (failu noklusējumi + vides noslēpumi) arī palīdz AI kodēšanas rīkiem: aģenti mācās vienu vietu literāļiem un vienu vietu noslēpumiem, nevis izdomā $_ENV lasījumus kontrolieros.
Izpratne
Jūs varat pielāgot noteiktu Flight darbību, iestatot konfigurācijas vērtības
ar set metodi.
Flight::set('flight.log_errors', true);
Strukturētā lietojumprogrammā (ieskaitot skeleton) jūs parasti ielādējat projekta iestatījumus no app/config/config.php un pēc tam lietojat atbilstošās atslēgas uz Engine (piemēram, flight.base_url, flight.views.path). Varat arī ievadīt nelielu konfigurācijas objektu kontrolieros, nevis lasīt globālos mainīgos visur — tas ir draudzīgāk testiem un aģentiem, kas seko AGENTS.md.
Pamata lietošana
Flight konfigurācijas opcijas
Šeit ir saraksts ar visiem pieejamajiem konfigurācijas iestatījumiem:
- flight.base_url
?string- Pārraksta pieprasījuma bāzes URL, ja Flight darbojas apakšdirektorijā. (noklusējums: null) - flight.case_sensitive
bool- Reģistrjutīga URL atbilstība. (noklusējums: false) - flight.handle_errors
bool- Ļauj Flight iekšēji apstrādāt visas kļūdas. (noklusējums: true) - flight.log_errors
bool- Reģistrē kļūdas tīmekļa servera kļūdu žurnālfailā. (noklusējums: false)- Ja jums ir instalēts Tracy, Tracy reģistrēs kļūdas, pamatojoties uz Tracy konfigurācijām, nevis šo konfigurāciju.
- flight.debug
bool- Izvada detalizētu kļūdu informāciju (izņēmuma ziņojumu, kodu un steka izsekojumu) pārlūkā, kad rodas kļūda. (noklusējums: false)- Nekad neiespējojiet to ražošanā — tas atklāj iekšējas lietojumprogrammas detaļas. Lietojiet to tikai vietējai izstrādei vai starpposma videi.
- Ja
false, tiek rādīta vispārīga500 Internal Server Erroratbilde. Savienojiet arflight.log_errors, lai uztvertu kļūdas servera pusē.
- flight.allow_method_override
bool- Ļauj pārrakstīt HTTP metodi, izmantojotX-HTTP-Method-Overridepieprasījuma galveni vai_methodlauku POST pamattekstā. (noklusējums: true)- Ieteicams iestatīt
falselietojumprogrammām, kurām nav nepieciešama HTML veidlapu metodes viltošana, jo tas novērš klientu iespēju viltotDELETEvaiPUTpieprasījumus, izmantojot standarta POST veidlapu. - Skatiet Drošība sīkākai informācijai.
- Ieteicams iestatīt
- flight.views.path
string- Direktorija, kurā atrodas skata veidņu faili. (noklusējums: ./views) - flight.views.extension
string- Skata veidņu faila paplašinājums. (noklusējums:.php; oficiālais skeleton iestata.twig, ja tiek izmantots Twig) - flight.content_length
bool- IestataContent-Lengthgalveni. (noklusējums: true)- Ja izmantojat Tracy, tas ir jāiestata uz false, lai Tracy varētu pareizi renderēt.
- flight.v2.output_buffering
bool- Izmantot mantoto izejas buferizāciju. Skatiet migrating to v3. (noklusējums: false)
Ielādētāja konfigurācija
Ir vēl viens konfigurācijas iestatījums ielādētājam. Tas ļauj
automātiski ielādēt klases ar _ nosaukumā.
// Iespējot klašu ielādi ar apakšsvītrām
// Noklusējums ir true
Loader::$v2ClassLoading = false;
Atcerieties, ka automātiskā ielāde ir atkarīga arī no mapju reģistra atbilstības jūsu nosaukumvietām — īpaši ar skeleton App\ + app/Controller/ izkārtojumu.
Projekta konfigurācija un .env (skeleton modelis)
Flight kodolam nav nepieciešami .env faili. Daudzas lietojumprogrammas izmanto tikai PHP konfigurācijas masīvu. Oficiālais skeleton noslāņo konfigurāciju, lai noslēpumi paliktu ārpus git, kamēr Runway joprojām var droši pārrakstīt literālo konfigurāciju:
.env/ reālā vide — noslēpumi un izvietošanas pārrakstīšanas (giģnorēti).app/config/config.php— literālo PHP masīvu noklusējumi (kopēti noconfig_sample.php). Dodiet priekšroku bez$_ENV[...]izteiksmēm šajā failā: rīki, piemēram,runway config:set, var to pārrakstīt kā statiskas vērtības un iecept noslēpumus failā.- Sapludināšana startēšanas laikā — vide uzvar kartētajām atslēgām; lietojumprogrammas kods lasa konfigurācijas objektu vai
$app->get(), nevis$_ENVkontrolieros.
Piemērs config_sample.php / config.php formas (vienkāršots):
<?php
// Tikai literāļi — noslēpumi pieder .env skeleton darbplūsmā
return [
'app' => [
'env' => 'development',
'debug' => true,
'base_url' => '/',
'timezone' => 'UTC',
],
'database' => [
'driver' => 'sqlite', // vai mysql, vai '' lai atspējotu
'host' => 'localhost',
'dbname' => '',
'user' => '',
'password' => '',
'file_path' => __DIR__ . '/../../database.sqlite',
],
// ...
];
# .env.example → .env (skeleton)
APP_ENV=development
APP_DEBUG=true
FLIGHT_BASE_URL=/
DB_DRIVER=sqlite
# DB_PASSWORD=...
Šī sadalīšana ir apzināta AI draudzīgiem projektiem: instrukcijas var teikt "noklusējumi config.php, noslēpumi .env, ievadiet Config / Engine — nekad neizgudrojiet env piekļuvi kontrolierī." Esošās lietojumprogrammas var pilnībā ignorēt .env un saglabāt vienu konfigurācijas failu.
Mainīgie
Flight ļauj saglabāt mainīgos, lai tos varētu izmantot jebkurā jūsu lietojumprogrammas vietā.
// Saglabājiet savu mainīgo
Flight::set('id', 123);
// Citur jūsu lietojumprogrammā
$id = Flight::get('id');
Lai pārbaudītu, vai mainīgais ir iestatīts, varat:
if (Flight::has('id')) {
// Izdariet kaut ko
}
Varat notīrīt mainīgo, rīkojoties šādi:
// Notīra id mainīgo
Flight::clear('id');
// Notīra visus mainīgos
Flight::clear();
Piezīme: Tas, ka varat iestatīt mainīgo, nenozīmē, ka jums tas būtu jādara. Lietojiet šo funkciju taupīgi. Iemesls ir tāds, ka viss, kas šeit glabājas, kļūst par globālo mainīgo. Globālie mainīgie ir slikti, jo tos var mainīt no jebkuras vietas jūsu lietojumprogrammā, apgrūtinot kļūdu izsekošanu. Turklāt tas var sarežģīt tādas lietas kā vienību testēšana. Dodiet priekšroku konstruktora ievadīšanai (kā skeleton + Dice iestatījumā) pakalpojumiem un konfigurācijai, kas nepieciešama kontrolieriem.
Kļūdas un izņēmumi
Visas kļūdas un izņēmumi tiek uztverti ar Flight un nodoti error metodei,
ja flight.handle_errors ir iestatīts uz true.
Noklusējuma uzvedība ir nosūtīt vispārīgu HTTP 500 Internal Server Error
atbildi ar zināmu kļūdas informāciju.
Varat pārrakstīt šo uzvedību savām vajadzībām:
Flight::map('error', function (Throwable $error) {
// Apstrādāt kļūdu
echo $error->getTraceAsString();
});
Pēc noklusējuma kļūdas netiek reģistrētas tīmekļa serverī. To var iespējot, mainot konfigurāciju:
Flight::set('flight.log_errors', true);
404 Nav atrasts
Ja URL nevar atrast, Flight izsauc notFound metodi. Noklusējuma
uzvedība ir nosūtīt HTTP 404 Not Found atbildi ar vienkāršu ziņojumu.
Varat pārrakstīt šo uzvedību savām vajadzībām:
Flight::map('notFound', function () {
// Apstrādāt nav atrasts
});
Skatīt arī
- Instalācija - Skeleton konfigurācija,
.env, un startēšanas izkārtojums. - Automātiskā ielāde - Nosaukumvietas un mapju reģistrs.
- Flight paplašināšana - Kā paplašināt un pielāgot Flight pamata funkcionalitāti.
- Vienību testēšana - Kā rakstīt vienību testus jūsu Flight lietojumprogrammai.
- AI un izstrādātāja pieredze -
AGENTS.mdun konsekventas projekta instrukcijas. - Tracy - Spraudnis uzlabotai kļūdu apstrādei un atkļūdošanai.
- Tracy paplašinājumi - Paplašinājumi Tracy integrēšanai ar Flight.
- APM - Spraudnis lietojumprogrammas veiktspējas uzraudzībai un kļūdu izsekošanai.
- Drošība - Stiprināšanas karodziņi un noslēpumu apstrāde.
Problēmu novēršana
- Ja jums ir problēmas atrast visas konfigurācijas vērtības, varat izmantot
var_dump(Flight::get()); - Ja Runway vai izvietošanas rīki pārrakstīja
config.php, pārliecinieties, ka noslēpumi netika ierakstīti git — turiet tos.envvai reālajā vidē, ja izmantojat skeleton modeli.
Izmaiņu žurnāls
- Dokumentācija — Dokumentēta skeleton stila konfigurācija /
.envslāņošana un Twig skata paplašinājuma noklusējums jauniem projektiem. - v3.18.1 - Pievienotas
flight.debugunflight.allow_method_overridekonfigurācijas opcijas. - v3.5.0 - Pievienota konfigurācija
flight.v2.output_buffering, lai atbalstītu mantoto izejas buferizācijas uzvedību. - v2.0 - Pievienotas pamata konfigurācijas.
Learn/ai
AI un izstrādātāju pieredze ar Flight
Pārskats
Flight ir veidots, lai strādātu ar AI kodēšanas rīkiem—nevis cīnītos pret tiem. Neliels, paredzams API, skaidrs lietotnes izkārtojums oficiālajā skeleton un projektam specifiski instrukciju faili nozīmē, ka asistenti, piemēram, GitHub Copilot, Cursor, Windsurf, Claude Code un Gemini, var sekot tiem pašiem modeļiem, ko jūs rakstītu paši.
Ar iebūvētām Runway komandām savienošanai ar LLM pakalpojumu sniedzējiem un projektu instrukciju ģenerēšanai, Flight palīdz jums un jūsu komandai saņemt konsekventu un atbilstošu palīdzību bez nepieciešamības ielīmēt vienu un to pašu kontekstu katrā tērzēšanā.
Izpratne
AI kodēšanas asistenti ir visnoderīgākie, kad tie saprot jūsu projekta kontekstu, konvencijas un mērķus. Flight AI palīgi ļauj jums:
- Savienot jūsu projektu ar populāriem LLM pakalpojumu sniedzējiem (OpenAI, Grok, Claude utt.)
- Ģenerēt un atjaunināt projektam specifiskus instrukciju failus, lai visi saņemtu vienus un tos pašus norādījumus
- Saglabāt roku rakstītu un AI ģenerētu kodu vienā izkārtojumā (īpaši ar skeleton)
Šie rīki ir iekļauti Flight pamata CLI (caur Runway) un ir iepriekš konfigurēti oficiālajā flightphp/skeleton sākuma projektā.
Ko skeleton nodrošina AI
Oficiālais sākuma projekts uzskata AGENTS.md par patiesības avotu AI rīkiem:
| Fails | Loma |
|---|---|
AGENTS.md (projekta sakne) |
Globālie noteikumi, palaišanas plūsma, namespaces, DI, “ko nedrīkst darīt” |
Scoped AGENTS.md zem app/, migrations/, tests/ utt. |
Vieglas, mapēm specifiskas padomes, kad strādājat šajā kokā |
SECURITY.md |
Noslēpumi, galvenes, XSS/SQL, ziņošana—drošība paliek apzināta un atsevišķa |
Skeleton nav atsevišķa stila faila Copilot / Cursor / Gemini / Windsurf. Norādiet savu asistentu uz saknes AGENTS.md (un ļaujiet tam sekot saitēm uz scoped failiem). Cilvēki var pilnībā ignorēt šos failus un izmantot README; izkārtojums abos gadījumos ir vienāds.
Dokumentācija māca API; skeleton māca izkārtojumu. Īsi
Flight::piemēri šajā dokumentācijā ir lieliski mācībām. Skeleton lietotnē dodiet priekšrokuApp\…klasēm, konstruktora injekcijai un$this->appnevis statiskajam fasādes stilam kontrolieros. Skatiet Instalācija un Autoloading.
Pamata lietošana
LLM akreditācijas datu iestatīšana
Komanda ai:init ved jūs cauri projekta savienošanai ar LLM pakalpojumu sniedzēju.
php runway ai:init
Jums tiks prasīts:
- Izvēlēties pakalpojumu sniedzēju (OpenAI, Grok, Claude utt.)
- Ievadīt savu API atslēgu
- Iestatīt bāzes URL un modeļa nosaukumu
Tas izveido akreditācijas datus, kas tiek izmantoti vēlākiem LLM pieprasījumiem (piemēram, instrukciju ģenerēšanai).
Piemērs:
Laipni lūgti AI Init!
Kuru LLM API vēlaties izmantot? [1] openai, [2] grok, [3] claude: 1
Ievadiet bāzes URL LLM API [https://api.openai.com]:
Ievadiet savu API atslēgu priekš openai: sk-...
Ievadiet modeļa nosaukumu, kuru vēlaties izmantot (piem., gpt-4, claude-3-opus utt.) [gpt-4o]:
Akreditācijas dati saglabāti .runway-creds.json
Projektam specifisku AI instrukciju ģenerēšana
Komanda ai:generate-instructions izveido vai atjaunina instrukcijas AI kodēšanas asistentiem, pielāgotas jūsu projektam.
php runway ai:generate-instructions
Jums būs jāatbild uz dažiem jautājumiem (apraksts, datubāze, template engine, drošība, komandas lielums utt.). Flight izmanto jūsu LLM pakalpojumu sniedzēju, lai ģenerētu instrukcijas, un ieraksta tās galvenokārt:
AGENTS.mdprojekta saknē (neatkarīgi no rīka; to sagaida oficiālais skeleton un lielākā daļa mūsdienu asistentu)
Atkarībā no CLI versijas un opcijām komanda var ierakstīt arī rīkiem specifiskas kopijas vecākām darba plūsmām (piemēram, Copilot, Cursor, Windsurf vai Gemini noteikumu failus). Jauniem projektiem, kas veidoti no skeleton, uzskatiet AGENTS.md (plus jebkurus scoped AGENTS.md failus, ko saglabājat zem app/) par vienīgo patiesības avotu—neuzturiet piecus atšķirīgus instrukciju failus manuāli.
Piemērs:
Lūdzu, aprakstiet, kam jūsu projekts ir paredzēts? Mana lieliskā API
Kuru datubāzi plānojat izmantot? MySQL
Kuru HTML template engine plānojat izmantot (ja tāds ir)? twig
Vai drošība ir svarīgs šī projekta elements? (j/n) j
...
AI instrukcijas veiksmīgi atjauninātas.
Tagad AI rīki var ieteikt kodu, kas atbilst jūsu faktiskajai tehnoloģiju kopai un izkārtojumam—nevis vispārīgai PHP apmācībai.
Papildu lietošana
- Pielāgojiet akreditācijas datus vai izvades ceļus ar komandu opcijām (skatiet
--helpkatrai komandai). - Šie rīki darbojas ar jebkuru LLM pakalpojumu sniedzēju, kas atbalsta OpenAI saderīgu API.
- Pārvietojiet
ai:generate-instructionsatkārtoti, projektam attīstoties, lai asistenti paliktu sinhronizēti. - Skeleton saglabājiet drošības politiku
SECURITY.mdfailā un kodēšanas izkārtojumuAGENTS.mdfailā, lai neviens no dokumentiem nekļūtu par visu iespējamo krātuvi. - Dodiet priekšroku docs.flightphp.com un Flight MCP serverim, kad asistentiem nepieciešama API informācija; pārbaudiet izgudrotas metodes pret
vendor/flightphp/core.
Skatīt arī
- Flight Skeleton – Oficiālais sākuma projekts ar
AGENTS.md, Twig, SimplePdo un Dice, kas konfigurēti AI draudzīgai struktūrai - Instalācija – Ieteicamais
create-projectizkārtojums - Autoloading – Mapes reģistrs atbilst namespaces (
App\Controller↔app/Controller/) - Runway CLI – CLI, kas nodrošina
ai:*un scaffolding komandas - Drošība – Drošie noklusējumi, kurus asistenti (un cilvēki) nedrīkst vājināt
Problēmu novēršana
- Ja redzat “Missing .runway-creds.json”, vispirms izpildiet
php runway ai:init. - Pārliecinieties, ka jūsu API atslēga ir derīga un tai ir piekļuve izvēlētajam modelim.
- Ja instrukcijas netiek atjauninātas, pārbaudiet failu atļaujas projekta direktorijā.
- Ja asistenti izgudro Flight API vai nepareizu mapju izkārtojumu, norādiet tos uz saknes
AGENTS.mdun šo dokumentācijas vietni; skeleton izkārtojums ir noteicošais kodam zemapp/.
Izmaiņu žurnāls
- v3.18.4 –
ai:generate-instructionsieraksta projekta instrukcijasAGENTS.mdprojekta saknē. - v3.16.0 – Pievienotas
ai:initunai:generate-instructionsCLI komandas AI integrācijai.
Learn/unit_testing_and_solid_principles
Šis raksts sākotnēji tika publicēts vietnē Airpair 2015. gadā. Visi nopelni tiek doti Airpair un Brianam Fentonam, kurš sākotnēji uzrakstīja šo rakstu, lai gan vietne vairs nav pieejama, un raksts pastāv tikai Wayback Machine. Šis raksts ir pievienots vietnei mācību un izglītības mērķiem PHP kopienai kopumā.
1 Iestatīšana un konfigurācija
1.1 Turiet to aktuālu
Sāksim ar to – pārsteidzoši maz PHP instalāciju praksē ir aktuālas vai tiek uzturētas aktuālas. Vai tas ir dēļ koplietotas hostinga ierobežojumiem, noklusējumiem, kurus neviens nemaina, vai laika/budžeta trūkuma atjaunināšanas testēšanai, PHP binārās faili mēdz tikt atstāti novārtā. Tāpēc viena skaidra labākā prakse, kurai vajadzētu pievērst vairāk uzmanības, ir vienmēr izmantot aktuālu PHP versiju (5.6.x šajā rakstā). Turklāt ir svarīgi plānot regulāras atjaunināšanas gan pašam PHP, gan jebkādiem paplašinājumiem vai piegādātāju bibliotēkām, kuras jūs izmantojat. Atjaunināšanas sniedz jaunas valodas funkcijas, uzlabotu ātrumu, mazāku atmiņas lietojumu un drošības atjauninājumus. Jo biežāk jūs atjauninat, jo mazāk sāpīgs process kļūst.
1.2 Iestatiet saprātīgus noklusējumus
PHP veic pienācīgu darbu, iestatot labus noklusējumus ar saviem php.ini.development un php.ini.production failiem, bet mēs varam darīt labāk. Piemēram, tie mums nekur nenorāda datumu/laiku joslu. Tas ir saprātīgi no izplatīšanas viedokļa, bet bez tās PHP izmetīs E_WARNING kļūdu katru reizi, kad izsaucam datuma/laika saistītu funkciju. Lūk, daži ieteikti iestatījumi:
- date.timezone – izvēlieties no atbalstīto laika joslu saraksta
- session.savepath – ja mēs izmantojam failus sesijām un ne kādu citu saglabāšanas pārvaldnieku, iestatiet to kaut kur ārpus /tmp. Atstāt to kā /tmp var būt riskanti koplietotā hostinga vidē, jo /tmp_ parasti ir plašas atļaujas. Pat ar sticky-bit iestatītu, ikviens, kam ir pieeja šīs direktorijas satura sarakstam, var uzzināt visus jūsu aktīvos sesijas ID.
- session.cookie_secure – acīmredzami, ieslēdziet to, ja jūsu PHP kodu pasniedzat pār HTTPS.
- session.cookie_httponly – iestatiet to, lai novērstu piekļuvi PHP sesijas sīkdatnēm caur JavaScript
- Vairāk... izmantojiet rīku kā iniscan, lai pārbaudītu savu konfigurāciju pret biežām ievainojamībām
1.3 Paplašinājumi
Tas arī ir laba ideja deaktivizēt (vai vismaz neaktivizēt) paplašinājumus, kurus jūs neizmantosiet, piemēram, datu bāzes draiverus. Lai redzētu, kas ir aktivizēts, izpildiet phpinfo() komandu vai dodieties uz komandrindu un izpildiet šo.
$ php -i
Informācija ir tā pati, bet phpinfo() pievieno HTML formatējumu. CLI versija ir vieglāk caurvadāma uz grep, lai atrastu specifisku informāciju. Piem.
$ php -i | grep error_log
Viens ierobežojums šai metodei: iespējams, ka dažādas PHP iestatījumi attiecas uz tīmekļa versiju un CLI versiju.
2 Izmantojiet Composer
Tas varētu būt pārsteigums, bet viena no labākajām praksēm mūsdienu PHP rakstīšanai ir rakstīt mazāk no tā. Lai gan ir taisnība, ka viens no labākajiem veidiem, kā kļūt labākam programmēšanā, ir darīt to, ir daudz problēmu, kas jau ir atrisinātas PHP telpā, piemēram, maršrutēšana, pamata ievades validācijas bibliotēkas, vienību konvertēšana, datu bāzes abstrakcijas slāņi utt... Vienkārši apmeklējiet Packagist un izpētiet. Jūs, visticamāk, atradīsiet, ka ievērojamas daļas no problēmas, kuru mēģināt atrisināt, jau ir uzrakstītas un testētas.
Kaut arī vilinoši ir rakstīt visu kodu pašam (un ar to nav nekā slikta – rakstīt savu ietvaru vai bibliotēku kā mācību pieredzi), jums vajadzētu cīnīties pret šīm "Neizgudrots Šeit" izjūtām un ietaupīt sev daudz laika un galvassāpju. Sekojiet PIE doktrīnai – Lepni Izgudrots Citur. Arī, ja jūs izvēlaties rakstīt savu kaut ko, neatklaidiet to, ja tas nedara kaut ko ievērojami atšķirīgu vai labāku nekā esošie piedāvājumi.
Composer ir pakotņu pārvaldnieks PHP, līdzīgs pip Python, gem Ruby un npm Node. Tas ļauj definēt JSON failu, kas uzskaita jūsu koda atkarības, un tas mēģinās atrisināt šīs prasības, lejupielādējot un instalējot nepieciešamo kodu saišķus.
2.1 Composer instalēšana
Mēs pieņemam, ka tas ir lokāls projekts, tāpēc instalēsim Composer instanci tikai šim projektam. Dodieties uz savu projektu direktoriju un izpildiet šo:
$ curl -sS https://getcomposer.org/installer | php
Atcerieties, ka caurvadīt jebkuru lejupielādi tieši uz skripta interpreters (sh, ruby, php utt...) ir drošības risks, tāpēc izlasiet instalēšanas kodu un pārliecinieties, ka esat ar to mierā, pirms izpildāt jebkuru šādu komandu.
Ērtības dēļ (ja jūs dodat priekšroku rakstīt composer install nevis php composer.phar install), jūs varat izmantot šo komandu, lai instalētu vienu Composer kopiju globāli:
$ mv composer.phar /usr/local/bin/composer
$ chmod +x composer
Jums var būt nepieciešams izpildīt šos ar sudo, atkarībā no jūsu failu atļaujām.
2.2 Composer izmantošana
Composer ir divas galvenās atkarību kategorijas, kuras tas var pārvaldīt: "require" un "require-dev". Atkarības, kas uzskaitītas kā "require", tiek instalētas visur, bet "require-dev" atkarības tiek instalētas tikai tad, kad tās tiek īpaši pieprasītas. Parasti tās ir rīki, kad kods ir aktīvā attīstībā, piemēram, PHP_CodeSniffer. Zemāk redzams piemērs, kā instalēt Guzzle, populāru HTTP bibliotēku.
$ php composer.phar require guzzle/guzzle
Lai instalētu rīku tikai attīstības mērķiem, pievienojiet karogu --dev:
$ php composer.phar require --dev 'sebastian/phpcpd'
Tas instalē PHP Copy-Paste Detector, citu koda kvalitātes rīku kā attīstības atkarību.
2.3 Install vs update
Kad mēs pirmo reizi izpildām composer install, tas instalēs jebkuras bibliotēkas un to atkarības, balstoties uz composer.json failu. Kad tas ir paveikts, composer izveido bloķēšanas failu, paredzami sauktu composer.lock. Šis fails satur sarakstu ar atkarībām, kuras composer atrada mums, un to precīzajām versijām ar hashiem. Tad jebkuru nākamo reizi, kad izpildām composer install, tas paskatīsies bloķēšanas failā un instalēs tās precīzās versijas.
composer update ir mazliet atšķirīga būtne. Tas ignorēs composer.lock failu (ja tāds ir) un mēģinās atrast visjaunākās katras atkarības versijas, kas joprojām apmierina ierobežojumus composer.json. Tad tas rakstīs jaunu composer.lock failu, kad tas ir pabeigts.
2.4 Autoloadēšana
Gan composer install, gan composer update ģenerēs autoloader mums, kas stāsta PHP, kur atrast visas nepieciešamās failus, lai izmantotu bibliotēkas, kuras mēs tikko instalējām. Lai to izmantotu, vienkārši pievienojiet šo rindiņu (parasti uz bootstrap failu, kas tiek izpildīts katru pieprasījumu):
require 'vendor/autoload.php';
3 Sekojiet labiem dizaina principiem
3.1 SOLID
SOLID ir mnemonika, lai atgādinātu mums par piecām galvenajām principiem labā objekt-orientētā programmatūras dizainā.
3.1.1 S - Single Responsibility Principle
Tas norāda, ka klasēm vajadzētu būt tikai vienai atbildībai, vai, citādi sakot, tām vajadzētu būt tikai viens iemesls izmaiņām. Tas labi iekļaujas Unix filozofijā ar daudzām mazām rīkām, kas dara vienu lietu labi. Klases, kas dara tikai vienu lietu, ir daudz vieglāk testēt un atkļūdot, un tās mazāk jūs pārsteigs. Jūs nevēlaties, lai metodes izsaukums uz Validator klasi atjaunina db ierakstus. Lūk, piemērs ar SRP pārkāpumu, kādu jūs bieži redzētu aplikācijā, kas balstīta uz ActiveRecord pattern.
class Person extends Model
{
public $name;
public $birthDate;
protected $preferences;
public function getPreferences() {}
public function save() {}
}
Tā ir diezgan pamata entity modelis. Bet viena no šīm lietām šeit nepieder. Entitātes modelim vajadzētu būt tikai uzvedībai, kas saistīta ar entītāti, ko tā pārstāv, tam nevajadzētu būt atbildīgam par pašas saglabāšanu.
class Person extends Model
{
public $name;
public $birthDate;
protected $preferences;
public function getPreferences() {}
}
class DataStore
{
public function save(Model $model) {}
}
Tas ir labāk. Person modelis atgriežas pie tā, ka dara tikai vienu lietu, un saglabāšanas uzvedība ir pārvietota uz noturības objektu. Ņemiet vērā, ka es tikai type hinted uz Model, ne Person. Mēs atgriezīsimies pie tā, kad nonāksim pie L un D SOLID daļām.
3.1.2 O - Open Closed Principle
Ir lielisks tests šim, kas diezgan labi apkopo, par ko šis princips ir: padomājiet par funkciju, ko ieviest, iespējams, pēdējo, pie kuras strādājāt vai strādājat. Vai jūs varat ieviest šo funkciju esošajā kodsbazē TIKAI pievienojot jaunas klases un nemainot nevienu esošu klasi sistēmā? Jūsu konfigurācija un vadošais kods saņem mazliet atlaides, bet lielākajā daļā sistēmu tas ir pārsteidzoši grūti. Jums ir jāpaļaujas daudz uz polimorfisku nosūtīšanu, un lielākā daļā kodsbazju tas vienkārši nav iestatīts. Ja jūs interesējaties par to, ir labs Google runas video YouTube par polimorfismu un kodu rakstīšanu bez If, kas izpēta to tālāk. Kā bonuss, runu vada Miško Hevery, kuru daudzi var zināt kā AngularJs izveidotāju.
3.1.3 L - Liskov Substitution Principle
Šis princips ir nosaukts Barbara Liskov vārdā, un tas ir izdrukāts zemāk:
"Objekti programmā vajadzētu būt aizvietojami ar viņu apakštipu instancēm, nekaitējot programmas pareizībai."
Tas viss izklausās labi, bet tas ir skaidrāk ilustrēts ar piemēru.
abstract class Shape
{
public function getHeight();
public function setHeight($height);
public function getLength();
public function setLength($length);
}
Šis pārstāvēs mūsu pamata četrām pusēm formu. Nekas izsmalcināts šeit.
class Square extends Shape
{
protected $size;
public function getHeight() {
return $this->size;
}
public function setHeight($height) {
$this->size = $height;
}
public function getLength() {
return $this->size;
}
public function setLength($length) {
$this->size = $length;
}
}
Šī ir mūsu pirmā forma, Kvadrāts. Diezgan taisni uz priekšu forma, vai ne? Jūs varat pieņemt, ka ir konstruktors, kur mēs iestatām izmērus, bet no šīs realizācijas jūs redzat, ka garums un augstums vienmēr būs vienādi. Kvadrāti vienkārši ir tādi.
class Rectangle extends Shape
{
protected $height;
protected $length;
public function getHeight() {
return $this->height;
}
public function setHeight($height) {
$this->height = $height;
}
public function getLength() {
return $this->length;
}
public function setLength($length) {
$this->length = $length;
}
}
Tā ir cita forma. Joprojām ir tās pašas metodes paraksti, tā joprojām ir četrām pusēm forma, bet ko, ja mēs sākam mēģināt izmantot tās citu vietā? Tagad pēkšņi, ja mēs mainām formas augstumu, mēs vairs nevaram pieņemt, ka formas garums sakritīs. Mēs esam pārkāpuši līgumu, ko bijām noslēguši ar lietotāju, kad devām viņam mūsu Kvadrāta formu.
Tas ir tipisks LSP pārkāpuma piemērs, un mums ir vajadzīgs šāds princips, lai vislabāk izmantotu tipa sistēmu. Pat duck typing nepateiks mums, ja pamata uzvedība ir atšķirīga, un, tā kā mēs to nevaram zināt bez tam lūstot, ir labāk pārliecināties, ka tā nav atšķirīga.
3.1.3 I - Interface Segregation Principle
Šis princips prasa priekšroku daudzām mazām, smalkām saskarnēm pret vienu lielu. Saskarnes vajadzētu balstīties uz uzvedību, nevis "tas ir viena no šīm klasēm". Padomājiet par saskarnēm, kas nāk ar PHP. Traversable, Countable, Serializable, tādas lietas. Tās reklamē spējas, ko objekts piemīt, nevis ko tas manto. Tāpēc turiet savas saskarnes mazas. Jūs nevēlaties, lai saskarnei būtu 30 metodes, 3 ir daudz labāks mērķis.
3.1.4 D - Dependency Inversion Principle
Jūs, iespējams, esat dzirdējuši par to citās vietās, kur runāja par Dependency Injection, bet Dependency Inversion un Dependency Injection nav gluži viena un tā pati lieta. Dependency inversion patiesībā ir veids, kā teikt, ka jums vajadzētu paļauties uz abstrakcijām savā sistēmā, nevis uz tās detaļām. Ko tas nozīmē jums ikdienā?
Neizmantojiet mysqli_query() tieši visā savā kodā, izmantojiet kaut ko kā DataStore->query() tā vietā.
Šī principa kodols ir par abstrakcijām. Tas vairāk ir par teikumu "izmantojiet datu bāzes adapteri" nevis paļaujoties uz tiešiem izsaukumiem uz lietām kā mysqli_query. Ja jūs tieši izmantojat mysqli_query pusē no savām klasēm, tad jūs visu saistāt tieši ar savu datu bāzi. Nekas pret MySQL šeit, bet, ja jūs izmantojat mysqli_query, šāda veida zemlaukuma detaļas vajadzētu būt paslēptas tikai vienā vietā, un tad šī funkcionalitāte vajadzētu būt pieejama caur ģenerisku aploksni.
Tagad es zinu, ka tas ir mazliet izmantots piemērs, ja jūs par to domājat, jo reizes, kad jūs pilnībā mainīsiet savu datu bāzes dzinēju pēc produkta ieviešanas, ir ļoti, ļoti zemas. Es to izvēlējos, jo domāju, ka cilvēki būs pazīstami ar ideju no sava koda. Arī, pat ja jums ir datu bāze, ar kuru jūs zināt, ka paliksiet, šī abstraktā aploksnes objekts ļauj jums labot kļūdas, mainīt uzvedību vai ieviest funkcijas, kuras jūs vēlaties, lai jūsu izvēlētajai datu bāzei būtu. Tas arī padara unit testēšanu iespējamo, kur zemlaukuma izsaukumi to nedarītu.
4 Objektu vingrinājumi
Šis nav pilns izpēte šiem principiem, bet pirmie divi ir viegli atcerēties, sniedz labu vērtību un var tikt nekavējoties piemēroti gandrīz jebkurai kodsbazei.
4.1 Ne vairāk kā viens indentācijas līmenis uz metodi
Tas ir noderīgs veids, kā domāt par metožu sadalīšanu mazākos gabalos, atstājot kodu, kas ir skaidrāks un vairāk pašdokumentējošs. Jo vairāk indentācijas līmeņu jums ir, jo vairāk metode dara un jo vairāk stāvokļa jums jāseko prātā, kamēr jūs ar to strādājat.
Tūlīt es zinu, ka cilvēki iebildīs pret to, bet tas ir tikai vadlīnija/heiistika, ne cieta un ātra likums. Es negaidu, ka kāds izpildīs PHP_CodeSniffer noteikumus tam (lai gan cilvēki ir).
Apskatīsim ātru paraugu, kā tas varētu izskatīties:
public function transformToCsv($data)
{
$csvLines = array();
$csvLines[] = implode(',', array_keys($data[0]));
foreach ($data as $row) {
if (!$row) {
continue;
}
$csvLines[] = implode(',', $row);
}
return $csvLines;
}
Kamēr šis nav briesmīgs kods (tas tehniski ir pareizs, testējams utt...), mēs varam darīt daudz vairāk, lai to padarītu skaidru. Kā mēs samazinātu ligzdas līmeņus šeit?
Mēs zinām, ka mums ir jāvienkāršo foreach cikla saturs (vai to noņemt pilnībā), tāpēc sāksim tur.
if (!$row) {
continue;
}
Šī pirmā daļa ir viegla. Tas tikai ignorē tukšas rindas. Mēs varam saīsināt šo procesu, izmantojot iebūtu PHP funkciju pirms pat nokļūšanas ciklā.
$data = array_filter($data);
foreach ($data as $row) {
$csvLines[] = implode(',', $row);
}
Tagad mums ir mūsu viens ligzdas līmenis. Bet, skatoties uz to, viss, ko mēs darām, ir funkcijas piemērošana katram vienumam masīvā. Mums pat nav vajadzīgs foreach cikls, lai to darītu.
$data = array_filter($data);
$csvLines = array_map(function($row) {
return implode(',', $row);
}, $data);
Tagad mums vispār nav ligzdas, un kods, visticamāk, būs ātrāks, jo mēs darām visu ciklu ar iebūtiem C funkcijām nevis PHP. Mums ir jāiesaistās mazliet viltībā, lai nodotu komatu uz implode, tāpēc jūs varētu argumentēt, ka apstāšanās pie iepriekšējā soļa ir daudz saprotamāka.
4.2 Mēģiniet neizmantot else
Tas tiešām attiecas uz divām galvenajām idejām. Pirmā ir vairākas return paziņojumi no metodes. Ja jums ir pietiekami daudz informācijas, lai pieņemtu lēmumu par metodes rezultātu, ejiet uz priekšu un pieņemiet to un return. Otrā ir ideja, kas pazīstama kā Guard Clauses. Tās ir pamata validācijas pārbaudes, kas kombinētas ar agrīniem return, parasti metodes augšdaļā. Ļaujiet man parādīt, ko es domāju.
public function addThreeInts($first, $second, $third) {
if (is_int($first)) {
if (is_int($second)) {
if (is_int($third)) {
$sum = $first + $second + $third;
} else {
return null;
}
} else {
return null;
}
} else {
return null;
}
return $sum;
}
Tā ir diezgan taisna uz priekšu atkal, tā pievieno 3 intus kopā un atgriež rezultātu, vai null, ja kāds no parametriem nav integers. Ignorējot to, ka mēs varētu apvienot visas šīs pārbaudes vienā rindā ar AND operatoriem, es domāju, ka jūs redzat, cik ligzotais if/else struktūra padara kodu grūtāk sekot. Tagad paskatieties uz šo piemēru.
public function addThreeInts($first, $second, $third) {
if (!is_int($first)) {
return null;
}
if (!is_int($second)) {
return null;
}
if (!is_int($third)) {
return null;
}
return $first + $second + $third;
}
Man šis piemērs ir daudz vieglāk sekot. Šeit mēs izmantojam guard clauses, lai verificētu mūsu sākotnējos pieņēmumus par parametriem, ko mēs pārejam, un nekavējoties izkāpjam no metodes, ja tās neizdodas. Mēs arī vairs neesam ar starpposma mainīgo, lai izsekotu summu caur visu metodi. Šajā gadījumā mēs esam verificējuši, ka mēs jau esam uz laimīgā ceļa, un varam vienkārši darīt to, ko mēs atnācām darīt. Atkal mēs varētu vienkārši darīt visas šīs pārbaudes vienā if, bet princips vajadzētu būt skaidrs.
5 Unit testēšana
Unit testēšana ir prakse rakstīt mazus testus, kas verificē uzvedību jūsu kodā. Tie gandrīz vienmēr tiek rakstīti tajā pašā valodā kā kods (šajā gadījumā PHP) un ir paredzēti, lai būtu pietiekami ātri, lai tos izpildītu jebkurā laikā. Tie ir ārkārtīgi vērtīgi kā rīks, lai uzlabotu jūsu kodu. Papildus acīmredzamajām priekšrocībām, nodrošinot, ka jūsu kods dara to, ko jūs domājat, unit testēšana var sniegt ļoti noderīgu dizaina atsauksmi. Ja koda gabals ir grūti testējams, tas bieži parāda dizaina problēmas. Tie arī dod jums drošības tīklu pret regresijām, un tas ļauj jums refactorēt daudz biežāk un attīstīt savu kodu tīrākam dizainam.
5.1 Rīki
Ir vairāki unit testēšanas rīki PHP, bet tālu un prom visizplatītākais ir PHPUnit. Jūs varat instalēt to, lejupielādējot PHAR failu tieši, vai instalēt to ar composer. Tā kā mēs izmantojam composer visam pārējam, mēs parādīsim šo metodi. Arī, tā kā PHPUnit, visticamāk, netiks izvietots ražošanā, mēs varam instalēt to kā dev atkarību ar šo komandu:
composer require --dev phpunit/phpunit
5.2 Testi ir specifikācija
Vissvarīgākā unit testu loma jūsu kodā ir nodrošināt izpildāmu specifikāciju tam, ko kods ir paredzēts darīt. Pat ja testa kods ir nepareizs vai kodā ir kļūdas, zināšanas par to, ko sistēma ir paredzēts darīt, ir nenovērtējama.
5.3 Rakstiet savus testus vispirms
Ja jums ir bijusi iespēja redzēt testu kopu, kas rakstīta pirms koda, un vienu, kas rakstīta pēc koda pabeigšanas, tās ir satriecoši atšķirīgas. "Pēc" testi ir daudz vairāk uztraukti par klases īstenošanas detaļām un labas līnijas seguma nodrošināšanu, savukārt "pirms" testi vairāk ir par vēlamās ārējās uzvedības verificēšanu. Tas tiešām ir tas, par ko mums rūp ar unit testiem, ir pārliecināties, ka klase izrāda pareizo uzvedību. Uz īstenošanu fokusēti testi faktiski padara refactorēšanu grūtāku, jo tie lūzt, ja klases iekšējās daļas mainās, un jūs tikko esat pazaudējis OOP informācijas slēptuves priekšrocības.
5.4 Kas padara labu unit testu
Labiem unit testiem ir daudz no šīm īpašībām:
- Ātrs – vajadzētu darboties milise kundās.
- Nav tīkla piekļuve – vajadzētu būt spējīgam izslēgt bezvadu/nepievienot un visi testi joprojām izdodas.
- Ierobežota failu sistēmas piekļuve – tas pievieno ātrumu un elastīgumu, ja izvieto kodu citās vidēs.
- Nav datu bāzes piekļuve – izvairās no dārgiem iestatīšanas un izjaukšanas aktivitātēm.
- Testē tikai vienu lietu vienlaicīgi – unit testam vajadzētu būt tikai viens iemesls, kāpēc tas neizdodas.
- Labi nosaukts – skatiet 5.2 augstāk.
- Galvenokārt viltoti objekti – vienīgie "īstie" objekti unit testos vajadzētu būt objektam, ko mēs testējam, un vienkāršiem vērtību objektiem. Pārējie vajadzētu būt kādas formas test double
Ir iemesli iet pret dažiem no šiem, bet kā vispārēji vadlīnijas tās jums kalpos labi.
5.5 Kad testēšana ir sāpīga
Unit testēšana liek jums izjust sliktā dizaina sāpes uz priekšu – Michael Feathers
Kad jūs rakstāt unit testus, jūs piespiežat sevi faktiski izmantot klasi, lai paveiktu lietas. Ja jūs rakstāt testus beigās, vai vēl sliktāk, vienkārši metat kodu pāri sienai QA vai kam, lai rakstītu testus, jūs nesaņemat atsauksmi par to, kā klase faktiski uzvedas. Ja mēs rakstām testus un klase ir reāla sāpe izmantot, mēs to uzzināsim, kamēr mēs to rakstām, kas ir gandrīz lētākais laiks to labot.
Ja klase ir grūti testējama, tas ir dizaina trūkums. Dažādi trūkumi parādās dažādos veidos, kaut gan. Ja jums ir jādara daudz mocking, jūsu klasei, iespējams, ir pārāk daudz atkarību vai jūsu metodes dara pārāk daudz. Jo vairāk iestatīšanas jums ir jāveic katram testam, jo vairāk iespējams, ka jūsu metodes dara pārāk daudz. Ja jums ir jāraksta patiešām sarežģīti testa scenāriji, lai izmantotu uzvedību, klases metodes, iespējams, dara pārāk daudz. Ja jums ir jāizrok iekšā daudz privātu metožu un stāvokļa, lai testētu lietas, varbūt tur ir cita klase, kas mēģina izkļūt. Unit testēšana ir ļoti laba, lai atklātu "aisberga klases", kur 80% no tā, ko klase dara, ir paslēpts aiz protected vai private koda. Es kādreiz biju liels fans padarīt cik iespējams daudz protected, bet tagad es sapratu, ka es tikai liku savām individuālajām klasēm atbildēt par pārāk daudz, un īstā risinājums bija sadalīt klasi mazākos gabalos.
Rakstījis Brian Fenton - Brian Fenton ir bijis PHP izstrādātājs 8 gadus Vidējos Rietumos un Bay Area, šobrīd Thismoment. Viņš fokusējas uz kodu amatniecību un dizaina principiem. Blogs www.brianfenton.us, Twitter @brianfenton. Kad viņš nav aizņemts būdams tēvs, viņam patīk ēdiens, alus, spēles un mācīšanās.
Learn/security
Drošība
Pārskats
Drošība ir liela lieta, runājot par tīmekļa lietojumprogrammām. Jūs vēlaties pārliecināties, ka jūsu lietojumprogramma ir droša un ka jūsu lietotāju dati ir drošībā. Flight piedāvā vairākas funkcijas, lai palīdzētu jums aizsargāt savas tīmekļa lietojumprogrammas.
Oficiālais skelets ietver arī īpašu SECURITY.md un drošības galveņu starpprogrammatūru, lai AI kodēšanas rīkiem (un cilvēkiem) būtu viena apzināta vieta noslēpumiem, galvenēm un XSS/SQL noteikumiem — atsevišķi no vispārējā koda stila failā AGENTS.md.
Izpratne
Ir vairāki izplatīti drošības apdraudējumi, par kuriem jums vajadzētu zināt, veidojot tīmekļa lietojumprogrammas. Daži no visizplatītākajiem apdraudējumiem ir:
- Starpsaites pieprasījuma viltošana (CSRF)
- Starpsaites skriptošana (XSS)
- SQL injekcija
- Cross Origin Resource Sharing (CORS)
Veidnes palīdz pret XSS, pēc noklusējuma atdalot izvadi (Twig un Latte to dara; izmantojiet šo priekšrocību). Sesijas var palīdzēt pret CSRF, saglabājot CSRF tokenu lietotāja sesijā, kā aprakstīts tālāk. Sagatavotu vaicājumu izmantošana ar PDO — vai SimplePdo palīgmetodes — palīdz novērst SQL injekcijas. CORS var apstrādāt ar vienkāršu āķi pirms Flight::start() izsaukšanas.
Visas šīs metodes darbojas kopā, lai palīdzētu uzturēt jūsu tīmekļa lietojumprogrammas drošas. Jums vienmēr priekšplānā jābūt apgūt un izprast drošības paraugpraksi. Nelūdziet AI asistentam "atspējot CSP" vai vājināt galvenes tikai tāpēc, lai lapa ielādētos, nesaprotot kompromisu.
Pamata lietošana
Galvenes
HTTP galvenes ir viens no vienkāršākajiem veidiem, kā aizsargāt savas tīmekļa lietojumprogrammas. Varat izmantot galvenes, lai novērstu klikšķināšanas nolaupīšanu (clickjacking), XSS un citus uzbrukumus. Ir vairāki veidi, kā pievienot šīs galvenes savai lietojumprogrammai.
Divas lieliskas vietnes, kur pārbaudīt savu galveņu drošību, ir securityheaders.com un observatory.mozilla.org. Pēc tālāk norādītā koda iestatīšanas jūs varat viegli pārbaudīt, vai jūsu galvenes darbojas, izmantojot šīs divas vietnes.
Skelets ietver App\Middleware\SecurityHeadersMiddleware (CSP ar pieprasījumam atbilstošu nonce, frame opcijām, HSTS un vairāk). Dodiet priekšroku tā apzinātai paplašināšanai, nevis galveņu atspējošanai.
Pievienošana ar rokām
Šīs galvenes varat pievienot manuāli, izmantojot header metodi uz Flight\Response objekta.
// Iestatiet X-Frame-Options galveni, lai novērstu clickjacking
Flight::response()->header('X-Frame-Options', 'SAMEORIGIN');
// Iestatiet Content-Security-Policy galveni, lai novērstu XSS
// Piezīme: šī galvene var kļūt ļoti sarežģīta, tāpēc jūs vēlēsities
// apskatīt piemērus internetā savai lietojumprogrammai
Flight::response()->header("Content-Security-Policy", "default-src 'self'");
// Iestatiet X-XSS-Protection galveni, lai novērstu XSS
Flight::response()->header('X-XSS-Protection', '1; mode=block');
// Iestatiet X-Content-Type-Options galveni, lai novērstu MIME uzminēšanu
Flight::response()->header('X-Content-Type-Options', 'nosniff');
// Iestatiet Referrer-Policy galveni, lai kontrolētu, cik daudz referrer informācijas tiek nosūtīts
Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade');
// Iestatiet Strict-Transport-Security galveni, lai piespiestu HTTPS
Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
// Iestatiet Permissions-Policy galveni, lai kontrolētu, kādas funkcijas un API var tikt izmantotas
Flight::response()->header('Permissions-Policy', 'geolocation=()');
Tās var pievienot savu routes.php vai index.php failu augšpusē.
Pievienošana kā filtrs
Varat tās arī pievienot filtrā/āķī, piemēram:
// Pievienojiet galvenes filtrā
Flight::before('start', function() {
Flight::response()->header('X-Frame-Options', 'SAMEORIGIN');
Flight::response()->header("Content-Security-Policy", "default-src 'self'");
Flight::response()->header('X-XSS-Protection', '1; mode=block');
Flight::response()->header('X-Content-Type-Options', 'nosniff');
Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade');
Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
Flight::response()->header('Permissions-Policy', 'geolocation=()');
});
Pievienošana kā starpprogrammatūra
Varat tās pievienot arī kā starpprogrammatūras klasi, kas nodrošina vislielāko elastību, nosakot, kuriem maršrutiem to piemērot. Parasti šīs galvenes būtu jāpiemēro visām HTML un API atbildēm.
Skeleta stila ceļš un nosaukumvieta (mapes reģistrs atbilst App\Middleware):
// app/Middleware/SecurityHeadersMiddleware.php
namespace App\Middleware;
use flight\Engine;
class SecurityHeadersMiddleware
{
protected Engine $app;
public function __construct(Engine $app)
{
$this->app = $app;
}
public function before(array $params): void
{
$response = $this->app->response();
// Dodiet priekšroku CSP nonce no bootstrap, ja jums ir iekļauti skripti (skelets iestata csp_nonce)
$nonce = $this->app->get('csp_nonce');
$csp = $nonce
? "default-src 'self'; script-src 'self' 'nonce-{$nonce}'; style-src 'self' 'nonce-{$nonce}'"
: "default-src 'self'";
$response->header('X-Frame-Options', 'SAMEORIGIN');
$response->header('Content-Security-Policy', $csp);
$response->header('X-XSS-Protection', '1; mode=block');
$response->header('X-Content-Type-Options', 'nosniff');
$response->header('Referrer-Policy', 'no-referrer-when-downgrade');
$response->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
$response->header('Permissions-Policy', 'geolocation=()');
}
}
// app/config/routes.php — tukšas virknes grupa = globālā starpprogrammatūra visiem maršrutiem
use App\Middleware\SecurityHeadersMiddleware;
use flight\net\Router;
$router->group('', function (Router $router) {
$router->get('/users', [ \App\Controller\UserController::class, 'getUsers' ]);
// vairāk maršrutu
}, [SecurityHeadersMiddleware::class]);
Vecāki projekti joprojām var izmantot app/middlewares un app\middlewares; tas darbojas, ja mapes sakrīt. Jaunās skeleta lietotnes izmanto app/Middleware/ un App\Middleware. Skatīt Automātiskā ielāde.
Starpsaites pieprasījuma viltošana (CSRF)
Starpsaites pieprasījuma viltošana (CSRF) ir uzbrukuma veids, kurā ļaunprātīga vietne var likt lietotāja pārlūkprogrammai nosūtīt pieprasījumu jūsu vietnei. To var izmantot, lai veiktu darbības jūsu vietnē bez lietotāja ziņas. Flight nepiedāvā iebūvētu CSRF aizsardzības mehānismu, taču jūs to viegli varat ieviest pats, izmantojot starpprogrammatūru.
Iestatīšana
Vispirms jums ir jāģenerē CSRF tokens un jāsaglabā tas lietotāja sesijā. Pēc tam varat izmantot šo tokenu savās veidlapās un pārbaudīt to, kad veidlapa tiek iesniegta. Mēs izmantosim flightphp/session spraudni, lai pārvaldītu sesijas.
// Ģenerējiet CSRF tokenu un saglabājiet to lietotāja sesijā
// (pieņemot, ka esat izveidojis sesijas objektu un pievienojis to Flight)
// skatiet sesijas dokumentāciju, lai iegūtu vairāk informācijas
Flight::register('session', flight\Session::class);
// Jums ir jāģenerē tikai viens tokens katrā sesijā (lai tas darbotos
// vairākās cilnēs un pieprasījumos vienam un tam pašam lietotājam)
if(Flight::session()->get('csrf_token') === null) {
Flight::session()->set('csrf_token', bin2hex(random_bytes(32)) );
}
Izmantojot noklusējuma PHP Flight veidni
<!-- Izmantojiet CSRF tokenu savā veidlapā -->
<form method="post">
<input type="hidden" name="csrf_token" value="<?= Flight::session()->get('csrf_token') ?>">
<!-- citi veidlapas lauki -->
</form>
Izmantojot Twig (skeleta noklusējums)
Reģistrējiet Twig funkciju vai nododiet tokenu katrā veidlapas skatā. Minimāls piemērs ar globālo mainīgo + veidlapas lauku:
// Konfigurējot Twig (piem., services.php)
$twig->addGlobal('csrf_token', $app->session()->get('csrf_token'));
{# app/views/form.twig #}
<form method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
{# citi lauki #}
</form>
Izmantojot Latte
Varat arī iestatīt pielāgotu funkciju, lai izvadītu CSRF tokenu savās Latte veidnēs.
Flight::map('render', function(string $template, array $data, ?string $block): void {
$latte = new Latte\Engine;
// citas konfigurācijas...
// Iestatiet pielāgotu funkciju, lai izvadītu CSRF tokenu
$latte->addFunction('csrf', function() {
$csrfToken = Flight::session()->get('csrf_token');
return new \Latte\Runtime\Html('<input type="hidden" name="csrf_token" value="' . $csrfToken . '">');
});
$latte->render($finalPath, $data, $block);
});
Un tagad savās Latte veidnēs varat izmantot csrf() funkciju, lai izvadītu CSRF tokenu.
<form method="post">
{csrf()}
<!-- citi veidlapas lauki -->
</form>
CSRF tokena pārbaude
CSRF tokenu var pārbaudīt vairākos veidos.
Starpprogrammatūra
// app/Middleware/CsrfMiddleware.php
namespace App\Middleware;
use flight\Engine;
class CsrfMiddleware
{
protected Engine $app;
public function __construct(Engine $app)
{
$this->app = $app;
}
public function before(array $params): void
{
if($this->app->request()->method == 'POST') {
$token = $this->app->request()->data->csrf_token;
if($token !== $this->app->session()->get('csrf_token')) {
$this->app->halt(403, 'Invalid CSRF token');
}
}
}
}
// routes.php
use App\Middleware\CsrfMiddleware;
$router->group('', function ($router) {
$router->get('/users', [ \App\Controller\UserController::class, 'getUsers' ]);
// vairāk maršrutu
}, [CsrfMiddleware::class]);
Notikumu filtri
// Šī starpprogrammatūra pārbauda, vai pieprasījums ir POST pieprasījums, un, ja ir, tā pārbauda, vai CSRF tokens ir derīgs
Flight::before('start', function() {
if(Flight::request()->method == 'POST') {
// iegūstiet csrf tokenu no veidlapas vērtībām
$token = Flight::request()->data->csrf_token;
if($token !== Flight::session()->get('csrf_token')) {
Flight::halt(403, 'Invalid CSRF token');
// vai JSON atbildei
Flight::jsonHalt(['error' => 'Invalid CSRF token'], 403);
}
}
});
Starpsaites skriptošana (XSS)
Starpsaites skriptošana (XSS) ir uzbrukuma veids, kurā ļaunprātīgs veidlapas ievads var ievietot kodu jūsu vietnē. Lielākā daļa šo iespēju rodas no veidlapas vērtībām, ko aizpilda jūsu galalietotāji. Jums nekad nevajadzētu uzticēties lietotāju ievadei! Vienmēr pieņemiet, ka viņi visi ir labākie hakeri pasaulē. Viņi var ievietot ļaunprātīgu JavaScript vai HTML jūsu lapā. Šo kodu var izmantot, lai nozagtu informāciju no jūsu lietotājiem vai veiktu darbības jūsu vietnē. Izmantojot Flight skatu klasi vai veidņu dzinēju, piemēram, Twig vai Latte, jūs varat viegli aizsargāt izvadi, lai novērstu XSS uzbrukumus.
// Pieņemsim, ka lietotājs ir viltīgs un mēģina to izmantot kā savu vārdu
$name = '<script>alert("XSS")</script>';
// Tas atdalīs izvadi (escape)
Flight::view()->set('name', $name);
// Tas izvadīs: <script>alert("XSS")</script>
// Twig (skeleta noklusējums) un Latte pēc noklusējuma automātiski atdala izvadi — dodiet tiem priekšroku, nevis neapstrādātam PHP echo
Flight::render('template', ['name' => $name]);
// Twig: {{ name }} → atdalīts
// Izvairieties no |raw / neatdalītas izvades, ja vien saturs nav pilnībā uzticams
SQL injekcija
SQL injekcija ir uzbrukuma veids, kurā ļaunprātīgs lietotājs var ievietot SQL kodu jūsu datubāzē. To var izmantot, lai nozagtu informāciju no jūsu datubāzes vai veiktu darbības jūsu datubāzē. Atkal jums nekad nevajadzētu uzticēties lietotāju ievadei! Vienmēr pieņemiet, ka viņi ir izslāpuši pēc asinīm. Izmantojiet sagatavotus vaicājumus — SimplePdo palīgmetodes padara to par noklusējuma ceļu.
// Pieņemot, ka Flight::db() ir reģistrēts kā SimplePdo (vai injicējiet SimplePdo kontrolierī)
$statement = Flight::db()->prepare('SELECT * FROM users WHERE username = :username');
$statement->execute([':username' => $username]);
$users = $statement->fetchAll();
// SimplePdo (ieteicams) — vienas rindas vaicājumi ar piesaistītiem parametriem
$users = Flight::db()->fetchAll('SELECT * FROM users WHERE username = :username', [ 'username' => $username ]);
// Tā pati ideja ar ? vietturiem
$users = Flight::db()->fetchAll('SELECT * FROM users WHERE username = ?', [ $username ]);
Skeleta stila kontrolieros dodiet priekšroku konstruktora injekcijai ar SimplePdo, nevis Flight::db(), lai testi un AI ģenerēts kods paliktu konsekventi (DIC).
Nedrošs piemērs
Tālāk redzams, kāpēc mēs izmantojam SQL sagatavotus vaicājumus, lai aizsargātos no nekaitīgiem piemēriem, kā zemāk:
// galalietotājs aizpilda tīmekļa veidlapu.
// kā veidlapas vērtību hakeris ievada aptuveni šo:
$username = "' OR 1=1; -- ";
$sql = "SELECT * FROM users WHERE username = '$username' LIMIT 5";
$users = Flight::db()->fetchAll($sql);
// Pēc vaicājuma izveides tas izskatās šādi
// SELECT * FROM users WHERE username = '' OR 1=1; -- LIMIT 5
// Tas izskatās dīvaini, bet tas ir derīgs vaicājums, kas darbosies. Patiesībā,
// tas ir ļoti izplatīts SQL injekcijas uzbrukums, kas atgriezīs visus lietotājus.
var_dump($users); // tas izdrukās visus datubāzes lietotājus, nevis tikai vienu konkrēto lietotājvārdu
Noslēpumi un konfigurācija
- Ievietojiet noslēpumus
.env(vai īstajā vidē), nevis iekļautajosconfig.phpparaugos. - Skeleta noteikums: burtiskās noklusējuma vērtības
config.php; bootstrap laikā apvienojiet env; nedariet lasiet$_ENVkontrolieros — tā vietā injicējiet konfigurāciju. Skatiet Konfigurācija. - Nekad neiekļaujiet API atslēgas, datubāzes paroles vai sesijas šifrēšanas atslēgas. Norādiet AI rīkus uz
SECURITY.md, lai tie neizdomā nedrošus īsceļus.
JSONP atzvanīšanas validācija
Ja izmantojat Flight Flight::jsonp() metodi, ņemiet vērā, ka Flight pārbauda JSONP atzvanīšanas parametra nosaukumu pret stingru atļauto sarakstu ar regulāro izteiksmi (/^[A-Za-z_$][\w$.]{0,127}$/). Jebkurš atzvanīšanas nosaukums, kas neatbilst šim paraugam, liks Flight izmest izņēmumu, tādējādi novēršot patvaļīga JavaScript ievadīšanu caur ļaunprātīgu atzvanīšanas vērtību.
Šī validācija ir iebūvēta un neprasa papildu konfigurāciju, taču ir vērts par to zināt, atkļūdojot negaidītas kļūdas no JSONP galapunktiem.
CORS
Cross-Origin Resource Sharing (CORS) ir mehānisms, kas ļauj daudzus resursus (piemēram, fontus, JavaScript u.c.) tīmekļa lapā pieprasīt no cita domēna ārpus domēna, no kura resurss nācis. Flight nav iebūvētas funkcionalitātes, taču to var viegli apstrādāt ar āķi, kas tiek palaists pirms Flight::start() metodes izsaukšanas.
// app/Utils/CorsUtil.php (skelets: PascalCase Utils mape → App\Utils)
namespace App\Utils;
use flight\Engine;
class CorsUtil
{
protected Engine $app;
public function __construct(Engine $app)
{
$this->app = $app;
}
public function set(array $params = []): void
{
$request = $this->app->request();
$response = $this->app->response();
if ($request->getVar('HTTP_ORIGIN') !== '') {
$this->allowOrigins();
$response->header('Access-Control-Allow-Credentials', 'true');
$response->header('Access-Control-Max-Age', '86400');
}
if ($request->method === 'OPTIONS') {
if ($request->getVar('HTTP_ACCESS_CONTROL_REQUEST_METHOD') !== '') {
$response->header(
'Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD'
);
}
if ($request->getVar('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') !== '') {
$response->header(
"Access-Control-Allow-Headers",
$request->getVar('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')
);
}
$response->status(200);
$response->send();
exit;
}
}
private function allowOrigins(): void
{
// pielāgojiet savus atļauto resursdatoru sarakstu šeit.
$allowed = [
'capacitor://localhost',
'ionic://localhost',
'http://localhost',
'http://localhost:4200',
'http://localhost:8080',
'http://localhost:8100',
];
$request = $this->app->request();
if (in_array($request->getVar('HTTP_ORIGIN'), $allowed, true) === true) {
$response = $this->app->response();
$response->header("Access-Control-Allow-Origin", $request->getVar('HTTP_ORIGIN'));
}
}
}
// bootstrap / maršruti — izpildīt pirms start
$app = Flight::app();
$cors = new \App\Utils\CorsUtil($app);
$app->before('start', [ $cors, 'set' ]);
Flight konfigurācijas nostiprināšana
Flight atklāj vairākus dzinēja iestatījumus, kuriem ir tieša ietekme uz drošību. Pareiza šo iestatījumu konfigurēšana ir viens no vienkāršākajiem veidiem, kā nostiprināt savu lietojumprogrammu.
flight.allow_method_override
Pēc noklusējuma Flight ļauj klientiem mainīt pieprasījuma HTTP metodi, izmantojot vai nu X-HTTP-Method-Override galveni, vai _method lauku POST pamattekstā. Lai gan tas ir ērti HTML veidlapām, kas var nosūtīt tikai GET/POST, tas var būt bīstami, ja jūs to negaidāt — uzbrucējs varētu viltot DELETE vai PUT pieprasījumus caur parastu veidlapu.
Ja jūsu lietojumprogramma nepaļaujas uz šo uzvedību (piem., veidojat API, ko izmanto mūsdienīgi klienti vai JavaScript priekšgali, kas var nosūtīt jebkuru HTTP metodi), jums tas būtu jāatspējo:
// Savā index.php vai bootstrap failā, pirms Flight::start()
Flight::set('flight.allow_method_override', false);
Noklusējuma vērtība ir true atpakaļsaderības dēļ, taču ieteicams to iestatīt uz false jebkurai lietojumprogrammai, kurai nav tieši nepieciešama aizstāšanas funkcija.
flight.debug
Flight ir flight.debug iestatījums, kas nosaka, vai detalizēta kļūdas informācija (izņēmuma ziņojums, kods un pilna steka izsekojums) tiek parādīta pārlūkprogrammā, kad rodas neapstrādāts izņēmums. Noklusējums ir false, kas nozīmē, ka tiek rādīts tikai vispārīgs ziņojums 500 Internal Server Error — klientam netiek nopludinātas iekšējās detaļas.
Nekad neiespējojiet to uz produkcijas servera. Izmantojiet to tikai lokāli vai staging vidē:
// Drošs tikai lokālai izstrādei — NEKAD produkcijā
Flight::set('flight.debug', true);
Kad flight.debug ir false (noklusējums), jūs joprojām varat reģistrēt kļūdas, iespējojot flight.log_errors:
// Reģistrējiet kļūdas servera pusē, nepadarot tās redzamas klientam
Flight::set('flight.debug', false);
Flight::set('flight.log_errors', true);
Ieteicamā produkcijas konfigurācija
// index.php vai lietots no lietotnes konfigurācijas / bootstrap
Flight::set('flight.allow_method_override', false);
Flight::set('flight.debug', false);
Flight::set('flight.log_errors', true);
Kļūdu apstrāde
Slēpiet sensitīvas kļūdu detaļas produkcijas vidē, lai neizpaustu informāciju uzbrucējiem. Produkcijas vidē reģistrējiet kļūdas, nevis rādiet tās, iestatot display_errors uz 0.
// Savā bootstrap.php vai index.php failā
// pievienojiet to savam app/config/config.php
$environment = ENVIRONMENT;
if ($environment === 'production') {
ini_set('display_errors', 0); // Atspējo kļūdu attēlošanu
ini_set('log_errors', 1); // Tā vietā reģistrē kļūdas
ini_set('error_log', '/path/to/error.log');
}
// Savos maršrutos vai kontrolieros
// Izmantojiet Flight::halt() kontrolētām kļūdu atbildēm
Flight::halt(403, 'Access denied');
Ievades sanitizācija
Nekad neuzticieties lietotāja ievadei. Sanitizējiet to, izmantojot filter_var, pirms apstrādes, lai novērstu ļaunprātīgu datu iekļūšanu. Dodiet priekšroku ievades lasīšanai ar $app->request() (vai Flight::request()), nevis neapstrādātiem $_GET / $_POST lietotnes kodā.
// Pieņemsim, ka ir $_POST pieprasījums ar $_POST['input'] un $_POST['email']
// Sanitizējiet virknes ievadi
$clean_input = filter_var(Flight::request()->data->input, FILTER_SANITIZE_STRING);
// Sanitizējiet e-pasta adresi
$clean_email = filter_var(Flight::request()->data->email, FILTER_SANITIZE_EMAIL);
Paroļu hešēšana
Glabājiet paroles droši un pārbaudiet tās drošā veidā, izmantojot PHP iebūvētās funkcijas, piemēram, password_hash un password_verify. Paroles nekad nedrīkst glabāt vienkāršā tekstā, un tās nedrīkst šifrēt ar atgriezeniskām metodēm. Hešēšana nodrošina, ka pat tad, ja jūsu datubāze tiek kompromitēta, faktiskās paroles paliek aizsargātas.
$password = Flight::request()->data->password;
// Hešējiet paroli, kad to saglabājat (piem., reģistrācijas laikā)
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Pārbaudiet paroli (piem., pieteikšanās laikā)
if (password_verify($password, $stored_hash)) {
// Parole atbilst
}
Pieprasījumu ātruma ierobežošana
Aizsargājieties pret brutāla spēka uzbrukumiem vai pakalpojuma atteikuma uzbrukumiem, ierobežojot pieprasījumu ātrumu ar kešatmiņu.
// Pieņemot, ka flightphp/cache ir instalēts un reģistrēts
// Izmantojot flightphp/cache filtrā
Flight::before('start', function() {
$cache = Flight::cache();
$ip = Flight::request()->ip;
$key = "rate_limit_{$ip}";
$attempts = (int) $cache->retrieve($key);
if ($attempts >= 10) {
Flight::halt(429, 'Too many requests');
}
$cache->set($key, $attempts + 1, 60); // Atiestatīt pēc 60 sekundēm
});
Skatīt arī
- Sesijas - Kā droši pārvaldīt lietotāju sesijas.
- Veidnes - Twig/Latte automātiska izvades atdalīšana un XSS.
- SimplePdo - Datubāzes palīgmetodes ar sagatavotiem vaicājumiem.
- PdoWrapper - Novecojis; izmantojiet SimplePdo jaunam kodam.
- Starpprogrammatūra - Kā izmantot starpprogrammatūru, lai vienkāršotu drošības galveņu pievienošanas procesu.
- Konfigurācija -
.envsalīdzinājumā ar burtisko konfigurāciju, produkcijas karodziņi. - AI un izstrādātāju pieredze - Glabājiet drošības politiku
SECURITY.mdaģentiem. - Atbildes - Kā pielāgot HTTP atbildes ar drošām galvenēm.
- Pieprasījumi - Kā apstrādāt un sanitizēt lietotāja ievadi.
- filter_var - PHP funkcija ievades sanitizācijai.
- password_hash - PHP funkcija drošai paroļu hešēšanai.
- password_verify - PHP funkcija hešēto paroļu pārbaudei.
Problēmu novēršana
- Skatiet iepriekšējo sadaļu "Skatīt arī", lai iegūtu informāciju par problēmu novēršanu saistībā ar Flight Framework komponentu jautājumiem.
- Ja CSP bloķē jūsu skriptus, pievienojiet nonce (skeleta paraugs) vai iekļaujiet atļauto sarakstā konkrētas izcelsmes — neiestatiet
script-src *bez plāna.
Izmaiņu žurnāls
- Dokumentācija — Skeleta
App\Middleware, Twig CSRF/XSS piezīmes, SimplePdo, noslēpumi/.envunSECURITY.mdAI draudzīgiem projektiem. - v3.18.1 - Pievienota Flight konfigurācijas nostiprināšanas sadaļa, kas aptver
flight.allow_method_override,flight.debugun JSONP atzvanīšanas validāciju. - v3.1.0 - Pievienotas sadaļas par CORS, kļūdu apstrādi, ievades sanitizāciju, paroļu hešēšanu un pieprasījumu ātruma ierobežošanu.
- v2.0 - Pievienota izvades atdalīšana noklusējuma skatiem, lai novērstu XSS.
Learn/routing
Maršrutēšana
Pārskats
Maršrutēšana Flight PHP kartē URL modeļus ar atzvanīšanas funkcijām vai klašu metodēm, nodrošinot ātru un vienkāršu pieprasījumu apstrādi. Tā ir veidota ar minimālu papildu slogu, iesācējiem draudzīgu lietošanu un paplašināmību bez ārējām atkarībām.
Izpratne
Maršrutēšana ir pamata mehānisms, kas savieno HTTP pieprasījumus ar jūsu lietojumprogrammas loģiku Flight. Definējot maršrutus, jūs norādāt, kā dažādi URL aktivizē konkrētu kodu — neatkarīgi no tā, vai tas notiek caur funkcijām, klašu metodēm vai kontrolieru darbībām. Flight maršrutēšanas sistēma ir elastīga, atbalstot pamata modeļus, nosauktus parametrus, regulārās izteiksmes un papildu funkcijas, piemēram, atkarību ievadīšanu un resursu maršrutēšanu. Šī pieeja uztur jūsu kodu organizētu un viegli uzturamu, vienlaikus paliekot ātra un vienkārša iesācējiem, kā arī paplašināma pieredzējušiem lietotājiem.
Piezīme: Vēlaties saprast vairāk par maršrutēšanu? Apskatiet lapu "kāpēc ietvars?", lai iegūtu padziļinātu skaidrojumu.
Pamata lietošana
Vienkārša maršruta definēšana
Pamata maršrutēšana Flight tiek veikta, saskaņojot URL modeli ar atzvanīšanas funkciju vai klases un metodes masīvu.
Flight::route('/', function(){
echo 'hello world!';
});
Maršruti tiek saskaņoti to definēšanas secībā. Pirmais maršruts, kas atbilst pieprasījumam, tiks izsaukts.
Funkciju izmantošana kā atzvanīšanas
Atzvanīšana var būt jebkurš objekts, kas ir izsaucams. Tātad varat izmantot parasto funkciju:
function hello() {
echo 'hello world!';
}
Flight::route('/', 'hello');
Klašu un metožu izmantošana kā kontrolieris
Varat izmantot arī klases metodi (statisku vai nestatisku):
class GreetingController {
public function hello() {
echo 'hello world!';
}
}
Flight::route('/', [ 'GreetingController','hello' ]);
// vai
Flight::route('/', [ GreetingController::class, 'hello' ]); // ieteicamā metode
// vai
Flight::route('/', [ 'GreetingController::hello' ]);
// vai
Flight::route('/', [ 'GreetingController->hello' ]);
Vai arī izveidojot objektu vispirms un pēc tam izsaucot metodi:
use flight\Engine;
// GreetingController.php
class GreetingController
{
protected Engine $app
public function __construct(Engine $app) {
$this->app = $app;
$this->name = 'John Doe';
}
public function hello() {
echo "Hello, {$this->name}!";
}
}
// index.php
$app = Flight::app();
$greeting = new GreetingController($app);
Flight::route('/', [ $greeting, 'hello' ]);
Piezīme: Pēc noklusējuma, kad kontrolieris tiek izsaukts ietvara ietvaros,
flight\Engineklase vienmēr tiek ievadīta, ja vien nenorādāt citādi, izmantojot atkarību ievadīšanas konteineru
Metodei specifiska maršrutēšana
Pēc noklusējuma maršruta modeļi tiek saskaņoti ar visām pieprasījuma metodēm. Varat atbildēt uz konkrētām metodēm, novietojot identifikatoru pirms URL.
Flight::route('GET /', function () {
echo 'I received a GET request.';
});
Flight::route('POST /', function () {
echo 'I received a POST request.';
});
// Jūs nevarat izmantot Flight::get() maršrutiem, jo tā ir metode
// mainīgo iegūšanai, nevis maršruta izveidei.
Flight::post('/', function() { /* kods */ });
Flight::patch('/', function() { /* kods */ });
Flight::put('/', function() { /* kods */ });
Flight::delete('/', function() { /* kods */ });
Varat arī kartēt vairākas metodes vienai atzvanīšanai, izmantojot atdalītāju |:
Flight::route('GET|POST /', function () {
echo 'I received either a GET or a POST request.';
});
Īpaša apstrāde HEAD un OPTIONS pieprasījumiem
Flight nodrošina iebūvētu apstrādi HEAD un OPTIONS HTTP pieprasījumiem:
HEAD pieprasījumi
- HEAD pieprasījumi tiek apstrādāti tāpat kā
GETpieprasījumi, bet Flight automātiski noņem atbildes pamattekstu pirms tā nosūtīšanas klientam. - Tas nozīmē, ka varat definēt maršrutu
GET, un HEAD pieprasījumi uz to pašu URL atgriezīs tikai galvenes (bez satura), kā to nosaka HTTP standarti.
Flight::route('GET /info', function() {
echo 'This is some info!';
});
// HEAD pieprasījums uz /info atgriezīs tās pašas galvenes, bet bez pamatteksta.
OPTIONS pieprasījumi
OPTIONS pieprasījumus Flight automātiski apstrādā jebkuram definētam maršrutam.
- Kad tiek saņemts OPTIONS pieprasījums, Flight atbild ar
204 No Contentstatusu unAllowgalveni, kurā uzskaitītas visas atbalstītās HTTP metodes šim maršrutam. - Jums nav jādefinē atsevišķs maršruts OPTIONS.
// Maršrutam, kas definēts kā:
Flight::route('GET|POST /users', function() { /* ... */ });
// OPTIONS pieprasījums uz /users atbildēs ar:
//
// Statuss: 204 No Content
// Allow: GET, POST, HEAD, OPTIONS
Router objekta izmantošana
Papildus varat iegūt Router objektu, kuram ir dažas palīgmetodes, ko varat izmantot:
$router = Flight::router();
// kartē visas metodes tāpat kā Flight::route()
$router->map('/', function() {
echo 'hello world!';
});
// GET pieprasījums
$router->get('/users', function() {
echo 'users';
});
$router->post('/users', function() { /* kods */});
$router->put('/users/update/@id', function() { /* kods */});
$router->delete('/users/@id', function() { /* kods */});
$router->patch('/users/@id', function() { /* kods */});
Regulārās izteiksmes (Regex)
Maršrutos varat izmantot regulārās izteiksmes:
Flight::route('/user/[0-9]+', function () {
// Šis atbilst /user/1234
});
Lai gan šī metode ir pieejama, ieteicams izmantot nosauktus parametrus vai nosauktus parametrus ar regulārajām izteiksmēm, jo tie ir lasāmāki un vieglāk uzturami.
Nosauktie parametri
Maršrutos varat norādīt nosauktus parametrus, kas tiks nodoti jūsu atzvanīšanas funkcijai. Tas vairāk ir paredzēts maršruta lasāmībai nekā kam citam. Lūdzu, skatiet sadaļu zemāk par svarīgu piezīmi.
Flight::route('/@name/@id', function (string $name, string $id) {
echo "hello, $name ($id)!";
});
Varat iekļaut arī regulārās izteiksmes ar saviem nosauktajiem parametriem, izmantojot atdalītāju ::
Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) {
// Šis atbilst /bob/123
// Bet neatbilst /bob/12345
});
Piezīme: Regulārās izteiksmes grupu
()saskaņošana ar pozicionālajiem parametriem netiek atbalstīta. Piemēram::'\(
Svarīga piezīme
Lai gan iepriekšējā piemērā šķiet, ka @name ir tieši saistīts ar mainīgo $name, tas tā nav. Parametru secība atzvanīšanas funkcijā nosaka to, kas tiek nodots. Ja jūs apmainītu parametru secību atzvanīšanas funkcijā, mainīgie tiktu apmainīti arī. Šeit ir piemērs:
Flight::route('/@name/@id', function (string $id, string $name) {
echo "hello, $name ($id)!";
});
Un, ja jūs dotos uz šādu URL: /bob/123, izvade būtu hello, 123 (bob)!.
Esiet uzmanīgi, kad veidojat savus maršrutus un atzvanīšanas funkcijas!
Neobligātie parametri
Varat norādīt nosauktus parametrus, kas nav obligāti saskaņošanai, iekļaujot segmentus iekavās.
Flight::route(
'/blog(/@year(/@month(/@day)))',
function(?string $year, ?string $month, ?string $day) {
// Šis atbilst šādiem URL:
// /blog/2012/12/10
// /blog/2012/12
// /blog/2012
// /blog
}
);
Jebkuri neobligātie parametri, kas netiek saskaņoti, tiks nodoti kā NULL.
Aizstājējzīmju maršrutēšana
Saskaņošana tiek veikta tikai atsevišķiem URL segmentiem. Ja vēlaties saskaņot vairākus segmentus, varat izmantot aizstājējzīmi *.
Flight::route('/blog/*', function () {
// Šis atbilst /blog/2000/02/01
});
Lai novirzītu visus pieprasījumus uz vienu atzvanīšanu, varat rīkoties šādi:
Flight::route('*', function () {
// Dariet kaut ko
});
404 Nav atrasts apstrādātājs
Pēc noklusējuma, ja URL nevar atrast, Flight nosūtīs HTTP 404 Not Found atbildi, kas ir ļoti vienkārša un parasta.
Ja vēlaties pielāgotāku 404 atbildi, varat kartēt savu notFound metodi:
Flight::map('notFound', function() {
$url = Flight::request()->url;
// Varat arī izmantot Flight::render() ar pielāgotu veidni.
$output = <<<HTML
<h1>Mana pielāgotā 404 Nav atrasts</h1>
<h3>Lapa, kuru pieprasījāt ({$url}), netika atrasta.</h3>
HTML;
$this->response()
->clearBody()
->status(404)
->write($output)
->send();
});
Metode nav atrasta apstrādātājs
Pēc noklusējuma, ja URL tiek atrasts, bet metode nav atļauta, Flight nosūtīs HTTP 405 Method Not Allowed atbildi, kas ir ļoti vienkārša un parasta (piem., Method Not Allowed. Allowed Methods are: GET, POST). Tā arī iekļaus Allow galveni ar atļautajām metodēm šim URL.
Ja vēlaties pielāgotāku 405 atbildi, varat kartēt savu methodNotFound metodi:
use flight\net\Route;
Flight::map('methodNotFound', function(Route $route) {
$url = Flight::request()->url;
$methods = implode(', ', $route->methods);
// Varat arī izmantot Flight::render() ar pielāgotu veidni.
$output = <<<HTML
<h1>Mana pielāgotā 405 Metode nav atļauta</h1>
<h3>Metode, kuru pieprasījāt ({$url}), nav atļauta.</h3>
<p>Atļautās metodes ir: {$methods}</p>
HTML;
$this->response()
->clearBody()
->status(405)
->setHeader('Allow', $methods)
->write($output)
->send();
});
Papildu lietošana
Atkarību ievadīšana maršrutos
Ja vēlaties izmantot atkarību ievadīšanu caur konteineru (PSR-11, PHP-DI, Dice utt.), vienīgais maršrutu veids, kur tas ir pieejams, ir vai nu pašam tieši izveidot objektu un izmantot konteineru sava objekta izveidei, vai arī varat izmantot virknes, lai definētu klasi un izsaucamo metodi. Plašāku informāciju skatiet lapā Atkarību ievadīšana.
Šeit ir ātrs piemērs:
use flight\database\SimplePdo;
// Greeting.php
class Greeting
{
protected SimplePdo $db;
public function __construct(SimplePdo $db) {
$this->db = $db;
}
public function hello(int $id) {
// darīt kaut ko ar $this->db
$name = $this->db->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]);
echo "Hello, world! My name is {$name}!";
}
}
// index.php
// Iestatiet konteineru ar nepieciešamajiem parametriem
// Skatiet lapu Par atkarību ievadīšanu, lai iegūtu vairāk informācijas par PSR-11
$dice = new \Dice\Dice();
// Neaizmirstiet pārdefinēt mainīgo ar '$dice = '!!!!!
$dice = $dice->addRule(SimplePdo::class, [
'shared' => true,
'constructParams' => [
'mysql:host=localhost;dbname=test',
'root',
'password'
]
]);
// Reģistrējiet konteinera apstrādātāju
Flight::registerContainerHandler(function($class, $params) use ($dice) {
return $dice->create($class, $params);
});
// Maršruti kā parasti
Flight::route('/hello/@id', [ 'Greeting', 'hello' ]);
// vai
Flight::route('/hello/@id', 'Greeting->hello');
// vai
Flight::route('/hello/@id', 'Greeting::hello');
Flight::start();
Izpildes nodošana nākamajam maršrutam
Novecojis
Varat nodot izpildi nākamajam atbilstošajam maršrutam, atgriežot true no savas atzvanīšanas funkcijas.
Flight::route('/user/@name', function (string $name) {
// Pārbaudiet kādu nosacījumu
if ($name !== "Bob") {
// Turpiniet uz nākamo maršrutu
return true;
}
});
Flight::route('/user/*', function () {
// Šis tiks izsaukts
});
Tagad ieteicams izmantot starpprogrammatūru, lai apstrādātu sarežģītus gadījumus, piemēram, šo.
Maršruta aizstājvārdi
Piešķirot maršrutam aizstājvārdu, vēlāk varat šo aizstājvārdu dinamiski izsaukt savā lietotnē, lai to ģenerētu vēlāk kodā (piem., saite HTML veidnē vai pāradresācijas URL ģenerēšana).
Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view');
// vai
Flight::route('/users/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view');
// vēlāk kaut kur kodā
class UserController {
public function update() {
// kods lietotāja saglabāšanai...
$id = $user['id']; // piemēram, 5
$redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // atgriezīs '/users/5'
Flight::redirect($redirectUrl);
}
}
Tas ir īpaši noderīgi, ja jūsu URL gadās mainīties. Iepriekšējā piemērā pieņemsim, ka lietotāji tika pārvietoti uz /admin/users/@id vietā.
Ar aizstājvārdu maršrutam jums vairs nav jāatrod visi vecie URL savā kodā un jāmaina tie, jo aizstājvārds tagad atgriezīs /admin/users/5, kā iepriekšējā piemērā.
Maršruta aizstājvārdi darbojas arī grupās:
Flight::group('/users', function() {
Flight::route('/@id', function($id) { echo 'user:'.$id; }, false, 'user_view');
// vai
Flight::route('/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view');
});
Maršruta informācijas apskate
Ja vēlaties apskatīt atbilstošā maršruta informāciju, to var izdarīt divos veidos:
- Varat izmantot rekvizītu
executedRouteuzFlight::router()objekta. - Varat pieprasīt, lai maršruta objekts tiktu nodots jūsu atzvanīšanai, nododot
truekā trešo parametru maršruta metodē. Maršruta objekts vienmēr būs pēdējais parametrs, kas tiek nodots jūsu atzvanīšanas funkcijai.
executedRoute
Flight::route('/', function() {
$route = Flight::router()->executedRoute;
// Dariet kaut ko ar $route
// Saskaņoto HTTP metožu masīvs
$route->methods;
// Nosaukto parametru masīvs
$route->params;
// Atbilstošā regulārā izteiksme
$route->regex;
// Satur jebkura '*' saturu, kas izmantots URL modelī
$route->splat;
// Parāda URL ceļu... ja jums tiešām tas ir nepieciešams
$route->pattern;
// Parāda, kāda starpprogrammatūra ir piešķirta šim
$route->middleware;
// Parāda šim maršrutam piešķirto aizstājvārdu
$route->alias;
});
Piezīme: Rekvizīts
executedRoutetiks iestatīts tikai pēc tam, kad maršruts ir izpildīts. Ja mēģināsiet tam piekļūt pirms maršruta izpildes, tas būsNULL. Varat izmantotexecutedRoutearī starpprogrammatūrā!
Nododiet true maršruta definīcijā
Flight::route('/', function(\flight\net\Route $route) {
// Saskaņoto HTTP metožu masīvs
$route->methods;
// Nosaukto parametru masīvs
$route->params;
// Atbilstošā regulārā izteiksme
$route->regex;
// Satur jebkura '*' saturu, kas izmantots URL modelī
$route->splat;
// Parāda URL ceļu... ja jums tiešām tas ir nepieciešams
$route->pattern;
// Parāda, kāda starpprogrammatūra ir piešķirta šim
$route->middleware;
// Parāda šim maršrutam piešķirto aizstājvārdu
$route->alias;
}, true);// <-- Šis true parametrs to nodrošina
Maršrutu grupēšana un starpprogrammatūra
Var būt gadījumi, kad vēlaties grupēt saistītus maršrutus (piemēram, /api/v1).
To var izdarīt, izmantojot metodi group:
Flight::group('/api/v1', function () {
Flight::route('/users', function () {
// Atbilst /api/v1/users
});
Flight::route('/posts', function () {
// Atbilst /api/v1/posts
});
});
Varat pat ligzdot grupu grupas:
Flight::group('/api', function () {
Flight::group('/v1', function () {
// Flight::get() iegūst mainīgos, tas neiestata maršrutu! Skatiet objekta kontekstu zemāk
Flight::route('GET /users', function () {
// Atbilst GET /api/v1/users
});
Flight::post('/posts', function () {
// Atbilst POST /api/v1/posts
});
Flight::put('/posts/1', function () {
// Atbilst PUT /api/v1/posts
});
});
Flight::group('/v2', function () {
// Flight::get() iegūst mainīgos, tas neiestata maršrutu! Skatiet objekta kontekstu zemāk
Flight::route('GET /users', function () {
// Atbilst GET /api/v2/users
});
});
});
Grupēšana ar objekta kontekstu
Varat joprojām izmantot maršrutu grupēšanu ar Engine objektu šādā veidā:
$app = Flight::app();
$app->group('/api/v1', function (Router $router) {
// izmantojiet $router mainīgo
$router->get('/users', function () {
// Atbilst GET /api/v1/users
});
$router->post('/posts', function () {
// Atbilst POST /api/v1/posts
});
});
Piezīme: Šī ir ieteicamā metode maršrutu un grupu definēšanai ar
$routerobjektu.
Grupēšana ar starpprogrammatūru
Varat arī piešķirt starpprogrammatūru maršrutu grupai:
Flight::group('/api/v1', function () {
Flight::route('/users', function () {
// Atbilst /api/v1/users
});
}, [ MyAuthMiddleware::class ]); // vai [ new MyAuthMiddleware() ], ja vēlaties izmantot instanci
Sīkāku informāciju skatiet lapā grupas starpprogrammatūra.
Resursu maršrutēšana
Varat izveidot maršrutu kopu resursam, izmantojot metodi resource. Tas izveidos maršrutu kopu resursam, kas atbilst RESTful konvencijām.
Lai izveidotu resursu, rīkojieties šādi:
Flight::resource('/users', UsersController::class);
Un fonā tiks izveidoti šādi maršruti:
[
'index' => 'GET /users',
'create' => 'GET /users/create',
'store' => 'POST /users',
'show' => 'GET /users/@id',
'edit' => 'GET /users/@id/edit',
'update' => 'PUT /users/@id',
'destroy' => 'DELETE /users/@id'
]
Un jūsu kontrolieris izmantos šādas metodes:
class UsersController
{
public function index(): void
{
}
public function show(string $id): void
{
}
public function create(): void
{
}
public function store(): void
{
}
public function edit(string $id): void
{
}
public function update(string $id): void
{
}
public function destroy(string $id): void
{
}
}
Piezīme: Jūs varat apskatīt jaunpievienotos maršrutus ar
runway, izpildotphp runway routes.
Resursu maršrutu pielāgošana
Ir dažas iespējas, kā konfigurēt resursu maršrutus.
Aizstājvārda bāze
Varat konfigurēt aliasBase. Pēc noklusējuma aizstājvārds ir pēdējā norādītā URL daļa.
Piemēram, /users/ rezultātā aliasBase būs users. Kad šie maršruti tiek izveidoti, aizstājvārdi ir users.index, users.create utt. Ja vēlaties mainīt aizstājvārdu, iestatiet aliasBase uz vēlamo vērtību.
Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]);
Only un Except
Varat arī norādīt, kurus maršrutus vēlaties izveidot, izmantojot opcijas only un except.
// Iekļaujiet tikai šīs metodes un izslēdziet pārējās
Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' ] ]);
// Izslēdziet tikai šīs metodes un iekļaujiet pārējās
Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]);
Tās būtībā ir iekļaušanas un izslēgšanas opcijas, lai jūs varētu norādīt, kurus maršrutus vēlaties izveidot.
Starpprogrammatūra
Varat arī norādīt starpprogrammatūru, kas jāpalaiž katram maršrutam, kas izveidots ar resource metodi.
Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]);
Straumēšanas atbildes
Tagad varat straumēt atbildes klientam, izmantojot stream() vai streamWithHeaders().
Tas ir noderīgi, lai nosūtītu lielus failus, ilgstošus procesus vai ģenerētu lielas atbildes. Maršruta straumēšana tiek apstrādāta nedaudz savādāk nekā parastais maršruts.
Piezīme: Straumēšanas atbildes ir pieejamas tikai tad, ja
flight.v2.output_bufferingir iestatīts uzfalse.
Straumēšana ar manuālām galvenēm
Varat straumēt atbildi klientam, izmantojot metodi stream() maršrutā. Ja to darāt, jums pašam jāiestata visas galvenes pirms jebko izvadāt klientam.
Tas tiek darīts ar PHP funkciju header() vai Flight::response()->setRealHeader() metodi.
Flight::route('/@filename', function($filename) {
$response = Flight::response();
// protams, jūs sanitizētu ceļu un tamlīdzīgi.
$fileNameSafe = basename($filename);
// Ja jums ir papildu galvenes, kas jāiestata pēc maršruta izpildes,
// tās jādefinē pirms jebkas tiek izvadīts.
// Tām visām jābūt tiešam izsaukumam uz header() funkciju vai
// izsaukumam uz Flight::response()->setRealHeader()
header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"');
// vai
$response->setRealHeader('Content-Disposition: attachment; filename="'.$fileNameSafe.'"');
$filePath = '/some/path/to/files/'.$fileNameSafe;
if (!is_readable($filePath)) {
Flight::halt(404, 'File not found');
}
// manuāli iestatiet satura garumu, ja vēlaties
header('Content-Length: '.filesize($filePath));
// vai
$response->setRealHeader('Content-Length: '.filesize($filePath));
// Straumējiet failu klientam, kamēr tas tiek lasīts
readfile($filePath);
// Šī ir burvju rindiņa šeit
})->stream();
Straumēšana ar galvenēm
Varat arī izmantot metodi streamWithHeaders(), lai iestatītu galvenes pirms straumēšanas sākšanas.
Flight::route('/stream-users', function() {
// šeit varat pievienot jebkuras papildu galvenes, kuras vēlaties
// tikai jāizmanto header() vai Flight::response()->setRealHeader()
// neatkarīgi no tā, kā iegūstat savus datus, tikai kā piemērs...
$users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users");
echo '{';
$user_count = count($users);
while($user = $users_stmt->fetch(PDO::FETCH_ASSOC)) {
echo json_encode($user);
if(--$user_count > 0) {
echo ',';
}
// Tas ir nepieciešams, lai nosūtītu datus klientam
ob_flush();
}
echo '}';
// Šādi jūs iestatīsiet galvenes pirms straumēšanas sākšanas.
})->streamWithHeaders([
'Content-Type' => 'application/json',
'Content-Disposition' => 'attachment; filename="users.json"',
// neobligāts statusa kods, pēc noklusējuma 200
'status' => 200
]);
Skatīt arī
- Starpprogrammatūra - Starpprogrammatūras izmantošana ar maršrutiem autentifikācijai, žurnālfailiem utt.
- Atkarību ievadīšana - Objektu izveides un pārvaldības vienkāršošana maršrutos.
- Kāpēc ietvars? - Izpratne par tāda ietvara kā Flight izmantošanas priekšrocībām.
- Paplašināšana - Kā paplašināt Flight ar savu funkcionalitāti, ieskaitot
notFoundmetodi. - php.net: preg_match - PHP funkcija regulāro izteiksmju saskaņošanai.
Problēmu novēršana
- Maršruta parametri tiek saskaņoti pēc secības, nevis pēc nosaukuma. Pārliecinieties, ka atzvanīšanas funkcijas parametru secība atbilst maršruta definīcijai.
Flight::get()lietošana nedefinē maršrutu; maršrutēšanai izmantojietFlight::route('GET /...')vai Router objekta kontekstu grupās (piem.,$router->get(...)).- Rekvizīts
executedRoutetiek iestatīts tikai pēc maršruta izpildes; pirms izpildes tas irNULL. - Straumēšanai ir jāatspējo Flight mantotā izejas buferizācijas funkcionalitāte (
flight.v2.output_buffering = false). - Atkarību ievadīšanai tikai dažas maršruta definīcijas atbalsta konteinerā balstītu instancēšanu.
404 Nav atrasts vai negaidīta maršruta darbība
Ja redzat 404 Nav atrasts kļūdu (bet jūs zvērat uz savu dzīvību, ka tā tur tiešām ir un tā nav drukas kļūda), tas faktiski var būt problēma ar to, ka maršruta galapunktā atgriežat vērtību, nevis vienkārši to izvadāt. Iemesls tam ir apzināts, bet tas var pārsteigt dažus izstrādātājus.
Flight::route('/hello', function(){
// Tas var izraisīt 404 Nav atrasts kļūdu
return 'Hello World';
});
// Tas, ko jūs, iespējams, vēlaties
Flight::route('/hello', function(){
echo 'Hello World';
});
Iemesls tam ir īpašs mehānisms, kas iebūvēts maršrutētājā un kas apstrādā atgriezto izvadi kā signālu "doties uz nākamo maršrutu". Šo darbību varat redzēt dokumentētu sadaļā Maršrutēšana.
Izmaiņu žurnāls
- v3: Pievienota resursu maršrutēšana, maršruta aizstājvārdi un straumēšanas atbalsts, maršrutu grupas un starpprogrammatūras atbalsts.
- v1: Lielākā daļa pamata funkciju ir pieejamas.
Learn/learn
Uzziniet par Flight
Flight ir ātrs, vienkāršs un paplašināms PHP ietvars. Tas ir diezgan daudzpusīgs, un to var izmantot jebkura veida tīmekļa lietojumprogrammu izveidei. Tas ir izstrādāts, domājot par vienkāršību, un ir rakstīts tā, lai to būtu viegli saprast un lietot — gan cilvēkiem, gan AI kodēšanas palīgiem.
Piezīme: Jūs redzēsiet piemērus, kuros
Flight::tiek izmantots kā statisks mainīgais, un dažus, kuros tiek izmantots$app->Engine objekts. Abi savstarpēji aizvietojami.$appun$this->appkontrolierī/starpprogrammatūrā ir Flight komandas ieteiktā pieeja (un to oficiālais skeletons +AGENTS.mdnosaka kā standartu jauniem projektiem).
Pamatkomponenti
Maršrutēšana
Uzziniet, kā pārvaldīt maršrutus savā tīmekļa lietojumprogrammā. Tas ietver arī maršrutu grupēšanu, maršrutu parametrus un starpprogrammatūru.
Starpprogrammatūra
Uzziniet, kā izmantot starpprogrammatūru, lai filtrētu pieprasījumus un atbildes savā lietojumprogrammā.
Automātiskā ielāde
Uzziniet, kā automātiski ielādēt savas klases. Mapes reģistram jāatbilst jūsu vārdtelpām—skeletons izmanto App\ un PascalCase mapes, piemēram, app/Controller/.
Pieprasījumi
Uzziniet, kā apstrādāt pieprasījumus un atbildes savā lietojumprogrammā.
Atbildes
Uzziniet, kā nosūtīt atbildes saviem lietotājiem.
HTML veidnes
Uzziniet, kā renderēt HTML, izmantojot Twig (skeletona noklusējums), Latte vai citus dzinējus—ne tikai iebūvētos PHP skatus.
Drošība
Uzziniet, kā aizsargāt savu lietojumprogrammu no izplatītiem drošības apdraudējumiem.
Konfigurācija
Uzziniet, kā konfigurēt ietvaru savai lietojumprogrammai.
Notikumu pārvaldnieks
Uzziniet, kā izmantot notikumu sistēmu, lai savai lietojumprogrammai pievienotu pielāgotus notikumus.
Flight paplašināšana
Uzziniet, kā paplašināt ietvaru, pievienojot savas metodes un klases.
Metodes āķi un filtrēšana
Uzziniet, kā pievienot notikumu āķus savām metodēm un iekšējām ietvara metodēm.
Atkarību injekcijas konteiners (DIC)
Uzziniet, kā izmantot atkarību injekcijas konteinerus (DIC), lai pārvaldītu savas lietojumprogrammas atkarības.
Palīgklases
Kolekcijas
Kolekcijas tiek izmantotas, lai saglabātu datus un būtu pieejamas kā masīvs vai kā objekts, lai atvieglotu lietošanu.
JSON ietinējs
Tajā ir dažas vienkāršas funkcijas, lai jūsu JSON kodēšana un atkodēšana būtu konsekventa.
SimplePdo
PDO reizēm var sagādāt vairāk galvassāpju, nekā nepieciešams. SimplePdo ir mūsdienīga PDO palīgklase ar ērtām metodēm, piemēram, insert(), update(), delete() un transaction(), lai datubāzes darbības būtu daudz vienkāršākas.
PdoWrapper (Novecojis)
Sākotnējais PDO ietinējs ir novecojis no v3.18.0. Lūdzu, tā vietā izmantojiet SimplePdo.
Augšupielādēto failu apstrādātājs
Vienkārša klase, kas palīdz pārvaldīt augšupielādētos failus un pārvietot tos uz pastāvīgu atrašanās vietu.
Svarīgi jēdzieni
Kāpēc ietvars?
Šeit ir īss raksts par to, kāpēc jums vajadzētu izmantot ietvaru. Ir labi saprast ietvaru izmantošanas priekšrocības, pirms sākat to lietot.
Turklāt izcilu apmācību ir izveidojis @lubiana. Lai gan tajā nav detalizēti aprakstīts tieši Flight, šī rokasgrāmata palīdzēs jums saprast dažus galvenos jēdzienus, kas saistīti ar ietvariem, un kāpēc tos ir izdevīgi izmantot. Apmācību varat atrast šeit.
Flight salīdzinājumā ar citiem ietvariem
Ja pārejat no cita ietvara, piemēram, Laravel, Slim, Fat-Free vai Symfony, uz Flight, šī lapa palīdzēs jums saprast atšķirības starp tiem.
Citas tēmas
Vienību testēšana
Sekojiet šai rokasgrāmatai, lai uzzinātu, kā veikt vienību testus savam Flight kodam, lai tas būtu ļoti stabils.
AI un izstrādātāja pieredze
Flight ir veidots, lai sadarbotos ar programmēšanas LLM: AGENTS.md, Runway ai:* komandas un viens skaidrs skeletona izkārtojums, lai aģenti paliktu uz pareizā ceļa.
Pāreja no v2 uz v3
Atpakaļsaderība lielākoties ir saglabāta, taču ir dažas izmaiņas, par kurām jums jāzina, pārejot no v2 uz v3.
Learn/unit_testing
Vienību testēšana
Pārskats
Vienību testēšana Flight lietotnē palīdz nodrošināt, ka jūsu lietotne darbojas, kā paredzēts, agri atklāt kļūdas un padarīt koda bāzi vieglāk uzturējamu. Flight ir izstrādāts, lai nevainojami sadarbotos ar PHPUnit, kas ir populārākais PHP testēšanas ietvars.
Izpratne
Vienību testi pārbauda atsevišķu jūsu lietotnes daļu (piemēram, kontrolleru vai pakalpojumu) uzvedību izolēti. Flight kontekstā tas nozīmē pārbaudīt, kā jūsu maršruti, kontrolleri un loģika reaģē uz dažādiem ievaddatiem, nepaļaujoties uz globālo stāvokli vai reāliem ārējiem pakalpojumiem.
Galvenie principi:
- Testējiet uzvedību, nevis ieviešanu: Koncentrējieties uz to, ko jūsu kods dara, nevis to, kā tas to dara.
- Izvairieties no globālā stāvokļa: Izmantojiet atkarību injekciju, nevis
Flight::set()vaiFlight::get(). - Mockojiet ārējos pakalpojumus: Aizstājiet tādas lietas kā datu bāzes vai e-pasta sūtītājus ar testa aizstājējiem.
- Saglabājiet testus ātrus un fokusētus: Vienību testiem nevajadzētu pieskarties reālām datu bāzēm vai API.
Pamata lietošana
PHPUnit iestatīšana
- Instalējiet PHPUnit ar Composer:
composer require --dev phpunit/phpunit - Izveidojiet
testsdirektoriju jūsu projekta saknē. - Pievienojiet testa skriptu savam
composer.json:"scripts": { "test": "phpunit --configuration phpunit.xml" } - Izveidojiet
phpunit.xmlfailu:<?xml version="1.0" encoding="UTF-8"?> <phpunit bootstrap="vendor/autoload.php"> <testsuites> <testsuite name="Flight Tests"> <directory>tests</directory> </testsuite> </testsuites> </phpunit>
Tagad varat palaist savus testus ar composer test.
Vienkārša maršruta apstrādātāja testēšana
Pieņemsim, ka jums ir maršruts, kas validē e-pasta adresi:
// index.php
$app->route('POST /register', [ UserController::class, 'register' ]);
// UserController.php
class UserController {
protected $app;
public function __construct(flight\Engine $app) {
$this->app = $app;
}
public function register() {
$email = $this->app->request()->data->email;
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return $this->app->json(['status' => 'error', 'message' => 'Invalid email']);
}
return $this->app->json(['status' => 'success', 'message' => 'Valid email']);
}
}
Vienkāršs tests šim kontrollerim:
use PHPUnit\Framework\TestCase;
use flight\Engine;
class UserControllerTest extends TestCase {
public function testValidEmailReturnsSuccess() {
$app = new Engine();
$app->request()->data->email = 'test@example.com';
$controller = new UserController($app);
$controller->register();
$response = $app->response()->getBody();
$output = json_decode($response, true);
$this->assertEquals('success', $output['status']);
$this->assertEquals('Valid email', $output['message']);
}
public function testInvalidEmailReturnsError() {
$app = new Engine();
$app->request()->data->email = 'invalid-email';
$controller = new UserController($app);
$controller->register();
$response = $app->response()->getBody();
$output = json_decode($response, true);
$this->assertEquals('error', $output['status']);
$this->assertEquals('Invalid email', $output['message']);
}
}
Padomi:
- Imitējiet POST datus, izmantojot
$app->request()->data. - Izvairieties izmantot
Flight::statiskos elementus savos testos — izmantojiet$appinstanci.
Atkarību injekcijas izmantošana testējamiem kontrolleriem
Ievadiet atkarības (piemēram, datu bāzi vai e-pasta sūtītāju) savos kontrolleros, lai tos būtu viegli mockot testos:
use flight\database\SimplePdo;
class UserController {
protected $app;
protected $db;
protected $mailer;
public function __construct($app, $db, $mailer) {
$this->app = $app;
$this->db = $db;
$this->mailer = $mailer;
}
public function register() {
$email = $this->app->request()->data->email;
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return $this->app->json(['status' => 'error', 'message' => 'Invalid email']);
}
$this->db->runQuery('INSERT INTO users (email) VALUES (?)', [$email]);
$this->mailer->sendWelcome($email);
return $this->app->json(['status' => 'success', 'message' => 'User registered']);
}
}
Un tests ar mock objektiem:
use PHPUnit\Framework\TestCase;
class UserControllerDICTest extends TestCase {
public function testValidEmailSavesAndSendsEmail() {
$mockDb = $this->createMock(flight\database\SimplePdo::class);
$mockDb->method('runQuery')->willReturn(true);
$mockMailer = new class {
public $sentEmail = null;
public function sendWelcome($email) { $this->sentEmail = $email; return true; }
};
$app = new flight\Engine();
$app->request()->data->email = 'test@example.com';
$controller = new UserController($app, $mockDb, $mockMailer);
$controller->register();
$response = $app->response()->getBody();
$result = json_decode($response, true);
$this->assertEquals('success', $result['status']);
$this->assertEquals('User registered', $result['message']);
$this->assertEquals('test@example.com', $mockMailer->sentEmail);
}
}
Papildu lietošana
- Mockošana: Izmantojiet PHPUnit iebūvētos mock objektus vai anonīmas klases, lai aizstātu atkarības.
- Kontrolleru tieša testēšana: Izveidojiet kontrolleru instanci ar jaunu
Engineun mockojiet atkarības. - Izvairieties no pārmērīgas mockošanas: Ļaujiet reālajai loģikai darboties, kur iespējams; mockojiet tikai ārējos pakalpojumus.
Skatīt arī
- Vienību testēšanas ceļvedis - Visaptverošs ceļvedis par vienību testēšanas labāko praksi.
- Atkarību injekcijas konteiners - Kā izmantot DIC, lai pārvaldītu atkarības un uzlabotu testējamību.
- Paplašināšana - Kā pievienot savus palīgus vai pārdefinēt pamata klases.
- SimplePdo - Vienkāršo datu bāzes mijiedarbību un ir vieglāk mockojams testos.
- Pieprasījumi - HTTP pieprasījumu apstrāde Flight.
- Atbildes - Atbilžu sūtīšana lietotājiem.
- Vienību testēšana un SOLID principi - Uzziniet, kā SOLID principi var uzlabot jūsu vienību testus.
Problēmu novēršana
- Izvairieties no globālā stāvokļa (
Flight::set(),$_SESSIONutt.) izmantošanas savā kodā un testos. - Ja jūsu testi ir lēni, iespējams, rakstāt integrācijas testus — mockojiet ārējos pakalpojumus, lai vienību testi būtu ātri.
- Ja testu iestatīšana ir sarežģīta, apsveriet iespēju refaktorēt savu kodu, lai izmantotu atkarību injekciju.
Izmaiņu žurnāls
- v3.15.0 - Pievienoti piemēri atkarību injekcijai un mockošanai.
Learn/flight_vs_symfony
Flight pret Symfoniju
Kas ir Symfony?
Symfony ir kopums ar pārlietojamiem PHP komponentiem un PHP ietvars tīmekļa projektiem.
Standarta pamatne, uz kuras tiek izveidotas labākās PHP lietojumprogrammas. Izvēlieties jebkuru no 50 pieejamajiem neatkarīgajiem komponentiem savām lietojumprogrammām.
Paātriniet jūsu PHP tīmekļa lietojumprogrammu izveidi un uzturēšanu. Beidziet atkārtojošos koda rakstīšanas uzdevumus un baudiet kontroles pār savu kodu priekšrocības.
Plusi salīdzinājumā ar Flight
- Symfony ir milzīga ekosistēma ar attīstītājiem un moduļiem, kas var tikt izmantoti, lai atrisinātu kopējas problēmas.
- Symfony ir pilnībā iekļauts ORM (Doctrine), kas var tikt izmantots, lai mijiedarbotos ar jūsu datubāzi.
- Symfony ir liels daudzums dokumentācijas un pamācību, kas var tikt izmantotas, lai iemācītos ietvaru.
- Symfony piedāvā podkāstus, konferences, sapulces, video un citus resursus, kas var tikt izmantoti, lai iemācītos ietvaru.
- Symfony ir vērsts uz pieredzējušu izstrādātāju, kurš vēlas izveidot pilnīgi iekļaujošu uzņēmumu tīmekļa lietojumprogrammu.
Mīnusi salīdzinājumā ar Flight
- Symfony zem kapuces darbojas daudz vairāk nekā Flight. Tas nāk ar dramatisku veiktspējas cenu. Skatiet TechEmpower salīdzinājumus lai iegūtu vairāk informācijas.
- Flight ir vērsts uz izstrādātāju, kurš vēlas izveidot vieglu, ātru un viegli lietojamu tīmekļa lietojumprogrammu.
- Flight ir vērsts uz vienkāršību un lietojamību.
- Viena no Flight pamata funkcijām ir tā, ka tā labākais darīs, lai uzturētu atpakaļējo saderību.
- Flight nav atkarīgs no citiem komponentiem, kamēr Symfony ir daudz atkarību
- Flight ir domāts izstrādātājiem, kuri iegrimst ietvaru jomā pirmo reizi.
- Flight arī var veidot uzņēmējdarbības līmeņa lietojumprogrammas, bet tam nav tik daudz piemēru un pamācību kā Symfony. Tas prasīs arī vairāk disciplīnas no izstrādātāja puses, lai saglabātu lietas kārtībā un labi strukturētu.
- Flight dod izstrādātājam lielāku kontroli pār lietojumprogrammu, kamēr Symfony var slēpties aiz kameru un veikt kaut kādus brīnumus.
Learn/flight_vs_another_framework
Salīdzinot Flight ar citu ietvaru
Ja jūs pārietat no cita ietvara, piemēram, Laravel, Slim, Fat-Free vai Symfony uz Flight, šī lapa palīdzēs jums saprast atšķirības starp abiem.
Laravel
Laravel ir pilnīgi iezīmēts ietvars, kuram ir visas papardes un brīnumaini izstrādātāja vērsti ekosistēma, bet par cenu veiktspējai un sarežģītībai.
Skatiet salīdzinājumu starp Laravel un Flight.
Slim
Slim ir mikro ietvars, kas ir līdzīgs Flight. Tas ir izstrādāts, lai būtu viegls un viegli lietojams, bet var būt nedaudz sarežģītāks nekā Flight.
Skatiet salīdzinājumu starp Slim un Flight.
Fat-Free
Fat-Free ir pilnas kaudzes ietvars daudz mazākā iepakojumā. Lai arī tam ir visas rīces rīku kastē, tas var padarīt dažus projektus sarežģītākus nekā tie vajadzīgi būtu.
Skatiet salīdzinājumu starp Fat-Free un Flight.
Symfony
Symfony ir modulārs uzņēmumu līmeņa ietvars, kas ir izstrādāts, lai būtu elastīgs un skalējams. Mazākiem projektiem vai jaunajiem izstrādātājiem Symfony var būt nedaudz apburošs.
Skatiet salīdzinājumu starp Symfony un Flight.
Learn/pdo_wrapper
PdoWrapper PDO Palīdze ģenerators
BRĪDINĀJUMS
Novecojis:
PdoWrapperir novecojis kopš Flight v3.18.0. Tas netiks noņemts nākamajā versijā, bet tiks uzturēts atpakaļsaderībai. Lūdzu, izmantojiet SimplePdo tā vietā, kas piedāvā tādu pašu funkcionalitāti plus papildu palīgmēģus biežām datubāzes operācijām.
Pārskats
PdoWrapper klase Flight ir draudzīgs palīgs darbam ar datubāzēm, izmantojot PDO. Tā vienkāršo izplatītās datubāzes uzdevumus, pievieno dažas ērtas metodes rezultātu iegūšanai un atgriež rezultātus kā Collections vieglai piekļuvei. Tā arī atbalsta vaicājumu reģistrēšanu un lietojumprogrammas veiktspējas uzraudzību (APM) sarežģītiem gadījumiem.
Saprašana
Darbs ar datubāzēm PHP var būt nedaudz verbāls, īpaši, izmantojot PDO tieši. PdoWrapper paplašina PDO un pievieno metodes, kas padara vaicājumu veikšanu, rezultātu iegūšanu un apstrādi daudz vieglāku. Tā vietā, lai žonglētu ar sagatavotiem paziņojumiem un iegūšanas režīmiem, jūs saņemat vienkāršas metodes izplatītiem uzdevumiem, un katra rindiņa tiek atgriezta kā Collection, tāpēc jūs varat izmantot masīva vai objekta notāciju.
Jūs varat reģistrēt PdoWrapper kā kopīgu servisu Flight, un tad izmantot to jebkur savā lietojumprogrammā caur Flight::db().
Pamata Izmantošana
Reģistrēšana PDO Palīgam
Vispirms reģistrējiet PdoWrapper klasi ar Flight:
Flight::register('db', \flight\database\PdoWrapper::class, [
'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8mb4\'',
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]
]);
Tagad jūs varat izmantot Flight::db() jebkur, lai iegūtu savienojumu ar datubāzi.
Vaicājumu Izpilde
runQuery()
function runQuery(string $sql, array $params = []): PDOStatement
Izmantojiet to INSERT, UPDATE vai kad vēlaties iegūt rezultātus manuāli:
$db = Flight::db();
$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']);
while ($row = $statement->fetch()) {
// $row ir masīvs
}
Jūs varat izmantot to arī rakstīšanai:
$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']);
$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]);
fetchField()
function fetchField(string $sql, array $params = []): mixed
Iegūstiet vienu vērtību no datubāzes:
$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']);
fetchRow()
function fetchRow(string $sql, array $params = []): Collection
Iegūstiet vienu rindiņu kā Collection (masīva/objekta piekļuve):
$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]);
echo $user['name'];
// vai
echo $user->name;
fetchAll()
function fetchAll(string $sql, array $params = []): array<Collection>
Iegūstiet visas rindiņas kā Collections masīvu:
$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']);
foreach ($users as $user) {
echo $user['name'];
// vai
echo $user->name;
}
Izmantojot IN() Vietu Turētājus
Jūs varat izmantot vienu ? IN() klauzulā un nodot masīvu vai komatiem atdalītu virkni:
$ids = [1, 2, 3];
$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]);
// vai
$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", ['1,2,3']);
Uzlabota Izmantošana
Vaicājumu Reģistrēšana & APM
Ja vēlaties izsekot vaicājuma veiktspēju, iespējiet APM izsekošanu reģistrējot:
Flight::register('db', \flight\database\PdoWrapper::class, [
'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // pēdējais params iespējina APM
]);
Pēc vaicājumu izpildes jūs varat reģistrēt tos manuāli, bet APM tos reģistrēs automātiski, ja iespējots:
Flight::db()->logQueries();
Tas izraisīs notikumu (flight.db.queries) ar savienojuma un vaicājuma metrikiem, ko jūs varat klausīties, izmantojot Flight notikumu sistēmu.
Pilns Piemērs
Flight::route('/users', function () {
// Iegūt visus lietotājus
$users = Flight::db()->fetchAll('SELECT * FROM users');
// Straumēt visus lietotājus
$statement = Flight::db()->runQuery('SELECT * FROM users');
while ($user = $statement->fetch()) {
echo $user['name'];
}
// Iegūt vienu lietotāju
$user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]);
// Iegūt vienu vērtību
$count = Flight::db()->fetchField('SELECT COUNT(*) FROM users');
// Īpaša IN() sintakse
$users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]);
$users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', ['1,2,3,4,5']);
// Ievietot jaunu lietotāju
Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']);
$insert_id = Flight::db()->lastInsertId();
// Atjaunināt lietotāju
Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]);
// Dzēst lietotāju
Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]);
// Iegūt skarto rindu skaitu
$statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']);
$affected_rows = $statement->rowCount();
});
Skatīt Arī
- Collections - Uzziniet, kā izmantot Collection klasi vieglai datu piekļuvei.
Traucējummeklēšana
- Ja saņemat kļūdu par datubāzes savienojumu, pārbaudiet savu DSN, lietotājvārdu, paroli un opcijas.
- Visas rindiņas tiek atgrieztas kā Collections—ja vajadzīgs vienkāršs masīvs, izmantojiet
$collection->getData(). - IN (?) vaicājumiem pārliecinieties, ka nododiet masīvu vai komatiem atdalītu virkni.
Izmaiņu Žurnāls
- v3.2.0 - Sākotnējā PdoWrapper izlaišana ar pamata vaicājuma un iegūšanas metodēm.
Learn/dependency_injection_container
Atkarību ievadīšanas konteiners
Pārskats
Atkarību ievadīšanas konteiners (DIC) ir jaudīgs papildinājums, kas ļauj pārvaldīt jūsu lietojumprogrammas atkarības. Tas ir arī viens no lielākajiem iemesliem, kāpēc Flight labi sadarbojas ar AI kodēšanas rīkiem un vienību testiem: kontrolleri konstruktorā saņem to, kas tiem nepieciešams, nevis piekļūst globālajiem mainīgajiem.
Izpratne
Atkarību ievadīšana (DI) ir galvenā koncepcija mūsdienu PHP ietvaros un tiek izmantota, lai pārvaldītu objektu izveidi un konfigurāciju. Daži DIC bibliotēku piemēri: flightphp/container, Dice, Pimple, PHP-DI un league/container.
DIC ir elegantīgs veids, kā izveidot un pārvaldīt savas klases centralizētā vietā. Tas ir noderīgi, ja jums viens un tas pats objekts jānodod vairākām klasēm (kontrolleriem, starpprogrammatūrai, komandām utt.).
Oficiālais flightphp/skeleton savieno Dice failā app/config/services.php, aizstāj kopīgo flight\Engine instanci un atrisina maršrutu mērķus, piemēram, [App\Controller\HomeController::class, 'index']. Jauniem projektiem izmantojiet šo paraugu, lai cilvēki un aģenti rediģētu vienas un tās pašas vietas.
Pamata lietošana
Vecais veids, kā to darīt, varētu izskatīties šādi:
require 'vendor/autoload.php';
// klase, lai pārvaldītu lietotājus no datubāzes
class UserController {
protected PDO $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function view(int $id) {
$stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $id]);
print_r($stmt->fetch());
}
}
// jūsu routes.php failā
$db = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$UserController = new UserController($db);
Flight::route('/user/@id', [ $UserController, 'view' ]);
// citi UserController maršruti...
Flight::start();
No augšējā koda var redzēt, ka mēs izveidojam jaunu PDO objektu un nododam to
mūsu UserController klasei. Mazai lietojumprogrammai tas ir labi, bet, kad
jūsu lietojumprogramma aug, jūs atklāsiet, ka vienu un to pašu PDO objektu
izveidojat vai nododat vairākās vietās. Šeit noder DIC.
Šis ir tas pats piemērs, izmantojot DIC (ar Dice):
require 'vendor/autoload.php';
// tā pati klase kā iepriekš. Nekas nav mainījies
class UserController {
protected PDO $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function view(int $id) {
$stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $id]);
print_r($stmt->fetch());
}
}
// izveido jaunu konteineru
$container = new \Dice\Dice;
// pievieno kārtulu, lai pateiktu konteineram, kā izveidot PDO objektu
// neaizmirsti to atkārtoti piešķirt sev, kā parādīts zemāk!
$container = $container->addRule('PDO', [
// shared nozīmē, ka katru reizi tiks atgriezts tas pats objekts
'shared' => true,
'constructParams' => ['mysql:host=localhost;dbname=test', 'user', 'pass' ]
]);
// Tas reģistrē konteinera apstrādātāju, lai Flight zinātu to izmantot.
Flight::registerContainerHandler(function($class, $params) use ($container) {
return $container->create($class, $params);
});
// tagad mēs varam izmantot konteineru, lai izveidotu mūsu UserController
Flight::route('/user/@id', [ UserController::class, 'view' ]);
Flight::start();
Varbūt jūs domājat, ka piemēram tika pievienots daudz lieka koda.
Burvība parādās, kad jums ir cits kontrolleris, kuram nepieciešams PDO objekts.
// Ja visiem jūsu kontrolleriem konstruktorā ir nepieciešams PDO objekts,
// katram no šiem maršrutiem tas tiks automātiski ievadīts!!!
Flight::route('/company/@id', [ CompanyController::class, 'view' ]);
Flight::route('/organization/@id', [ OrganizationController::class, 'view' ]);
Flight::route('/category/@id', [ CategoryController::class, 'view' ]);
Flight::route('/settings', [ SettingsController::class, 'view' ]);
Papildu ieguvums, izmantojot DIC, ir tas, ka vienību testēšana kļūst daudz vienkāršāka. Jūs varat izveidot viltojuma (mock) objektu un nodot to savai klasei. Tas ir milzīgs ieguvums, rakstot testus savai lietojumprogrammai — un, kad AI palīgs ģenerē kontrolleri, konstruktora ievadīšana sniedz tam skaidru, konsekventu paraugu, kam sekot (vienību testēšanas ceļvedis).
Centralizēta DIC apstrādātāja izveide
Jūs varat izveidot centralizētu DIC apstrādātāju savā pakalpojumu failā, paplašinot savu lietojumprogrammu. Šeit ir piemērs:
// services.php
// izveido jaunu konteineru
$container = new \Dice\Dice;
// neaizmirsti to atkārtoti piešķirt sev, kā parādīts zemāk!
$container = $container->addRule('PDO', [
// shared nozīmē, ka katru reizi tiks atgriezts tas pats objekts
'shared' => true,
'constructParams' => ['mysql:host=localhost;dbname=test', 'user', 'pass' ]
]);
// tagad mēs varam izveidot kartējamu metodi jebkura objekta izveidei.
Flight::map('make', function($class, $params = []) use ($container) {
return $container->create($class, $params);
});
// Tas reģistrē konteinera apstrādātāju, lai Flight zinātu to izmantot kontrolleriem/starpprogrammatūrai
Flight::registerContainerHandler(function($class, $params) {
return Flight::make($class, $params);
});
// pieņemsim, ka mums ir šāda parauga klase, kas konstruktorā saņem PDO objektu
class EmailCron {
protected PDO $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function send() {
// kods, kas nosūta e-pastu
}
}
// Un visbeidzot jūs varat izveidot objektus, izmantojot atkarību ievadīšanu
$emailCron = Flight::make(EmailCron::class);
$emailCron->send();
flightphp/container
Flight ir spraudnis, kas nodrošina vienkāršu PSR-11 saderīgu konteineru, kuru varat izmantot, lai pārvaldītu savu atkarību ievadīšanu. Šeit ir ātrs piemērs, kā to lietot:
// index.php, piemēram
require 'vendor/autoload.php';
use flight\Container;
$container = new Container;
$container->set(PDO::class, fn(): PDO => new PDO('sqlite::memory:'));
Flight::registerContainerHandler([$container, 'get']);
class TestController {
private PDO $pdo;
function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
function index() {
var_dump($this->pdo);
// izvadīs šo pareizi!
}
}
Flight::route('GET /', [TestController::class, 'index']);
Flight::start();
Papildu lietošana ar flightphp/container
Jūs varat arī rekursīvi atrisināt atkarības. Šeit ir piemērs:
<?php
require 'vendor/autoload.php';
use flight\Container;
class User {}
interface UserRepository {
function find(int $id): ?User;
}
class PdoUserRepository implements UserRepository {
private PDO $pdo;
function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
function find(int $id): ?User {
// Implementācija ...
return null;
}
}
$container = new Container;
$container->set(PDO::class, static fn(): PDO => new PDO('sqlite::memory:'));
$container->set(UserRepository::class, PdoUserRepository::class);
$userRepository = $container->get(UserRepository::class);
var_dump($userRepository);
/*
object(PdoUserRepository)#4 (1) {
["pdo":"PdoUserRepository":private]=>
object(PDO)#3 (0) {
}
}
*/
DICE
Jūs varat arī izveidot savu DIC apstrādātāju. Tas ir noderīgi, ja jums ir pielāgots konteiners, kuru vēlaties izmantot un kurš nav PSR-11 (Dice). Skatiet pamata lietošanas sadaļu, lai uzzinātu, kā to izdarīt.
Turklāt ir daži noderīgi noklusējumi, kas atvieglos jūsu darbu, lietojot Flight.
Engine instance (nepieciešama $app ievadīšanai)
Ja kontrolleros vai starpprogrammatūrā norādāt tipu flight\Engine, Dice nedrīkst izveidot jaunu Engine. Aizstājiet to ar to pašu instanci no sāknēšanas faila. To dara oficiālais skeleton, un tas ir paraugs, ko AGENTS.md sagaida no AI ģenerētiem kontrolleriem:
// Kaut kur jūsu sāknēšanas / services.php failā
use flight\Engine;
use flight\database\SimplePdo;
$app = Flight::app(); // vai $engine = Flight::app();
$container = new \Dice\Dice;
$container = $container->addRule('*', [
'substitutions' => [
// Svarīgi: atkārtoti izmantot sāknēto Engine — neļaujiet Dice veikt `new Engine()`
Engine::class => $app,
// Jaunam kodam vēlams izmantot SimplePdo
// SimplePdo::class => $db,
// Config::class => $config,
// \Twig\Environment::class => $twig,
]
]);
$app->registerContainerHandler(function ($class, $params) use ($container) {
return $container->create($class, $params);
});
// Neobligāts palīgs maršrutu ārpus koda
$app->map('make', function ($class, $params = []) use ($container) {
return $container->create($class, $params);
});
// app/Controller/MyController.php (skeleton izkārtojums — mapes nosaukums atbilst namespace)
namespace App\Controller;
use flight\Engine;
class MyController
{
protected Engine $app;
public function __construct(Engine $app)
{
$this->app = $app;
}
public function index(): void
{
// Nav Flight:: fasādes lietojumprogrammas slānī — vieglāk testēt un skaidrāk AI rīkiem
$this->app->render('welcome', ['message' => 'Hello']);
}
}
// app/config/routes.php
use App\Controller\MyController;
$router->get('/', [MyController::class, 'index']);
Ja izlaižat Engine aizstāšanu, Dice var izveidot otru Engine, un jūsu kontrolleris nedalīs maršrutus, konfigurāciju vai kartēto Twig render no sāknēšanas faila.
Citu koplietotu pakalpojumu pievienošana (SimplePdo, Config, Twig)
use flight\database\SimplePdo;
use flight\Engine;
// Pēc tam, kad services.php izveidojat $db, $config, $twig:
$substitutions = [
Engine::class => $app,
SimplePdo::class => $db,
// App\Utils\Config::class => $config,
// \Twig\Environment::class => $twig,
];
$container = $container->addRule('*', [
'substitutions' => $substitutions,
]);
Tad kontrolleri var konstruktorā pieņemt SimplePdo $db (vai jūsu config tipu) un nekad neizsaukt Flight::db(). Tas atbilst vienību testēšanas norādēm un skeleton stila paraugam.
Citu klašu pievienošana
Ja jums ir citas klases, kuras vēlaties pievienot konteineram, ar Dice tas ir vienkārši, jo konteiners tās atrisinās automātiski. Šeit ir piemērs:
$container = new \Dice\Dice;
// Ja jums nav nepieciešams ievadīt atkarības savās klasēs,
// jums nekas nav jādefinē!
Flight::registerContainerHandler(function($class, $params) use ($container) {
return $container->create($class, $params);
});
class MyCustomClass {
public function parseThing() {
return 'thing';
}
}
class UserController {
protected MyCustomClass $MyCustomClass;
public function __construct(MyCustomClass $MyCustomClass) {
$this->MyCustomClass = $MyCustomClass;
}
public function index() {
echo $this->MyCustomClass->parseThing();
}
}
Flight::route('/user', 'UserController->index');
PSR-11
Flight var izmantot arī jebkuru PSR-11 saderīgu konteineru. Tas nozīmē, ka varat izmantot jebkuru konteineru, kas implementē PSR-11 saskarni. Šeit ir piemērs, izmantojot League PSR-11 konteineru:
require 'vendor/autoload.php';
use flight\database\SimplePdo;
// tā pati UserController ideja kā iepriekš, bet ar SimplePdo tipu, nevis neapstrādātu PDO
$container = new \League\Container\Container();
$container->add(UserController::class)->addArgument(SimplePdo::class);
$container->add(SimplePdo::class)
->addArgument('mysql:host=localhost;dbname=test')
->addArgument('user')
->addArgument('pass');
Flight::registerContainerHandler($container);
Flight::route('/user', [ 'UserController', 'view' ]);
Flight::start();
Tas var būt nedaudz garāks nekā iepriekšējais Dice piemērs, taču tas joprojām sasniedz to pašu rezultātu ar tādiem pašiem ieguvumiem!
Skatīt arī
- Instalācija — Skeleton izkārtojums un kur atrodas
services.php. - Automātiskā ielāde —
App\namespace un mapju reģistrs. - Flight paplašināšana — Uzziniet, kā pievienot atkarību ievadīšanu savām klasēm, paplašinot ietvaru.
- Konfigurācija — Uzziniet, kā konfigurēt Flight savai lietojumprogrammai.
- Maršrutēšana — Uzziniet, kā definēt maršrutus savai lietojumprogrammai un kā atkarību ievadīšana darbojas ar kontrolleriem.
- Starpprogrammatūra — Uzziniet, kā izveidot starpprogrammatūru savai lietojumprogrammai un kā atkarību ievadīšana darbojas ar starpprogrammatūru.
- Vienību testēšana — Kāpēc konstruktora ievadīšana ir labāka par
Flight::globālajiem mainīgajiem. - AI un izstrādātāju pieredze — Viens DI paraugs cilvēkiem un aģentiem.
- SimplePdo — Ieteicamais datubāzes palīgs ievadīšanai.
Problēmu novēršana
- Ja jums ir problēmas ar konteineru, pārliecinieties, ka konteineram nododat pareizos klašu nosaukumus.
- Kontrolleri, kas norāda tipu
Engine, bet saņem "tukšu" lietotni: pievienojiet Engine aizstāšanu (skatīt iepriekš). Dice nedrīkst veiktnewotrajam Engine. - Klase netiek atrasta
App\Controller\…: pārbaudiet mapju reģistru zemapp/Controller/— skatiet Automātiskā ielāde. - Apstrādātājam ir jāatgriež izveidotais objekts no
registerContainerHandler(neizsaucietFlight::make()bezreturn).
Izmaiņu žurnāls
- Dokumentācija — Dokumentēta skeleton Dice + Engine aizstāšana, SimplePdo un
App\Controllerizkārtojums AI draudzīgiem projektiem. - v3.7.0 — Pievienota iespēja reģistrēt DIC apstrādātāju Flight.
Learn/middleware
Starpamats
Pārskats
Flight atbalsta maršruta un grupas maršruta vidusprogrammatūru. Vidusprogrammatūra ir jūsu lietojumprogrammas daļa, kur kods tiek izpildīts pirms ( vai pēc) maršruta atsauksmes. Tas ir lielisks veids, kā pievienot API autentifikācijas pārbaudes jūsu kodā vai lai pārbaudītu, vai lietotājam ir atļauja piekļūt maršrutam.
Saprašana
Vidusprogrammatūra var ievērojami vienkāršot jūsu lietojumprogrammu. Tā vietā, lai izmantotu sarežģītu abstraktas klases mantojumu vai metožu pārrakstīšanu, vidusprogrammatūra ļauj jums kontrolēt savus maršrutus, pievienojot tiem savu pielāgotu lietojumprogrammas loģiku. Jūs varat domāt par vidusprogrammatūru gandrīz kā par sendviču. Jums ir maize no ārpuses, un tad slāņi ar sastāvdaļām, piemēram, salātiem, tomātiem, gaļām un sieru. Tad iedomājieties, ka katrs pieprasījums ir kā iekost sendvičā, kur jūs ēdat ārējos slāņus vispirms un pakāpeniski nokļūstat līdz kodolam.
Šeit ir vizuāls attēlojums, kā darbojas vidusprogrammatūra. Tad mēs parādīsim jums praktisku piemēru, kā tas darbojas.
Lietotāja pieprasījums URL /api ---->
Vidusprogrammatūra->before() izpildīta ----->
Atsaucamā funkcija/metode, kas pievienota /api, izpildīta un atbilde ģenerēta ------>
Vidusprogrammatūra->after() izpildīta ----->
Lietotājs saņem atbildi no servera
Un šeit ir praktisks piemērs:
Lietotājs pāriet uz URL /dashboard
LoggedInMiddleware->before() izpildīta
before() pārbauda derīgu pieteikšanās sesiju
ja jā, nedarīt neko un turpināt izpildi
ja nē, novirzīt lietotāju uz /login
Atsaucamā funkcija/metode, kas pievienota /api, izpildīta un atbilde ģenerēta
LoggedInMiddleware->after() neko nav definēts, tāpēc ļauj izpildei turpināties
Lietotājs saņem dashboard HTML no servera
Izpildes secība
Vidusprogrammatūras funkcijas tiek izpildītas tajā secībā, kā tās tiek pievienotas maršrutam. Izpilde ir līdzīga tam, kā Slim Framework apstrādā šo.
before() metodes tiek izpildītas pievienotās secībā, un after() metodes tiek izpildītas pretējā secībā.
Piem.: Middleware1->before(), Middleware2->before(), Middleware2->after(), Middleware1->after().
Pamata izmantošana
Jūs varat izmantot vidusprogrammatūru kā jebkuru atsaucamu metodi, tostarp anonīmu funkciju vai klasi (ieteicams)
Anonīma funkcija
Šeit ir vienkāršs piemērs:
Flight::route('/path', function() { echo ' Here I am!'; })->addMiddleware(function() {
echo 'Middleware first!';
});
Flight::start();
// This will output "Middleware first! Here I am!"
Piezīme: Izmantojot anonīmu funkciju, vienīgā interpretētā metode ir
before()metode. Jūs nevarat definētafter()uzvedību ar anonīmu klasi.
Izmantojot klases
Vidusprogrammatūru var (un vajadzētu) reģistrēt kā klasi. Ja jums vajadzīga "after" funkcionalitāte, jūs jāizmanto klase.
class MyMiddleware {
public function before($params) {
echo 'Middleware first!';
}
public function after($params) {
echo 'Middleware last!';
}
}
$MyMiddleware = new MyMiddleware();
Flight::route('/path', function() { echo ' Here I am! '; })->addMiddleware($MyMiddleware);
// also ->addMiddleware([ $MyMiddleware, $MyMiddleware2 ]);
Flight::start();
// This will display "Middleware first! Here I am! Middleware last!"
Jūs varat definēt tikai vidusprogrammatūras klases nosaukumu, un tā uzreiz radīs klases экземпlāru.
Flight::route('/path', function() { echo ' Here I am! '; })->addMiddleware(MyMiddleware::class);
Piezīme: Ja jūs nodod tikai vidusprogrammatūras nosaukumu, tā automātiski tiks izpildīta, izmantojot atkarību injekcijas konteineru, un vidusprogrammatūra tiks izpildīta ar parametriem, kas tai nepieciešami. Ja jums nav reģistrēts atkarību injekcijas konteiners, tas pēc noklusējuma nodos
flight\Engineэкземпlāru__construct(Engine $app)metodē.
Izmantojot maršrutus ar parametriem
Ja jums vajadzīgi parametri no jūsu maršruta, tie tiks nodoti kā viens masīvs jūsu vidusprogrammatūras funkcijā. (function($params) { ... } vai public function before($params) { ... }). Iemesls tam ir tas, ka jūs varat strukturēt savus parametrus grupās, un dažās no tām jūsu parametri var parādīties citā secībā, kas salauztu vidusprogrammatūras funkciju, atsaucoties uz nepareizo parametru. Šādā veidā jūs varat piekļūt tiem pēc nosaukuma, nevis pozīcijas.
use flight\Engine;
class RouteSecurityMiddleware {
protected Engine $app;
public function __construct(Engine $app) {
$this->app = $app;
}
public function before(array $params) {
$clientId = $params['clientId'];
// jobId may or may not be passed in
$jobId = $params['jobId'] ?? 0;
// maybe if there's no job ID, you don't need to lookup anything.
if($jobId === 0) {
return;
}
// perform a lookup of some kind in your database
$isValid = !!$this->app->db()->fetchField("SELECT 1 FROM client_jobs WHERE client_id = ? AND job_id = ?", [ $clientId, $jobId ]);
if($isValid !== true) {
$this->app->halt(400, 'You are blocked, muahahaha!');
}
}
}
// routes.php
$router->group('/client/@clientId/job/@jobId', function(Router $router) {
// This group below still gets the parent middleware
// But the parameters are passed in one single array
// in the middleware.
$router->group('/job/@jobId', function(Router $router) {
$router->get('', [ JobController::class, 'view' ]);
$router->put('', [ JobController::class, 'update' ]);
$router->delete('', [ JobController::class, 'delete' ]);
// more routes...
});
}, [ RouteSecurityMiddleware::class ]);
Grupēšana maršrutus ar vidusprogrammatūru
Jūs varat pievienot maršruta grupu, un tad katrs maršruts šajā grupā būs ar to pašu vidusprogrammatūru. Tas ir noderīgi, ja jums vajag grupēt vairākus maršrutus, piemēram, ar Auth vidusprogrammatūru, lai pārbaudītu API atslēgu galvenē.
// added at the end of the group method
Flight::group('/api', function() {
// This "empty" looking route will actually match /api
Flight::route('', function() { echo 'api'; }, false, 'api');
// This will match /api/users
Flight::route('/users', function() { echo 'users'; }, false, 'users');
// This will match /api/users/1234
Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view');
}, [ new ApiAuthMiddleware() ]);
Ja jūs vēlaties piemērot globālu vidusprogrammatūru visiem jūsu maršrutiem, jūs varat pievienot "tukšu" grupu:
// added at the end of the group method
Flight::group('', function() {
// This is still /users
Flight::route('/users', function() { echo 'users'; }, false, 'users');
// And this is still /users/1234
Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view');
}, [ ApiAuthMiddleware::class ]); // or [ new ApiAuthMiddleware() ], same thing
Izplatīti izmantošanas gadījumi
API atslēgas validācija
Ja jūs vēlaties aizsargāt savus /api maršrutus, pārbaudot, vai API atslēga ir pareiza, jūs varat viegli to apstrādāt ar vidusprogrammatūru.
use flight\Engine;
class ApiMiddleware {
protected Engine $app;
public function __construct(Engine $app) {
$this->app = $app;
}
public function before(array $params) {
$authorizationHeader = $this->app->request()->getHeader('Authorization');
$apiKey = str_replace('Bearer ', '', $authorizationHeader);
// do a lookup in your database for the api key
$apiKeyHash = hash('sha256', $apiKey);
$hasValidApiKey = !!$this->db()->fetchField("SELECT 1 FROM api_keys WHERE hash = ? AND valid_date >= NOW()", [ $apiKeyHash ]);
if($hasValidApiKey !== true) {
$this->app->jsonHalt(['error' => 'Invalid API Key']);
}
}
}
// routes.php
$router->group('/api', function(Router $router) {
$router->get('/users', [ ApiController::class, 'getUsers' ]);
$router->get('/companies', [ ApiController::class, 'getCompanies' ]);
// more routes...
}, [ ApiMiddleware::class ]);
Tagad visi jūsu API maršruti ir aizsargāti ar šo API atslēgas validācijas vidusprogrammatūru, ko jūs esat iestatījis! Ja jūs pievienosiet vairāk maršrutus maršrutētāja grupai, tiem uzreiz būs tā pati aizsardzība!
Pieteikšanās validācija
Vai jūs vēlaties aizsargāt dažus maršrutus, lai tie būtu pieejami tikai pieteikušies lietotājiem? To var viegli sasniegt ar vidusprogrammatūru!
use flight\Engine;
class LoggedInMiddleware {
protected Engine $app;
public function __construct(Engine $app) {
$this->app = $app;
}
public function before(array $params) {
$session = $this->app->session();
if($session->get('logged_in') !== true) {
$this->app->redirect('/login');
exit;
}
}
}
// routes.php
$router->group('/admin', function(Router $router) {
$router->get('/dashboard', [ DashboardController::class, 'index' ]);
$router->get('/clients', [ ClientController::class, 'index' ]);
// more routes...
}, [ LoggedInMiddleware::class ]);
Maršruta parametra validācija
Vai jūs vēlaties aizsargāt savus lietotājus no vērtību maiņas URL, lai piekļūtu datiem, kas tiem nepieder? To var atrisināt ar vidusprogrammatūru!
use flight\Engine;
class RouteSecurityMiddleware {
protected Engine $app;
public function __construct(Engine $app) {
$this->app = $app;
}
public function before(array $params) {
$clientId = $params['clientId'];
$jobId = $params['jobId'];
// perform a lookup of some kind in your database
$isValid = !!$this->app->db()->fetchField("SELECT 1 FROM client_jobs WHERE client_id = ? AND job_id = ?", [ $clientId, $jobId ]);
if($isValid !== true) {
$this->app->halt(400, 'You are blocked, muahahaha!');
}
}
}
// routes.php
$router->group('/client/@clientId/job/@jobId', function(Router $router) {
$router->get('', [ JobController::class, 'view' ]);
$router->put('', [ JobController::class, 'update' ]);
$router->delete('', [ JobController::class, 'delete' ]);
// more routes...
}, [ RouteSecurityMiddleware::class ]);
Apstrāde vidusprogrammatūras izpildes
Pieņemsim, jums ir autentifikācijas vidusprogrammatūra, un jūs vēlaties novirzīt lietotāju uz pieteikšanās lapu, ja viņš nav autentificēts. Jums ir vairākas opcijas rīcībā:
- Jūs varat atgriezt false no vidusprogrammatūras funkcijas, un Flight automātiski atgriezīs 403 Forbidden kļūdu, bet bez pielāgošanas.
- Jūs varat novirzīt lietotāju uz pieteikšanās lapu, izmantojot
Flight::redirect(). - Jūs varat izveidot pielāgotu kļūdu vidusprogrammatūrā un apturēt maršruta izpildi.
Vienkāršs un tiešs
Šeit ir vienkāršs return false; piemērs:
class MyMiddleware {
public function before($params) {
$hasUserKey = Flight::session()->exists('user');
if ($hasUserKey === false) {
return false;
}
// since it's true, everything just keeps on going
}
}
Novirzīšanas piemērs
Šeit ir piemērs, kā novirzīt lietotāju uz pieteikšanās lapu:
class MyMiddleware {
public function before($params) {
$hasUserKey = Flight::session()->exists('user');
if ($hasUserKey === false) {
Flight::redirect('/login');
exit;
}
}
}
Pielāgota kļūdas piemērs
Pieņemsim, jums vajag mest JSON kļūdu, jo jūs veidojat API. Jūs varat to izdarīt šādi:
class MyMiddleware {
public function before($params) {
$authorization = Flight::request()->getHeader('Authorization');
if(empty($authorization)) {
Flight::jsonHalt(['error' => 'You must be logged in to access this page.'], 403);
// or
Flight::json(['error' => 'You must be logged in to access this page.'], 403);
exit;
// or
Flight::halt(403, json_encode(['error' => 'You must be logged in to access this page.']);
}
}
}
Skatīt arī
- Maršrutēšana - Kā kartēt maršrutus uz kontrolieriem un renderēt skatus.
- Pieprasījumi - Saprašana, kā apstrādāt ienākošos pieprasījumus.
- Atbildes - Kā pielāgot HTTP atbildes.
- Atkarību injekcija - Vienkāršo objektu izveidi un pārvaldību maršrutos.
- Kāpēc ietvars? - Saprašana par ietvara, piemēram, Flight, priekšrocībām.
- Vidusprogrammatūras izpildes stratēģijas piemērs
Traucējummeklēšana
- Ja jums ir novirzīšana jūsu vidusprogrammatūrā, bet jūsu lietojumprogramma, šķiet, nenovirzās, pārliecinieties, ka pievienojat
exit;paziņojumu jūsu vidusprogrammatūrā.
Izmaiņu žurnāls
- v3.1: Pievienots atbalsts vidusprogrammatūrai.
Learn/filtering
Filtrēšana
Pārskats
Flight ļauj jums filtrēt kartētos metodes pirms un pēc to izsaukšanas.
Saprašana
Nav iepriekš definētu āķu, kurus jums vajadzētu iegaumēt. Jūs varat filtrēt jebkuru no noklusējuma ietvara metodēm, kā arī jebkuru pielāgotu metožu, kuras esat kartējuši.
Filtra funkcija izskatās šādi:
/**
* @param array $params Metodei, kas tiek filtrēta, nodotie parametri.
* @param string $output (tikai v2 izvades buferizēšana) Metodes, kas tiek filtrēta, izvade.
* @return bool Atgrieziet true/void vai neatgrieziet, lai turpinātu ķēdi, false, lai pārtrauktu ķēdi.
*/
function (array &$params, string &$output): bool {
// Filtra kods
}
Izmantojot nodotās mainīgās, jūs varat manipulēt ar ievades parametriem un/vai izvadi.
Jūs varat likt filtram darboties pirms metodes, izdarot:
Flight::before('start', function (array &$params, string &$output): bool {
// Dariet kaut ko
});
Jūs varat likt filtram darboties pēc metodes, izdarot:
Flight::after('start', function (array &$params, string &$output): bool {
// Dariet kaut ko
});
Jūs varat pievienot tik daudz filtru, cik vēlaties, jebkurai metodei. Tie tiks izsaukti secībā, kādā tie ir deklarēti.
Šeit ir filtrēšanas procesa piemērs:
// Kartējiet pielāgotu metodi
Flight::map('hello', function (string $name) {
return "Hello, $name!";
});
// Pievienojiet pirms filtra
Flight::before('hello', function (array &$params, string &$output): bool {
// Manipulējiet parametru
$params[0] = 'Fred';
return true;
});
// Pievienojiet pēc filtra
Flight::after('hello', function (array &$params, string &$output): bool {
// Manipulējiet izvadi
$output .= " Have a nice day!";
return true;
});
// Izsauciet pielāgoto metodi
echo Flight::hello('Bob');
Šim vajadzētu parādīt:
Hello Fred! Have a nice day!
Ja esat definējuši vairākus filtrus, jūs varat pārtraukt ķēdi, atgriežot false
jebkurā no jūsu filtra funkcijām:
Flight::before('start', function (array &$params, string &$output): bool {
echo 'one';
return true;
});
Flight::before('start', function (array &$params, string &$output): bool {
echo 'two';
// Tas beigs ķēdi
return false;
});
// Tas netiks izsaukts
Flight::before('start', function (array &$params, string &$output): bool {
echo 'three';
return true;
});
Piezīme: Kodola metodes, piemēram,
mapunregister, nevar tikt filtrētas, jo tās tiek izsauktas tieši un ne dinamiski. Skatiet Extending Flight, lai iegūtu vairāk informācijas.
Skatīt arī
Traucējummeklēšana
- Pārliecinieties, ka atgriežat
falseno savām filtra funkcijām, ja vēlaties, lai ķēde apstātos. Ja neatgriežat neko, ķēde turpināsies.
Izmaiņu žurnāls
- v2.0 - Sākotnējais izdevums.
Learn/requests
Pieprasījumi
Pārskats
Flight ieslēdz HTTP pieprasījumu vienā objektā, ko var piekļūt, veicot:
$request = Flight::request();
Saprašana
HTTP pieprasījumi ir viens no galvenajiem HTTP dzīves cikla aspektiem, ko jāizprot. Lietotājs veic darbību tīmekļa pārlūkprogrammā vai HTTP klientā, un tie nosūta virkni galvenes, ķermeņa, URL utt. uz jūsu projektu. Jūs varat uztvert šīs galvenes (pārlūkprogrammas valoda, kādu kompresijas veidu tās var apstrādāt, lietotāja aģents utt.) un uztvert ķermeni un URL, kas nosūtīts uz jūsu Flight lietojumprogrammu. Šie pieprasījumi ir būtiski, lai jūsu lietojumprogramma saprastu, ko darīt tālāk.
Pamata Izmantošana
PHP ir vairākas superglobālās mainīgās, tostarp $_GET, $_POST, $_REQUEST, $_SERVER, $_FILES un $_COOKIE. Flight abstraktē šīs prom praktiskajās Kolekcijās. Jūs varat piekļūt query, data, cookies un files īpašībām kā masīviem vai objektiem.
Piezīme: Ir ĻOTI atgrūstami izmantot šīs superglobālās mainīgās savā projektā, un tām jāatsaucas caur
request()objektu.
Piezīme: Nav pieejama abstrakcija
$_ENV.
$_GET
Jūs varat piekļūt $_GET masīvam caur query īpašību:
// GET /search?keyword=something
Flight::route('/search', function(){
$keyword = Flight::request()->query['keyword'];
// or
$keyword = Flight::request()->query->keyword;
echo "You are searching for: $keyword";
// query a database or something else with the $keyword
});
$_POST
Jūs varat piekļūt $_POST masīvam caur data īpašību:
Flight::route('POST /submit', function(){
$name = Flight::request()->data['name'];
$email = Flight::request()->data['email'];
// or
$name = Flight::request()->data->name;
$email = Flight::request()->data->email;
echo "You submitted: $name, $email";
// save to a database or something else with the $name and $email
});
$_COOKIE
Jūs varat piekļūt $_COOKIE masīvam caur cookies īpašību:
Flight::route('GET /login', function(){
$savedLogin = Flight::request()->cookies['myLoginCookie'];
// or
$savedLogin = Flight::request()->cookies->myLoginCookie;
// check if it's really saved or not and if it is auto log them in
if($savedLogin) {
Flight::redirect('/dashboard');
return;
}
});
Lai iegūtu palīdzību par jaunu sīkfailu vērtību iestatīšanu, skatiet overclokk/cookie
$_SERVER
Ir pieejams saīsinājums, lai piekļūtu $_SERVER masīvam caur getVar() metodi:
$host = Flight::request()->getVar('HTTP_HOST');
$_FILES
Jūs varat piekļūt augšupielādētajām failiem caur files īpašību:
// raw access to $_FILES property. See below for recommended approach
$uploadedFile = Flight::request()->files['myFile'];
// or
$uploadedFile = Flight::request()->files->myFile;
Skatiet Uploaded File Handler vairāk informācijas.
Failu Augšupielādes Apstrāde
v3.12.0
Jūs varat apstrādāt failu augšupielādi, izmantojot ietvaru ar dažām palīgapstrādes metodēm. Tas būtībā samazinās līdz faila datu iegūšanai no pieprasījuma un to pārvietošanai uz jaunu atrašanās vietu.
Flight::route('POST /upload', function(){
// If you had an input field like <input type="file" name="myFile">
$uploadedFileData = Flight::request()->getUploadedFiles();
$uploadedFile = $uploadedFileData['myFile'];
$uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename());
});
Ja jums ir vairāki augšupielādēti faili, jūs varat tos iziet cauri cilpai:
Flight::route('POST /upload', function(){
// If you had an input field like <input type="file" name="myFiles[]">
$uploadedFiles = Flight::request()->getUploadedFiles()['myFiles'];
foreach ($uploadedFiles as $uploadedFile) {
$uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename());
}
});
Drošības Piezīme: Vienmēr validējiet un sanitizējiet lietotāja ievadi, īpaši, kad strādājat ar failu augšupielādi. Vienmēr validējiet paplašinājumu veidus, kurus atļausiet augšupielādēt, bet jums arī vajadzētu validēt faila "magic bytes", lai nodrošinātu, ka tas patiešām ir tāds faila veids, kādu lietotājs apgalvo. Ir pieejami raksti un bibliotēkas, lai palīdzētu ar to.
Pieprasījuma Ķermenis
Lai iegūtu neapstrādātu HTTP pieprasījuma ķermeni, piemēram, strādājot ar POST/PUT pieprasījumiem, jūs varat veikt:
Flight::route('POST /users/xml', function(){
$xmlBody = Flight::request()->getBody();
// do something with the XML that was sent.
});
JSON Ķermenis
Ja jūs saņemat pieprasījumu ar satura veidu application/json un piemēra datiem {"id": 123}
tas būs pieejams no data īpašības:
$id = Flight::request()->data->id;
Pieprasījuma Galvenes
Jūs varat piekļūt pieprasījuma galvenēm, izmantojot getHeader() vai getHeaders() metodi:
// Maybe you need Authorization header
$host = Flight::request()->getHeader('Authorization');
// or
$host = Flight::request()->header('Authorization');
// If you need to grab all headers
$headers = Flight::request()->getHeaders();
// or
$headers = Flight::request()->headers();
Pieprasījuma Metode
Jūs varat piekļūt pieprasījuma metodei, izmantojot method īpašību vai getMethod() metodi:
$method = Flight::request()->method; // actually populated by getMethod()
$method = Flight::request()->getMethod();
Piezīme: getMethod() metode vispirms iegūst metodi no $_SERVER['REQUEST_METHOD'], tad to var pārspēt
$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'], ja tā pastāv, vai $_REQUEST['_method'], ja tā pastāv.
Pieprasījuma Objekta Īpašības
Pieprasījuma objekts nodrošina šādas īpašības:
- body - Neapstrādāts HTTP pieprasījuma ķermenis
- url - Pieprasītais URL
- base - URL vecāka apakšdirektorija
- method - Pieprasījuma metode (GET, POST, PUT, DELETE)
- referrer - Atsauce URL
- ip - Klienta IP adrese
- ajax - Vai pieprasījums ir AJAX pieprasījums
- scheme - Servera protokols (http, https)
- user_agent - Pārlūkprogrammas informācija
- type - Satura veids
- length - Satura garums
- query - Vaicājuma virknes parametri
- data - POST dati vai JSON dati
- cookies - Sīkfailu dati
- files - Augšupielādētie faili
- secure - Vai savienojums ir drošs
- accept - HTTP pieņemšanas parametri
- proxy_ip - Klienta proxy IP adrese. Skenē
$_SERVERmasīvu pēcHTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR,HTTP_X_FORWARDED,HTTP_X_CLUSTER_CLIENT_IP,HTTP_FORWARDED_FOR,HTTP_FORWARDEDšādā secībā. - host - Pieprasījuma saimnieka nosaukums
- servername - SERVER_NAME no
$_SERVER
Palīgapstrādes Metodes
Ir dažas palīgapstrādes metodes, lai saliktu URL daļas vai strādātu ar noteiktām galvenēm.
Pilns URL
Jūs varat piekļūt pilnam pieprasījuma URL, izmantojot getFullUrl() metodi:
$url = Flight::request()->getFullUrl();
// https://example.com/some/path?foo=bar
Bāzes URL
Jūs varat piekļūt bāzes URL, izmantojot getBaseUrl() metodi:
// http://example.com/path/to/something/cool?query=yes+thanks
$url = Flight::request()->getBaseUrl();
// https://example.com
// Notice, no trailing slash.
Vaicājuma Parsēšana
Jūs varat nodot URL uz parseQuery() metodi, lai parsētu vaicājuma virkni asociatīvā masīvā:
$query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar');
// ['foo' => 'bar']
Saturu Pieņemšanas Veidu Sarunas
v3.17.2
Jūs varat izmantot negotiateContentType() metodi, lai noteiktu labāko satura veidu, ar kuru atbildēt, balstoties uz Accept galveni, ko nosūtījis klients.
// Example Accept header: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
// The below defines what you support.
$availableTypes = ['application/json', 'application/xml'];
$typeToServe = Flight::request()->negotiateContentType($availableTypes);
if ($typeToServe === 'application/json') {
// Serve JSON response
} elseif ($typeToServe === 'application/xml') {
// Serve XML response
} else {
// Default to something else or throw an error
}
Piezīme: Ja neviena no pieejamajām veidiem nav atrasta
Acceptgalvenē, metode atgriezīsnull. Ja nav definētaAcceptgalvene, metode atgriezīs pirmo veidu$availableTypesmasīvā.
Skatīt Arī
- Routing - Skatiet, kā kartēt maršrutus uz kontrolieriem un renderēt skatus.
- Responses - Kā pielāgot HTTP atbildes.
- Why a Framework? - Kā pieprasījumi iekļaujas lielajā attēlā.
- Collections - Darbs ar datu kolekcijām.
- Uploaded File Handler - Failu augšupielādes apstrāde.
Traucējummeklēšana
request()->ipunrequest()->proxy_ipvar atšķirties, ja jūsu tīmekļa serveris ir aiz proxy, slodzes balansētāja utt.
Izmaiņu Žurnāls
- v3.17.2 - Pievienota negotiateContentType()
- v3.12.0 - Pievienota spēja apstrādāt failu augšupielādi caur pieprasījuma objektu.
- v1.0 - Sākotnējais izdevums.
Learn/why_frameworks
Kāpēc ietvaru?
Daudzi programmētāji stingri iebilst pret ietvaru izmantošanu. Viņi argumentē, ka ietvari ir pārpildīti, lēni un grūti apgūstami. Viņi saka, ka ietvari nav nepieciešami un ka jūs varat rakstīt labāku kodu bez tiem. Noteikti var izteikt dažus pamatoti iebildumus pret ietvaru izmantošanu. Tomēr ir arī daudz priekšrocību, izmantojot ietvarus.
Iemesli izmantot ietvaru
Šeit ir daži iemesli, kāpēc jums varētu būt jāapsver ietvara izmantošana:
- Ātrā attīstība: Ietvari nodrošina daudz funkcionalitātes no paša sākuma. Tas nozīmē, ka jūs varat ātrāk veidot tīmekļa lietojumprogrammas. Jums nav jāraksta tik daudz koda, jo ietvars nodrošina lielu daļu funkcionalitātes, kas jums nepieciešama.
- Konzistence: Ietvari nodrošina vienotu veidu, kā darīt lietas. Tas padara vieglāku saprast, kā kods darbojas un atvieglo citiem izstrādātājiem saprast jūsu kodu. Ja jums ir skripti pēc skripta, varat zaudēt konsekvenci starp skriptiem, īpaši, ja strādājat ar izstrādātāju komandu.
- Drošība: Ietvari nodrošina drošības funkcijas, kas palīdz aizsargāt jūsu tīmekļa lietojumprogrammas no bieži sastopamām drošības draudiem. Tas nozīmē, ka jums nav jāuztraucas tik daudz par drošību, jo ietvars daudzās jomās rūpējas par to.
- Kopiena: Ietvariem ir lieli izstrādātāju kopienas, kas dod ieguldījumus ietvarā. Tas nozīmē, ka jūs varat saņemt palīdzību no citiem izstrādātājiem, kad jums ir jautājumi vai problēmas. Tas arī nozīmē, ka ir daudz resursu, kas palīdz jums apgūt, kā izmantot ietvaru.
- Labās prakses: Ietvari tiek izstrādāti, izmantojot labās prakses. Tas nozīmē, ka jūs varat mācīties no ietvara un izmantot tās pašas labās prakses savā kodā. Tas var palīdzēt jums kļūt par labāku programmētāju. Dažreiz jums nav zināšanu par to, ko nezināt, un tas jums visbeidzot var likt sasistas.
- Pievienojamība: Ietvari ir izstrādāti, lai tos varētu paplašināt. Tas nozīmē, ka varat pievienot savu funkcionalitāti ietvaram. Tas ļauj jums veidot tīmekļa lietojumprogrammas, kas pielāgotas jūsu konkrētajām vajadzībām.
Flight ir mikroietvars. Tas nozīmē, ka tas ir neliels un viegls. Tas nepiedāvā tik daudz funkcionalitātes kā lielāki ietvari, piemēram, Laravel vai Symfony. Tomēr tas nodrošina lielu daļu funkcionalitātes, kas jums nepieciešama, lai veidotu tīmekļa lietojumprogrammas. Tas arī ir viegli apgūstams un lietojams. Tas padara to par labu izvēli, lai ātri un viegli veidotu tīmekļa lietojumprogrammas. Ja esat jauns ietvaru jomā, Flight ir lielisks iesācēju ietvars, ar kuru sākt. Tas palīdzēs jums iemācīties par ietvaru izmantošanas priekšrocībām, neplūstot jums ar pārāk daudz sarežģītības. Kad esat ieguvis kādu pieredzi ar Flight, būs vieglāk pāriet uz sarežģītākiem ietvariem, piemēram, Laravel vai Symfony, taču Flight joprojām var veiksmīgi veidot izturīgu lietojumprogrammu.
Kas ir Maršrutēšana?
Maršrutēšana ir Flight ietvara pamatā, bet kas tas īsti ir? Maršrutēšana ir process, kurā tiek ņemts URL un tiek saskaņots ar konkrētu funkciju jūsu kodā. Tā ir veids, kā padarīt jūsu tīmekļa vietni dažāda satura, balstoties uz pieprasīto URL. Piemēram, jūs varētu vēlēties parādīt lietotāja profilu, kad viņi apmeklē /lietotājs/1234, bet parādīt visu lietotāju sarakstu, kad viņi apmeklē /lietotāji. Tas ir visu izdarīts caur maršrutēšanu.
Tas varētu darboties šādi:
- Lietotājs dodas uz jūsu pārlūkprogrammu un ieraksta
http://piemērs.com/lietotājs/1234. - Serveris saņem pieprasījumu un skatās URL, nododot to jūsu Flight lietojumprogrammas kodam.
- Iedomāsimies, ka jūsu Flight kodā ir kaut kas tāds kā
Flight::route('/lietotājs/@id', ['LietotājuKontrolieris', 'skatītLietotājaProfila']);. Jūsu Flight lietojumprogrammas kods apskata URL un redz, ka tas atbilst jums definētajam maršrutam, un tad izpilda kodu, ko esat definējis šim maršrutam. - Flight maršrutētājs pēc tam palaiž un izsauc
skatītLietotājaProfila($id)metodiLietotājuKontrolierisklasē, padodot1234kā$idargumentu šajā metodē. - Koda jūsu
skatītLietotājaProfila()metode pēc tam darbosies un darīs to, ko esat tai pateicis. Jūs varat beigt ar ātras lietotāja profila sākuma HTML atspoguļošanu, vai ja tas ir RESTful API, jūs varat atspoguļot JSON atbildi ar lietotāja informāciju. - Flight ietina to skaisti, ģenerē atbildes galvenes un nosūta to atpakaļ uz lietotāja pārlūku.
- Lietotājs ir piepildīts ar prieku un dod sev siltu apskāvi!
Un kāpēc ir svarīgi?
Pareiza centralizēta maršrutētāja sistēma faktiski var padarīt jūsu dzīvi dramatiski vieglāku! Tas var būt grūti pamanāms sākumā. Šeit ir daži iemesli, kāpēc:
- Centralizēta Maršrutēšana: Jūs varat turēt visus savus maršrutus vienuviet. Tas padara vieglāk redzēt, kādus maršrutus jums ir un ko tie dara. Tas arī atvieglo tos mainīt, ja ir nepieciešams.
- Maršruta Parametri: Jūs varat izmantot maršruta parametrus, lai padotu datus savām maršruta metodēm. Tas ir lielisks veids, kā saglabāt kodu tīru un organizētu.
- Maršrutu Grupēšana: Jūs varat grupēt maršrutus kopā. Tas ir lielisks veids, kā organizēt kodu un piemērot starpniekprogrammatūru maršrutu grupai.
- Maršruta Aliasing: Jūs varat piešķirt aliasu maršrutam, lai vēlāk dinamiski varētu ģenerēt URL savā kodā (piemēram, šablona gadījumā). Piemēram, tajā vietā, lai ciet kodētu
/lietotājs/1234savā kodā, jūs varētu atsauce vietā lietotlietotājs_skatītun padotidkā parametru. Tas padara to brīnišķīgu gadījumā, ja nolēmīsiet to vēlāk mainīt uz/administrators/lietotājs/1234. Jums nebūs jāmaina visi jūsu cietkodētās URL, vienkārši URL, kas pievienots maršrutam. - Maršruta Starpniekprogrammatūra: Jūs varat pievienot starpniekprogrammatūru savām maršrutām. Starpniekprogrammatūra ir ārkārtīgi spēcīga, pievienojot konkrētas darbības jūsu lietojumprogrammai, piemēram, autentificējot !{a} lietotāju piekļuvi maršrutai vai maršrutu grupai.
Es esmu drošs, ka esat iepazinies ar skriptu pa skriptam veidu, kā radīt tīmekļa vietni. Jums var būt fails, ko sauc index.php, kurā ir daudz if paziņojumu, lai pārbaudītu URL un tad izpildītu konkrētu funkciju, pamatojoties uz URL. Tas ir veids, kā maršrutēšana, bet tas nav ļoti organizēts un tas var ātri izvērsties. Flight maršrutēšanas sistēma ir daudz organizētāka un spēcīgāka veidā, kā apstrādāt maršrutēšanu.
Tas?
// /lietotajs/skatit_profila.php?id=1234
if ($_GET['id']) {
$id = $_GET['id'];
skatitLietotajaProfilu($id);
}
// /lietotajs/rediget_profila.php?id=1234
if ($_GET['id']) {
$id = $_GET['id'];
reditLietotajaProfilu($id);
}
// u.c...
Vai tas?
// index.php
Flight::route('/lietotajs/@id', ['LietotajaKontrolieris', 'skatitLietotajaProfilu']);
Flight::route('/lietotajs/@id/edit', ['LietotajaKontrolieris', 'reditLietotajaProfilu']);
// Varbūt jūsu app/controllers/LietotajaKontrolieris.php
class LietotajaKontrolieris {
public function skatitLietotajaProfilu($id) {
// darīt kaut ko
}
public function reditLietotajaProfilu($id) {
// darīt kaut ko
}
}
Cerams, jūs sākat ieraudzīt ieguvumus no centralizētas maršrutēšanas sistēmas izmantošanas. Ilgtermiņā to ir daudz vieglāk pārvaldīt un saprast!
Pieprasījumi un Atbildes
Flight nodrošina vienkāršu un vieglu veidu, kā apstrādāt pieprasījumus un atbildes. Tas ir tīmekļa ietvaru būtība. Tas pieņem pieprasījumu no lietotāja pārlūka, apstrādā to, un pēc tam nosūta atbildi. Tā ir veids, kā jūs varat veidot tīmekļa lietojumprogrammas, kas darbojas, piemēram, rāda lietotāja profilu, ļauj lietotājam pierakstīties vai ļauj lietotājam publicēt jaunu bloga ierakstu.
Pieprasījumi
Pieprasījums ir tas, ko lietotāja pārlūks sūta uz jūsu serveri, kad viņi apmeklē jūsu tīmekļa vietni. Šis pieprasījums satur informāciju par to, ko lietotājs vēlas darīt. Piemēram, tas var saturēt informāciju par to, kādu URL lietotājs vēlas apmeklēt, kādu datu lietotājs vēlas nosūtīt uz jūsu serveri vai kādu veidu dati lietotājs vēlas saņemt no jūsu servera. Svarīgi ir zināt, ka pieprasījums ir tikai lasīšanas režīmā. Jūs nevarat mainīt pieprasījumu, bet jūs to varat lasīt.
Flight nodrošina vienkāršu veidu, kā piekļūt informācijai par pieprasījumu. Jūs varat piekļūt informācijai par pieprasījumu, izmantojot Flight::request()
metodi. Šī metode atgriež Pieprasījums objektu, kas satur informāciju par pieprasījumu. Jūs varat izmantot šo objektu, lai piekļūtu informācijai par
pieprasījumu, piemēram, URL, metodi vai datiem, ko lietotājs nosūtījis uz jūsu serveri.
Atbildes
Atbilde ir tas, ko jūsu serveris nosūta atpakaļ uz lietotāja pārlūku, kad viņi apmeklē jūsu tīmekļa vietni. Šī atbilde satur informāciju par to, ko jūsu serveris vēlas darīt. Piemēram, tas var saturēt informāciju par to, kāda veida datus jūsu serveris vēlas nosūtīt lietotājam, kāda veida datus jūsu serveris vēlas saņemt no lietotāja vai kāda veida datus jūsu serveris vēlas saglabāt lietotāja datorā.
Flight nodrošina vienkāršu veidu, kā nosūtīt atbildi uz lietotāja pārlūku. Jūs varat nosūtīt atbildi, izmantojot Flight::response() metodi. Šī metode
nospiež Atbilde objektu kā argumentu un nosūta atbildi uz lietotāja pārlūku. Jūs varat izmantot šo objektu, lai nosūtītu atbildi uz lietotāja pārlūku, piemēram,
HTML, JSON vai failu. Flight palīdz jums automātiski ģenerēt dažas atbildes daļas, lai padarītu lietas vieglas,# Kāpēc ietvaru?
Daudzi programmētāji stingri iebilst pret ietvaru izmantošanu. Viņi argumentē, ka ietvari ir pārpildīti, lēni un grūti apgūstami. Viņi saka, ka ietvari nav nepieciešami un ka jūs varat rakstīt labāku kodu bez tiem. Noteikti var izteikt dažus pamatoti iebildumus pret ietvaru izmantošanu. Tomēr ir arī daudz priekšrocību, izmantojot ietvarus.
Iemesli izmantot ietvaru
Šeit ir daži iemesli, kāpēc jums varētu būt jāapsver ietvara izmantošana:
- Ātrā attīstība: Ietvari nodrošina daudz funkcionalitātes no paša sākuma. Tas nozīmē, ka jūs varat ātrāk veidot tīmekļa lietojumprogrammas. Jums nav jāraksta tik daudz koda, jo ietvars nodrošina lielu daļu funkcionalitātes, kas jums nepieciešama.
- Konzistence: Ietvari nodrošina vienotu veidu, kā darīt lietas. Tas padara vieglāku saprast, kā kods darbojas un atvieglo citiem izstrādātājiem saprast jūsu kodu. Ja jums ir skripti pēc skripta, varat zaudēt konsekvenci starp skriptiem, īpaši, ja strādājat ar izstrādātāju komandu.
- Drošība: Ietvari nodrošina drošības funkcijas, kas palīdz aizsargāt jūsu tīmekļa lietojumprogrammas no bieži sastopamām drošības draudiem. Tas nozīmē, ka jums nav jāuztraucas tik daudz par drošību, jo ietvars daudzās jomās rūpējas par to.
- Kopiena: Ietvariem ir lieli izstrādātāju kopienas, kas dod ieguldījumus ietvarā. Tas nozīmē, ka jūs varat saņemt palīdzību no citiem izstrādātājiem, kad jums ir jautājumi vai problēmas. Tas arī nozīmē, ka ir daudz resursu, kas palīdz jums apgūt, kā izmantot ietvaru.
- Labās prakses: Ietvari tiek izstrādāti, izmantojot labās prakses. Tas nozīmē, ka jūs varat mācīties no ietvara un izmantot tās pašas labās prakses savā kodā. Tas var palīdzēt jums kļūt par labāku programmētāju. Dažreiz jums nav zināšanu par to, ko nezināt, un tas jums visbeidzot var likt sasistas.
- Pievienojamība: Ietvari ir izstrādīti, lai tos varētu paplašināt. Tas nozīmē, ka varat pievienot savu funkcionalitāti ietvaram. Tas ļauj jums veidot tīmekļa lietojumprogrammas, kas pielāgotas jūsu konkrētajām vajadzībām.
Flight ir mikroietvars. Tas nozīmē, ka tas ir neliels un viegls. Tas nepiedāvā tik daudz funkcionalitātes kā lielāki ietvari, piemēram, Laravel vai Symfony. Tomēr tas nodrošina lielu daļu funkcionalitātes, kas jums nepieciešama, lai veidotu tīmekļa lietojumprogrammas. Tas arī ir viegli apgūstams un lietojams. Tas padara to par labu izvēli, lai ātri un viegli veidotu tīmekļa lietojumprogrammas. Ja esat jauns ietvaru jomā, Flight ir lielisks iesācēju ietvars, ar kuru sākt. Tas palīdzēs jums iemācīties par ietvaru izmantošanas priekšrocībām, neplūstot jums ar pārāk daudz sarežģītības. Kad esat ieguvis kādu pieredzi...
Learn/responses
Atbildes
Pārskats
Flight palīdz ģenerēt daļu no atbildes galvenes jums, bet jūs kontrolējat lielāko daļu no tā, ko nosūtāt atpakaļ lietotājam. Lielāko daļu laika jūs tieši piekļūsiet response() objektam, bet Flight piedāvā dažas palīgmēģinājumu metodes, lai iestatītu dažas atbildes galvenes jums.
Izpratne
Pēc tam, kad lietotājs nosūta savu pieprasījumu uz jūsu lietojumprogrammu, jums jāģenerē pareiza atbilde viņiem. Viņi ir nosūtījuši jums informāciju, piemēram, valodu, kuru viņi dod priekšroku, vai viņi var apstrādāt noteiktus kompresijas veidus, viņu lietotāja aģentu utt., un pēc visu apstrādes ir pienācis laiks nosūtīt viņiem atpakaļ pareizu atbildi. Tas var būt galvenes iestatīšana, HTML vai JSON ķermeņa izvade viņiem vai novirzīšana uz lapu.
Pamata lietošana
Atbildes ķermeņa nosūtīšana
Flight izmanto ob_start(), lai buferētu izvadi. Tas nozīmē, ka jūs varat izmantot echo vai print, lai nosūtītu atbildi lietotājam, un Flight to uztvers un nosūtīs atpakaļ lietotājam ar atbilstošajām galvenēm.
// Tas nosūtīs "Hello, World!" uz lietotāja pārlūkprogrammu
Flight::route('/', function() {
echo "Hello, World!";
});
// HTTP/1.1 200 OK
// Content-Type: text/html
//
// Hello, World!
Kā alternatīvu, jūs varat izsaukt write() metodi, lai pievienotu ķermenim.
// Tas nosūtīs "Hello, World!" uz lietotāja pārlūkprogrammu
Flight::route('/', function() {
// verbose, bet dažreiz tas ir nepieciešams
Flight::response()->write("Hello, World!");
// ja vēlaties iegūt ķermeni, kuru esat iestatījis šajā brīdī
// jūs varat to izdarīt šādi
$body = Flight::response()->getBody();
});
JSON
Flight nodrošina atbalstu JSON un JSONP atbilžu nosūtīšanai. Lai nosūtītu JSON atbildi, jūs nododiet datus, kas jākodē JSON:
Flight::route('/@companyId/users', function(int $companyId) {
// kaut kā izvilkt savus lietotājus no datubāzes, piemēram
$users = Flight::db()->fetchAll("SELECT id, first_name, last_name FROM users WHERE company_id = ?", [ $companyId ]);
Flight::json($users);
});
// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* more users */ ]
Piezīme: Pēc noklusējuma Flight nosūtīs
Content-Type: application/jsongalveni ar atbildi. Tas arī izmantos karodziņusJSON_THROW_ON_ERRORunJSON_UNESCAPED_SLASHES, kodējot JSON.
JSON ar statusa kodu
Jūs varat arī nodot statusa kodu kā otro argumentu:
Flight::json(['id' => 123], 201);
JSON ar skaistu izdruku
Jūs varat arī nodot argumentu pēdējā pozīcijā, lai iespējotu skaistu drukāšanu:
Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT);
JSON argumentu secības maiņa
Flight::json() ir ļoti vecs metode, bet Flight mērķis ir saglabāt atpakaļsaderību projektiem. Tas ir ļoti vienkārši, ja vēlaties pārkārtot argumentu secību, lai izmantotu vienkāršāku sintaksi, jūs varat tikai pārkartēt JSON metodi kā jebkuru citu Flight metodi:
Flight::map('json', function($data, $code = 200, $options = 0) {
// tagad jums nav jāizmanto `true, 'utf-8'`, kad izmantojat json() metodi!
Flight::_json($data, $code, true, 'utf-8', $options);
}
// Un tagad to var izmantot šādi
Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT);
JSON un izpildes apturēšana
v3.10.0
Ja vēlaties nosūtīt JSON atbildi un apturēt izpildi, jūs varat izmantot jsonHalt() metodi.
Tas ir noderīgi gadījumos, kad jūs pārbaudāt, iespējams, kādu autorizācijas veidu, un ja lietotājs nav autorizēts, jūs varat nekavējoties nosūtīt JSON atbildi, notīrīt esošo ķermeņa saturu un apturēt izpildi.
Flight::route('/users', function() {
$authorized = someAuthorizationCheck();
// Pārbaudiet, vai lietotājs ir autorizēts
if($authorized === false) {
Flight::jsonHalt(['error' => 'Unauthorized'], 401);
// nav izvades; nepieciešams šeit.
}
// Turpiniet ar pārējo maršrutu
});
Pirms v3.10.0, jums būtu jādara kaut kas šāds:
Flight::route('/users', function() {
$authorized = someAuthorizationCheck();
// Pārbaudiet, vai lietotājs ir autorizēts
if($authorized === false) {
Flight::halt(401, json_encode(['error' => 'Unauthorized']));
}
// Turpiniet ar pārējo maršrutu
});
Atbildes ķermeņa notīrīšana
Ja vēlaties notīrīt atbildes ķermeni, jūs varat izmantot clearBody metodi:
Flight::route('/', function() {
if($someCondition) {
Flight::response()->write("Hello, World!");
} else {
Flight::response()->clearBody();
}
});
Iepriekš minētais lietošanas gadījums, iespējams, nav izplatīts, tomēr tas varētu būt izplatītāks, ja tas tiktu izmantots starpprogrammatūrā.
Izpildes palaišana uz atbildes ķermeņa
Jūs varat palaist izpildes funkciju uz atbildes ķermeņa, izmantojot addResponseBodyCallback metodi:
Flight::route('/users', function() {
$db = Flight::db();
$users = $db->fetchAll("SELECT * FROM users");
Flight::render('users_table', ['users' => $users]);
});
// Tas sasniegs visas atbildes visiem maršrutiem
Flight::response()->addResponseBodyCallback(function($body) {
return gzencode($body, 9);
});
Jūs varat pievienot vairākas izpildes funkcijas, un tās tiks palaistas secībā, kādā tās tika pievienotas. Tā kā tas var pieņemt jebkuru izsaucamu, tas var pieņemt klases masīvu [ $class, 'method' ], aizvēršanu $strReplace = function($body) { str_replace('hi', 'there', $body); };, vai funkcijas nosaukumu 'minify', ja jums ir funkcija, lai samazinātu jūsu html kodu, piemēram.
Piezīme: Maršruta izpildes funkcijas nedarbosies, ja izmantojat flight.v2.output_buffering konfigurācijas opciju.
Īpašs maršruta izpildes funkcija
Ja vēlaties, lai tas attiektos tikai uz specifisku maršrutu, jūs varat pievienot izpildes funkciju pašā maršrutā:
Flight::route('/users', function() {
$db = Flight::db();
$users = $db->fetchAll("SELECT * FROM users");
Flight::render('users_table', ['users' => $users]);
// Tas sasniegs tikai šo maršrutu atbildi
Flight::response()->addResponseBodyCallback(function($body) {
return gzencode($body, 9);
});
});
Starpprogrammatūras opcija
Jūs varat arī izmantot starpprogrammatūru, lai piemērotu izpildes funkciju visiem maršrutiem caur starpprogrammatūru:
// MinifyMiddleware.php
class MinifyMiddleware {
public function before() {
// Šeit piemērojiet izpildes funkciju uz response() objektu.
Flight::response()->addResponseBodyCallback(function($body) {
return $this->minify($body);
});
}
protected function minify(string $body): string {
// kaut kā samaziniet ķermeni
return $body;
}
}
// index.php
Flight::group('/users', function() {
Flight::route('', function() { /* ... */ });
Flight::route('/@id', function($id) { /* ... */ });
}, [ new MinifyMiddleware() ]);
Statusa kodi
Jūs varat iestatīt atbildes statusa kodu, izmantojot status metodi:
Flight::route('/@id', function($id) {
if($id == 123) {
Flight::response()->status(200);
echo "Hello, World!";
} else {
Flight::response()->status(403);
echo "Forbidden";
}
});
Ja vēlaties iegūt pašreizējo statusa kodu, jūs varat izmantot status metodi bez jebkādiem argumentiem:
Flight::response()->status(); // 200
Atbildes galvenes iestatīšana
Jūs varat iestatīt galveni, piemēram, atbildes satura veidu, izmantojot header metodi:
// Tas nosūtīs "Hello, World!" uz lietotāja pārlūkprogrammu kā vienkāršu tekstu
Flight::route('/', function() {
Flight::response()->header('Content-Type', 'text/plain');
// vai
Flight::response()->setHeader('Content-Type', 'text/plain');
echo "Hello, World!";
});
Novirzīšana
Jūs varat novirzīt pašreizējo pieprasījumu, izmantojot redirect() metodi un nododot jaunu URL:
Flight::route('/login', function() {
$username = Flight::request()->data->username;
$password = Flight::request()->data->password;
$passwordConfirm = Flight::request()->data->password_confirm;
if($password !== $passwordConfirm) {
Flight::redirect('/new/location');
return; // tas ir nepieciešams, lai zemāk esošā funkcionalitāte neizpildītos
}
// pievienojiet jauno lietotāju...
Flight::db()->runQuery("INSERT INTO users ....");
Flight::redirect('/admin/dashboard');
});
Piezīme: Pēc noklusējuma Flight nosūta HTTP 303 ("See Other") statusa kodu. Jūs varat izvēles kārtā iestatīt pielāgotu kodu:
Flight::redirect('/new/location', 301); // pastāvīgs
Maršruta izpildes apturēšana
Jūs varat apturēt ietvaru un nekavējoties iziet jebkurā punktā, izsaucot halt metodi:
Flight::halt();
Jūs varat arī norādīt izvēles HTTP statusa kodu un ziņojumu:
Flight::halt(200, 'Be right back...');
Izsaucot halt, tas atmestīs jebkuru atbildes saturu līdz tam punktam un apturēs visu izpildi.
Ja vēlaties apturēt ietvaru un izvadīt pašreizējo atbildi, izmantojiet stop metodi:
Flight::stop($httpStatusCode = null);
Piezīme:
Flight::stop()ir dažas dīvainas uzvedības, piemēram, tas izvadīs atbildi, bet turpinās izpildīt jūsu skriptu, kas var nebūt tas, ko vēlaties. Jūs varat izmantotexitvaireturnpēcFlight::stop()izsaukšanas, lai novērstu turpmāku izpildi, bet parasti iesaka izmantotFlight::halt().
Tas saglabās galvenes atslēgu un vērtību atbildes objektā. Pieprasījuma dzīves cikla beigās tas izveidos galvenes un nosūtīs atbildi.
Uzlabota lietošana
Galvenes nosūtīšana nekavējoties
Var būt gadījumi, kad jums jāizdara kaut kas pielāgots ar galveni, un jums jānosūta galvene tajā pašā koda rindā, ar kuru strādājat. Ja jūs iestatāt straumētu maršrutu, tas ir tas, kas jums būtu nepieciešams. To var sasniegt caur response()->setRealHeader().
Flight::route('/', function() {
Flight::response()->setRealHeader('Content-Type: text/plain');
echo 'Streaming response...';
sleep(5);
echo 'Done!';
})->stream();
JSONP
JSONP pieprasījumiem jūs varat izvēles kārtā nodot vaicājuma parametra nosaukumu, ko izmantojat, lai definētu savu atgriezeniskās saites funkciju:
Flight::jsonp(['id' => 123], 'q');
Tātad, veicot GET pieprasījumu, izmantojot ?q=my_func, jums vajadzētu saņemt izvadi:
my_func({"id":123});
Ja nenododat vaicājuma parametra nosaukumu, tas pēc noklusējuma būs jsonp.
Piezīme: Ja joprojām izmantojat JSONP pieprasījumus 2025. gadā un vēlāk, ielēkiet čatā un pastāstiet mums, kāpēc! Mēs mīlam dzirdēt dažus labus kaujas/briesmu stāstus!
Atbildes datu notīrīšana
Jūs varat notīrīt atbildes ķermeni un galvenes, izmantojot clear() metodi. Tas notīrīs jebkuras galvenes, kas piešķirtas atbildei, notīrīs atbildes ķermeni un iestatīs statusa kodu uz 200.
Flight::response()->clear();
Tikai atbildes ķermeņa notīrīšana
Ja vēlaties notīrīt tikai atbildes ķermeni, jūs varat izmantot clearBody() metodi:
// Tas joprojām saglabās jebkuras galvenes, kas iestatītas uz response() objektu.
Flight::response()->clearBody();
HTTP kešošana
Flight nodrošina iebūvētu atbalstu HTTP līmeņa kešošanai. Ja kešošanas nosacījums ir izpildīts, Flight atgriezīs HTTP 304 Not Modified atbildi. Nākamreiz, kad klients pieprasa to pašu resursu, viņi tiks aicināti izmantot savu lokāli kešoto versiju.
Maršruta līmeņa kešošana
Ja vēlaties kešot visu savu atbildi, jūs varat izmantot cache() metodi un nodot kešošanas laiku.
// Tas kešos atbildi uz 5 minūtēm
Flight::route('/news', function () {
Flight::response()->cache(time() + 300);
echo 'This content will be cached.';
});
// Alternatīvi, jūs varat izmantot virkni, ko nodotu
// strtotime() metodei
Flight::route('/news', function () {
Flight::response()->cache('+5 minutes');
echo 'This content will be cached.';
});
Pēdējā modificēšana
Jūs varat izmantot lastModified metodi un nodot UNIX laika zīmogu, lai iestatītu datumu un laiku, kad lapa tika pēdējo reizi modificēta. Klients turpinās izmantot savu kešu, līdz pēdējās modificēšanas vērtība tiek mainīta.
Flight::route('/news', function () {
Flight::lastModified(1234567890);
echo 'This content will be cached.';
});
ETag
ETag kešošana ir līdzīga Last-Modified, izņemot to, ka jūs varat norādīt jebkuru ID, ko vēlaties resursam:
Flight::route('/news', function () {
Flight::etag('my-unique-id');
echo 'This content will be cached.';
});
Ņemiet vērā, ka izsaucot vai nu lastModified, vai etag, tas abus iestatīs un pārbaudīs keša vērtību. Ja keša vērtība ir tāda pati starp pieprasījumiem, Flight nekavējoties nosūtīs HTTP 304 atbildi un apturēs apstrādi.
Faila lejupielāde
v3.12.0
Ir palīgmēģinājuma metode, lai straumētu failu galapunktam. Jūs varat izmantot download metodi un nodot ceļu.
Flight::route('/download', function () {
Flight::download('/path/to/file.txt');
// No v3.17.1 jūs varat norādīt pielāgotu faila nosaukumu lejupielādei
Flight::download('/path/to/file.txt', 'custom_name.txt');
});
Skatīt arī
- Maršrutēšana - Kā kartēt maršrutus uz kontrolieriem un renderēt skatus.
- Pieprasījumi - Izpratne par to, kā apstrādāt ienākošos pieprasījumus.
- Starpprogrammatūra - Starpprogrammatūras izmantošana ar maršrutiem autentifikācijai, žurnālošanai utt.
- Kāpēc ietvars? - Izpratne par ietvara, piemēram, Flight, izmantošanas priekšrocībām.
- Paplašināšana - Kā paplašināt Flight ar savu funkcionalitāti.
Traucējummeklēšana
- Ja jums ir problēmas ar novirzīšanām, kas nedarbojas, pārliecinieties, ka pievienojat
return;metodē. stop()unhalt()nav tas pats.halt()nekavējoties apturēs izpildi, savukārtstop()ļaus izpildei turpināties.
Izmaiņu žurnāls
- v3.17.1 - Pievienots
$fileNamedownloadFile()metodei. - v3.12.0 - Pievienota downloadFile palīgmēģinājuma metode.
- v3.10.0 - Pievienots
jsonHalt. - v1.0 - Sākotnējais izdevums.
Learn/events
Notikumu pārvaldnieks
no v3.15.0
Pārskats
Notikumi ļauj reģistrēt un izraisīt pielāgotu uzvedību jūsu lietojumprogrammā. Ar Flight::onEvent() un Flight::triggerEvent() pievienošanu jūs tagad varat savienoties ar galvenajiem jūsu lietojumprogrammas dzīves cikla brīžiem vai definēt savus notikumus (piemēram, paziņojumus un e-pastus), lai padarītu jūsu kodu modulārāku un paplašināmu. Šīs metodes ir daļa no Flight mappable methods, kas nozīmē, ka jūs varat pārdefinēt to uzvedību atbilstoši savām vajadzībām.
Saprašana
Notikumi ļauj atdalīt dažādas jūsu lietojumprogrammas daļas, lai tās pārāk stipri nepaļautos viena uz otru. Šī atdalīšana — bieži saukta par decoupling — padara jūsu kodu vieglāku atjaunināt, paplašināt vai atkļūdot. Tā vietā, lai rakstītu visu vienā lielā gabalā, jūs varat sadalīt savu loģiku mazākos, neatkarīgos gabalos, kas reaģē uz specifiskām darbībām (notikumiem).
Iedomājieties, ka jūs veidojat emuāru lietojumprogrammu:
- Kad lietotājs publicē komentāru, jūs varētu vēlēties:
- Saglabāt komentāru datubāzē.
- Nosūtīt e-pastu emuāra īpašniekam.
- Reģistrēt darbību drošības nolūkos.
Bez notikumiem jūs visu sapotu vienā funkcijā. Ar notikumiem jūs varat to sadalīt: viena daļa saglabā komentāru, cita izraisa notikumu, piemēram, 'comment.posted', un atsevišķi klausītāji apstrādā e-pastu un reģistrēšanu. Tas uztur jūsu kodu tīrāku un ļauj pievienot vai noņemt funkcijas (piemēram, paziņojumus) bez pieskāriena kodola loģikai.
Izplatīti izmantošanas gadījumi
Lielākoties notikumi ir piemēroti lietām, kas ir izvēles, bet ne absolūti kodola daļa jūsu sistēmā. Piemēram, sekojošie ir labi, bet ja tie kaut kāda iemesla dēļ neizdodas, jūsu lietojumprogramma joprojām darbojas:
- Reģistrēšana: Reģistrēt darbības, piemēram, pieteikšanos vai kļūdas, bez jūsu galvenā koda sajaukšanas.
- Paziņojumi: Nosūtīt e-pastus vai brīdinājumus, kad kaut kas notiek.
- Kešatjauninājumi: Atsvaidzināt kešus vai informēt citas sistēmas par izmaiņām.
Tomēr pieņemsim, ka jums ir aizmirsta parole funkcija. Tā jābūt jūsu kodola funkcionalitātes daļai un nevis notikumam, jo ja tas e-pasts netiek nosūtīts, jūsu lietotājs nevar atiestatīt paroli un izmantot jūsu lietojumprogrammu.
Pamata izmantošana
Flight notikumu sistēma ir balstīta uz divām galvenajām metodēm: Flight::onEvent() notikumu klausītāju reģistrēšanai un Flight::triggerEvent() notikumu izraisīšanai. Lūk, kā jūs varat tās izmantot:
Notikumu klausītāju reģistrēšana
Lai klausītos notikumu, izmantojiet Flight::onEvent(). Šī metode ļauj definēt, kas jānotiek, kad notikums notiek.
Flight::onEvent(string $event, callable $callback): void
$event: Nosaukums jūsu notikumam (piemēram,'user.login').$callback: Funkcija, kas jāizpilda, kad notikums tiek izraisīts.
Jūs "abonējat" notikumu, sakot Flight, ko darīt, kad tas notiek. Atsaukums var pieņemt argumentus, kas nodoti no notikuma izraisītāja.
Flight notikumu sistēma ir sinhrona, kas nozīmē, ka katrs notikuma klausītājs tiek izpildīts secīgi, viens pēc otra. Kad jūs izraisa notikumu, visi reģistrētie klausītāji tam notikumam tiks izpildīti līdz galam, pirms jūsu kods turpinās. Tas ir svarīgi saprast, jo tas atšķiras no asinhronām notikumu sistēmām, kur klausītāji var darboties paralēli vai vēlākā laikā.
Vienkāršs piemērs
Flight::onEvent('user.login', function ($username) {
echo "Welcome back, $username!";
// you can send an email if the login is from a new location
});
Šeit, kad 'user.login' notikums tiek izraisīts, tas sveiks lietotāju vārdā un varētu ietvert loģiku e-pasta nosūtīšanai, ja nepieciešams.
Piezīme: Atsaukums var būt funkcija, anonīma funkcija vai klases metode.
Notikumu izraisīšana
Lai notikums notiktu, izmantojiet Flight::triggerEvent(). Tas saka Flight izpildīt visus klausītājus, kas reģistrēti tam notikumam, nododot līdzi jebkādu datu, ko jūs nododiet.
Flight::triggerEvent(string $event, ...$args): void
$event: Notikuma nosaukums, ko jūs izraisa (jāatbilst reģistrētam notikumam)....$args: Izvēles argumenti, ko nosūtīt klausītājiem (var būt jebkurš argumentu skaits).
Vienkāršs piemērs
$username = 'alice';
Flight::triggerEvent('user.login', $username);
Tas izraisa 'user.login' notikumu un nosūta 'alice' klausītājam, ko mēs definējām iepriekš, kas izvadīs: Welcome back, alice!.
- Ja nav reģistrēti klausītāji, nekas nenotiek — jūsu lietojumprogramma nesabojāsies.
- Izmantojiet izplatīšanas operatoru (
...), lai elastīgi nodotu vairākus argumentus.
Notikumu apturēšana
Ja klausītājs atgriež false, papildu klausītāji tam notikumam netiks izpildīti. Tas ļauj apturēt notikumu ķēdi, balstoties uz specifiskiem nosacījumiem. Atcerieties, ka klausītāju secība ir svarīga, jo pirmais, kas atgriež false, apturēs pārējos.
Piemērs:
Flight::onEvent('user.login', function ($username) {
if (isBanned($username)) {
logoutUser($username);
return false; // Stops subsequent listeners
}
});
Flight::onEvent('user.login', function ($username) {
sendWelcomeEmail($username); // this is never sent
});
Notikumu metožu pārdefinēšana
Flight::onEvent() un Flight::triggerEvent() ir pieejamas paplašināšanai, kas nozīmē, ka jūs varat pārdefinēt, kā tās darbojas. Tas ir lieliski attīstītiem lietotājiem, kas vēlas pielāgot notikumu sistēmu, piemēram, pievienojot reģistrēšanu vai mainot, kā notikumi tiek izplatīti.
Piemērs: onEvent pielāgošana
Flight::map('onEvent', function (string $event, callable $callback) {
// Log every event registration
error_log("New event listener added for: $event");
// Call the default behavior (assuming an internal event system)
Flight::_onEvent($event, $callback);
});
Tagad katru reizi, kad jūs reģistrējat notikumu, tas to reģistrē pirms turpināšanas.
Kāpēc pārdefinēt?
- Pievienot atkļūdošanu vai uzraudzību.
- Ierobežot notikumus noteiktās vidēs (piemēram, atslēgt testēšanā).
- Integrēt ar citu notikumu bibliotēku.
Kur novietot savus notikumus
Ja jūs esat jauns notikumu konceptos savā projektā, jūs varētu brīnīties: kur es reģistrēju visus šos notikumus savā lietojumprogrammā? Flight vienkāršība nozīmē, ka nav stingra noteikuma — jūs varat tos novietot kur vien tas ir loģiski jūsu projektam. Tomēr to organizēšana palīdz uzturēt jūsu kodu, kad jūsu lietojumprogramma aug. Lūk, daži praktiski varianti un labākās prakses, pielāgotas Flight vieglajai dabai:
Opcija 1: Jūsu galvenajā index.php
Mazām lietojumprogrammām vai ātriem prototipiem jūs varat reģistrēt notikumus tieši jūsu index.php failā blakus jūsu maršrutiem. Tas uztur visu vienā vietā, kas ir labi, kad vienkāršība ir jūsu prioritāte.
require 'vendor/autoload.php';
// Register events
Flight::onEvent('user.login', function ($username) {
error_log("$username logged in at " . date('Y-m-d H:i:s'));
});
// Define routes
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
echo "Logged in!";
});
Flight::start();
- Priekšrocības: Vienkārši, nav papildu failu, lieliski maziem projektiem.
- Trūkumi: Var kļūt nekārtīgs, kad jūsu lietojumprogramma aug ar vairāk notikumiem un maršrutiem.
Opcija 2: Atsevišķs events.php fails
Nedaudz lielākai lietojumprogrammai apsveriet notikumu reģistrāciju pārvietošanu uz veltītu failu, piemēram, app/config/events.php. Iekļaujiet šo failu jūsu index.php pirms jūsu maršrutiem. Tas imitē, kā maršruti bieži ir organizēti app/config/routes.php Flight projektos.
// app/config/events.php
Flight::onEvent('user.login', function ($username) {
error_log("$username logged in at " . date('Y-m-d H:i:s'));
});
Flight::onEvent('user.registered', function ($email, $name) {
echo "Email sent to $email: Welcome, $name!";
});
// index.php
require 'vendor/autoload.php';
require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
echo "Logged in!";
});
Flight::start();
- Priekšrocības: Uztur
index.phpfokusētu uz maršrutēšanu, loģiski organizē notikumus, viegli atrast un rediģēt. - Trūkumi: Pievieno mazu struktūru, kas var šķist pārspīlēta ļoti mazām lietojumprogrammām.
Opcija 3: Tuvu tam, kur tie tiek izraisīti
Vēl viena pieeja ir reģistrēt notikumus tuvu vietai, kur tie tiek izraisīti, piemēram, iekšā kontrolierī vai maršruta definīcijā. Tas labi darbojas, ja notikums ir specifisks vienai jūsu lietojumprogrammas daļai.
Flight::route('/signup', function () {
// Register event here
Flight::onEvent('user.registered', function ($email) {
echo "Welcome email sent to $email!";
});
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
echo "Signed up!";
});
- Priekšrocības: Uztur saistītu kodu kopā, labi izolētām funkcijām.
- Trūkumi: Izkliedē notikumu reģistrācijas, padarot grūtāku redzēt visus notikumus uzreiz; risks dublikēt reģistrācijas, ja neuzmanīgs.
Labākā prakse Flight
- Sākt vienkārši: Mazām lietojumprogrammām novietojiet notikumus
index.php. Tas ir ātri un atbilst Flight minimālismam. - Augt gudri: Kad jūsu lietojumprogramma paplašinās (piemēram, vairāk nekā 5-10 notikumi), izmantojiet
app/config/events.phpfailu. Tas ir dabisks solis uz augšu, kā maršrutu organizēšana, un uztur jūsu kodu sakārtotu bez sarežģītu ietvaru pievienošanas. - Izvairīties no pārspīlējuma: Neizveidojiet pilnībā attīstītu “notikumu pārvaldnieka” klasi vai direktoriju, ja vien jūsu lietojumprogramma nekļūst milzīga — Flight uzplaukst vienkāršībā, tāpēc uzturiet to vieglu.
Padoms: Grupēt pēc mērķa
events.php failā grupējiet saistītus notikumus (piemēram, visus lietotāju saistītos notikumus kopā) ar komentāriem skaidrībai:
// app/config/events.php
// User Events
Flight::onEvent('user.login', function ($username) {
error_log("$username logged in");
});
Flight::onEvent('user.registered', function ($email) {
echo "Welcome to $email!";
});
// Page Events
Flight::onEvent('page.updated', function ($pageId) {
Flight::cache()->delete("page_$pageId");
});
Šī struktūra labi paplašinās un paliek iesācējam draudzīga.
Reālas pasaules piemēri
Apskatīsim dažus reālas pasaules scenārijus, lai parādītu, kā notikumi darbojas un kāpēc tie ir noderīgi.
Piemērs 1: Lietotāja pieteikšanās reģistrēšana
// Step 1: Register a listener
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
error_log("$username logged in at $time");
});
// Step 2: Trigger it in your app
Flight::route('/login', function () {
$username = 'bob'; // Pretend this comes from a form
Flight::triggerEvent('user.login', $username);
echo "Hi, $username!";
});
Kāpēc tas ir noderīgs: Pieteikšanās kods nav jāzina par reģistrēšanu — tas tikai izraisa notikumu. Vēlāk jūs varat pievienot vairāk klausītāju (piemēram, nosūtīt sveiciena e-pastu) bez maršruta maiņas.
Piemērs 2: Paziņošana par jauniem lietotājiem
// Listener for new registrations
Flight::onEvent('user.registered', function ($email, $name) {
// Simulate sending an email
echo "Email sent to $email: Welcome, $name!";
});
// Trigger it when someone signs up
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
Flight::triggerEvent('user.registered', $email, $name);
echo "Thanks for signing up!";
});
Kāpēc tas ir noderīgs: Reģistrācijas loģika fokusējas uz lietotāja izveidošanu, kamēr notikums apstrādā paziņojumus. Jūs varētu vēlāk pievienot vairāk klausītāju (piemēram, reģistrēt reģistrāciju).
Piemērs 3: Keša dzēšana
// Listener to clear a cache
Flight::onEvent('page.updated', function ($pageId) {
// if using the flightphp/cache plugin
Flight::cache()->delete("page_$pageId");
echo "Cache cleared for page $pageId.";
});
// Trigger when a page is edited
Flight::route('/edit-page/(@id)', function ($pageId) {
// Pretend we updated the page
Flight::triggerEvent('page.updated', $pageId);
echo "Page $pageId updated.";
});
Kāpēc tas ir noderīgs: Rediģēšanas kods neuztraucas par kešošanu — tas tikai signalizē atjauninājumu. Citas lietojumprogrammas daļas var reaģēt pēc vajadzības.
Labākās prakses
- Skaidri nosaukt notikumus: Izmantojiet specifiskus nosaukumus, piemēram,
'user.login'vai'page.updated', lai būtu acīmredzams, ko tie dara. - Uzturēt klausītājus vienkāršus: Neievietojiet lēnas vai sarežģītas uzdevumus klausītājos — uzturiet savu lietojumprogrammu ātru.
- Testēt savus notikumus: Izraisiet tos manuāli, lai nodrošinātu, ka klausītāji darbojas kā paredzēts.
- Izmantot notikumus gudri: Tie ir lieliski atdalīšanai, bet pārāk daudzi var padarīt jūsu kodu grūti izsekojamu — izmantojiet tos, kad tas ir loģiski.
Flight PHP notikumu sistēma ar Flight::onEvent() un Flight::triggerEvent() sniedz jums vienkāršu, bet spēcīgu veidu, kā būvēt elastīgas lietojumprogrammas. Ļaujot dažādām jūsu lietojumprogrammas daļām sazināties caur notikumiem, jūs varat uzturēt savu kodu organizētu, atkārtoti izmantojamu un viegli paplašināmu. Vai nu jūs reģistrējat darbības, sūtat paziņojumus vai pārvaldāt atjauninājumus, notikumi palīdz to darīt bez jūsu loģikas savijuma. Turklāt, ar iespēju pārdefinēt šīs metodes, jums ir brīvība pielāgot sistēmu savām vajadzībām. Sāciet mazu ar vienu notikumu un skatieties, kā tas pārveido jūsu lietojumprogrammas struktūru!
Iebūvētie notikumi
Flight PHP nāk ar dažiem iebūvētiem notikumiem, ko jūs varat izmantot, lai savienotos ar ietvara dzīves ciklu. Šie notikumi tiek izraisīti specifiskos pieprasījuma/atbildes cikla punktos, ļaujot jums izpildīt pielāgotu loģiku, kad notiek noteiktas darbības.
Iebūvēto notikumu saraksts
- flight.request.received:
function(Request $request)Izraisīts, kad pieprasījums tiek saņemts, parsēts un apstrādāts. - flight.error:
function(Throwable $exception)Izraisīts, kad kļūda rodas pieprasījuma dzīves cikla laikā. - flight.redirect:
function(string $url, int $status_code)Izraisīts, kad tiek uzsākta pāradresēšana. - flight.cache.checked:
function(string $cache_key, bool $hit, float $executionTime)Izraisīts, kad kešs tiek pārbaudīts specifiskai atslēgai un vai kešs trāpījis vai ne. - flight.middleware.before:
function(Route $route)Izraisīts pēc before middleware izpildes. - flight.middleware.after:
function(Route $route)Izraisīts pēc after middleware izpildes. - flight.middleware.executed:
function(Route $route, $middleware, string $method, float $executionTime)Izraisīts pēc jebkura middleware izpildes - flight.route.matched:
function(Route $route)Izraisīts, kad maršruts ir saskaņots, bet vēl nav izpildīts. - flight.route.executed:
function(Route $route, float $executionTime)Izraisīts pēc maršruta izpildes un apstrādes.$executionTimeir laiks, kas vajadzīgs maršruta izpildei (izsaukt kontrolieri utt.). - flight.view.rendered:
function(string $template_file_path, float $executionTime)Izraisīts pēc skata renderēšanas.$executionTimeir laiks, kas vajadzīgs veidnes renderēšanai. Piezīme: Ja jūs pārdefinējatrendermetodi, jums būs jāizraisa šis notikums atkārtoti. - flight.response.sent:
function(Response $response, float $executionTime)Izraisīts pēc atbildes nosūtīšanas klientam.$executionTimeir laiks, kas vajadzīgs atbildes izveidošanai.
Skatīt arī
- Extending Flight - Kā paplašināt un pielāgot Flight kodola funkcionalitāti.
- Cache - Piemērs, kā izmantot notikumus keša dzēšanai, kad lapa tiek atjaunināta.
Problēmu risināšana
- Ja jūs neredzat savus notikumu klausītājus tiek izsauktus, pārliecinieties, ka jūs tos reģistrējat pirms notikumu izraisīšanas. Reģistrācijas secība ir svarīga.
Izmaiņu žurnāls
- v3.15.0 - Pievienoti notikumi Flight.
Learn/templates
HTML skati un veidnes
Pārskats
Flight pēc noklusējuma nodrošina pamata HTML veidņu funkcionalitāti. Veidņu izmantošana ir ļoti efektīvs veids, kā atdalīt lietojumprogrammas loģiku no prezentācijas slāņa. Īpašs dzinējs (Twig, Latte utt.) arī sniedz AI kodēšanas rīkiem pazīstamu, ierobežotu sintaksi, tāpēc tie mazāk iemaisīs biznesa loģiku jūsu HTML.
Izpratne
Veidojot lietojumprogrammu, jums, visticamāk, būs HTML, ko vēlēsities nosūtīt atpakaļ gala lietotājam. PHP pats par sevi ir veidņu valoda, bet tajā ir ļoti viegli iepīt biznesa loģiku, piemēram, datubāzes izsaukumus, API izsaukumus utt., jūsu HTML failā, padarot testēšanu un atsaistīšanu par ļoti sarežģītu procesu. Ievietojot datus veidnē un ļaujot veidnei sevi atveidot, kļūst daudz vieglāk atsaistīt un vienību testēt savu kodu. Jūs mums pateiksieties, ja izmantosiet veidnes!
Pamata lietošana
Flight ļauj nomainīt noklusējuma skatu dzinēju, vienkārši kartējot render (vai reģistrējot skatu klasi). Ritiniet uz leju, lai redzētu Twig, Latte, Smarty, Blade un citus.
Skeleton noklusējums: Oficiālais flightphp/skeleton izmanto tikai Twig mapē
app/views/(*.twig). Kontrolleri izsauc$this->app->render('welcome', $data)(paplašinājums nav obligāts). Tā ir lietojumprogrammas izvēle jauniem projektiem—nevis Flight kodola prasība. Latte un citi dzinēji joprojām tiek pilnībā atbalstīti.
Twig
skeleton noklusējums
Twig ir elastīgs, ātrs un drošs veidņu dzinējs, ko izmanto Symfony un daudzi citi PHP projekti. AI kodēšanas rīki mēdz īpaši labi pārzināt Twig, un tas pēc noklusējuma automātiski izbēg izvadi, kas palīdz aizsargāties pret XSS.
Instalēšana
composer require twig/twig
(Jau iekļauts, kad veicat composer create-project flightphp/skeleton.)
Pamata konfigurācija
Pārrakstiet render metodi, lai izmantotu Twig, nevis noklusējuma PHP renderētāju:
// pārrakstiet render metodi, lai izmantotu Twig, nevis noklusējuma PHP renderētāju
Flight::map('render', function(string $template, array $data): void {
$loader = new \Twig\Loader\FilesystemLoader(Flight::get('flight.views.path'));
$twig = new \Twig\Environment($loader, [
// Kur Twig glabā savas kompilētās veidnes
'cache' => __DIR__ . '/../cache/twig',
'auto_reload' => true,
]);
// Atļauj "welcome" vai "welcome.twig"
if (substr($template, -5) !== '.twig') {
$template .= '.twig';
}
echo $twig->render($template, $data);
});
Skeleton šis savienojums atrodas app/config/services.php (kopīga Twig vide, kešatmiņas ceļš, globālie mainīgie, piemēram, base_url / CSP nonce). Labāk injicējiet Engine un izsauciet $app->render() no kontrolleriem, lai kods paliktu AI- un testiem draudzīgs.
Twig izmantošana Flight
Tagad, kad varat renderēt ar Twig, varat darīt, piemēram, šādi:
{# app/views/home.twig #}
<html>
<head>
<title>{% if title %}{{ title }} - {% endif %}My App</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Hello, {{ name }}!</h1>
</body>
</html>
// routes.php
Flight::route('/@name', function ($name) {
Flight::render('home.twig', [
'title' => 'Home Page',
'name' => $name
]);
});
Kad pārlūkprogrammā apmeklējat /Bob, izvade būtu:
<html>
<head>
<title>Home Page - My App</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Hello, Bob!</h1>
</body>
</html>
Papildu lasīšana
Pilnīgāks Twig izmantošanas piemērs ar izkārtojumiem ir parādīts šīs dokumentācijas awesome plugins sadaļā. Lai redzētu renderēšanas laika metriku Tracy joslā, skatiet Twig paneli Tracy Extensions.
Vairāk par Twig pilnajām iespējām varat uzzināt, lasot oficiālo dokumentāciju.
Latte
lieliska alternatīva
Latte ir pilnvērtīgs dzinējs ar PHP līdzīgu sintaksi. Tas joprojām ir lieliska izvēle Flight lietotnēm; skeleton vienkārši standartizē Twig kā vienu kopīgu noklusējumu (īpaši noderīgi, kad AI rīki ģenerē veidnes).
Instalēšana
composer require latte/latte
Pamata konfigurācija
Galvenā doma ir pārrakstīt render metodi, lai izmantotu Latte, nevis noklusējuma PHP renderētāju.
// pārrakstiet render metodi, lai izmantotu latte, nevis noklusējuma PHP renderētāju
Flight::map('render', function(string $template, array $data, ?string $block): void {
$latte = new Latte\Engine;
// Kur latte tieši glabā savu kešatmiņu
$latte->setTempDirectory(__DIR__ . '/../cache/');
$finalPath = Flight::get('flight.views.path') . $template;
$latte->render($finalPath, $data, $block);
});
Latte izmantošana Flight
Tagad, kad varat renderēt ar Latte, varat darīt, piemēram, šādi:
<!-- app/views/home.latte -->
<html>
<head>
<title>{$title ? $title . ' - '}My App</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Hello, {$name}!</h1>
</body>
</html>
// routes.php
Flight::route('/@name', function ($name) {
Flight::render('home.latte', [
'title' => 'Home Page',
'name' => $name
]);
});
Kad pārlūkprogrammā apmeklējat /Bob, izvade būtu:
<html>
<head>
<title>Home Page - My App</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Hello, Bob!</h1>
</body>
</html>
Papildu lasīšana
Sarežģītāks Latte izmantošanas piemērs ar izkārtojumiem ir parādīts šīs dokumentācijas awesome plugins sadaļā.
Vairāk par Latte pilnajām iespējām, tostarp tulkošanas un valodu iespējām, varat uzzināt, lasot oficiālo dokumentāciju.
Iebūvētais skatu dzinējs
novecojis
Piezīme: Lai gan tā joprojām ir noklusējuma funkcionalitāte un tehniski joprojām darbojas.
Lai attēlotu skata veidni, izsauciet render metodi ar veidnes faila nosaukumu un neobligātiem veidnes datiem:
Flight::render('hello.php', ['name' => 'Bob']);
Veidnes dati, ko nododat, tiek automātiski ievadīti veidnē, un uz tiem var atsaukties kā uz lokāliem mainīgajiem. Veidņu faili ir vienkārši PHP faili. Ja hello.php veidnes faila saturs ir:
Hello, <?= $name ?>!
Izvade būtu:
Hello, Bob!
Varat arī manuāli iestatīt skata mainīgos, izmantojot set metodi:
Flight::view()->set('name', 'Bob');
Mainīgais name tagad ir pieejams visos jūsu skatos. Tātad varat vienkārši darīt:
Flight::render('hello');
Ņemiet vērā, ka, norādot veidnes nosaukumu render metodē, varat izlaist .php paplašinājumu.
Pēc noklusējuma Flight meklēs views direktoriju veidņu failiem. Varat iestatīt citu ceļu savām veidnēm, iestatot šādu konfigurāciju:
Flight::set('flight.views.path', '/path/to/views');
Izkārtojumi
Tīmekļa vietnēm ir izplatīts vienots izkārtojuma veidnes fails ar mainīgu saturu. Lai renderētu saturu, kas tiks izmantots izkārtojumā, varat nodot neobligātu parametru render metodei.
Flight::render('header', ['heading' => 'Hello'], 'headerContent');
Flight::render('body', ['body' => 'World'], 'bodyContent');
Jūsu skatam tad būs saglabātie mainīgie ar nosaukumiem headerContent un bodyContent. Pēc tam varat renderēt savu izkārtojumu šādi:
Flight::render('layout', ['title' => 'Home Page']);
Ja veidņu faili izskatās šādi:
header.php:
<h1><?= $heading ?></h1>
body.php:
<div><?= $body ?></div>
layout.php:
<html>
<head>
<title><?= $title ?></title>
</head>
<body>
<?= $headerContent ?>
<?= $bodyContent ?>
</body>
</html>
Izvade būtu:
<html>
<head>
<title>Home Page</title>
</head>
<body>
<h1>Hello</h1>
<div>World</div>
</body>
</html>
Smarty
Lūk, kā jūs varētu izmantot Smarty veidņu dzinēju saviem skatiem:
// Ielādē Smarty bibliotēku
require './Smarty/libs/Smarty.class.php';
// Reģistrē Smarty kā skatu klasi
// Nodod arī atzvanīšanas funkciju, lai konfigurētu Smarty ielādes laikā
Flight::register('view', Smarty::class, [], function (Smarty $smarty) {
$smarty->setTemplateDir('./templates/');
$smarty->setCompileDir('./templates_c/');
$smarty->setConfigDir('./config/');
$smarty->setCacheDir('./cache/');
});
// Piešķir veidnes datus
Flight::view()->assign('name', 'Bob');
// Attēlo veidni
Flight::view()->display('hello.tpl');
Lai nodrošinātu pilnīgumu, jums vajadzētu arī pārrakstīt Flight noklusējuma render metodi:
Flight::map('render', function(string $template, array $data): void {
Flight::view()->assign($data);
Flight::view()->display($template);
});
Blade
Lūk, kā jūs varētu izmantot Blade veidņu dzinēju saviem skatiem:
Pirmkārt, jums ir jāinstalē BladeOne bibliotēka, izmantojot Composer:
composer require eftec/bladeone
Pēc tam varat konfigurēt BladeOne kā skatu klasi Flight:
<?php
// Ielādē BladeOne bibliotēku
use eftec\bladeone\BladeOne;
// Reģistrē BladeOne kā skatu klasi
// Nodod arī atzvanīšanas funkciju, lai konfigurētu BladeOne ielādes laikā
Flight::register('view', BladeOne::class, [], function (BladeOne $blade) {
$views = __DIR__ . '/../views';
$cache = __DIR__ . '/../cache';
$blade->setPath($views);
$blade->setCompiledPath($cache);
});
// Piešķir veidnes datus
Flight::view()->share('name', 'Bob');
// Attēlo veidni
echo Flight::view()->run('hello', []);
Lai nodrošinātu pilnīgumu, jums vajadzētu arī pārrakstīt Flight noklusējuma render metodi:
<?php
Flight::map('render', function(string $template, array $data): void {
echo Flight::view()->run($template, $data);
});
Šajā piemērā hello.blade.php veidnes fails varētu izskatīties šādi:
<?php
Hello, {{ $name }}!
Izvade būtu:
Hello, Bob!
Skatīt arī
- Instalēšana - Skeleton izkārtojums (
app/views/*.twig) jauniem projektiem. - Paplašināšana - Kā pārrakstīt
rendermetodi, lai izmantotu citu veidņu dzinēju. - Maršrutēšana - Kā kartēt maršrutus uz kontrolleriem un renderēt skatus.
- Atbildes - Kā pielāgot HTTP atbildes.
- Drošība - Automātiskā izbēgšana un XSS.
- AI un izstrādātāja pieredze - Kāpēc viens veidņu dzinēja noklusējums palīdz kodēšanas aģentiem.
- Kāpēc ietvars? - Kā veidnes iekļaujas lielajā attēlā.
Problēmu novēršana
- Ja starpprogrammatūrā (middleware) ir novirzīšana (redirect), bet jūsu lietotne, šķiet, nenovirza, pārliecinieties, ka starpprogrammatūrā pievienojat
exit;paziņojumu. - Ja Twig nevar atrast veidni, pārbaudiet
flight.views.pathun to, vai fails pastāv šajā ceļā ar paredzēto paplašinājumu (skeleton:app/views/).
Izmaiņu žurnāls
- Dokumentācija – Twig dokumentēts kā oficiālais skeleton noklusējums; Latte joprojām ir pirmšķirīga alternatīva.
- v2.0 - Sākotnējais laidiens.
Learn/simple_pdo
SimplePdo PDO Palīdze Ģimene
Pārskats
SimplePdo klase Flight ir moderna, funkcijām bagāta palīdze darbam ar datubāzēm, izmantojot PDO. Tā paplašina PdoWrapper un pievieno ērtas palīgmēģenēm izplatītām datubāzes operācijām, piemēram, insert(), update(), delete() un transakcijām. Tā vienkāršo datubāzes uzdevumus, atgriež rezultātus kā Collections vieglai piekļuvei un atbalsta vaicājumu žurnālveidošanu un lietojumprogrammas veiktspējas uzraudzību (APM) sarežģītām lietošanas situācijām.
Saprašana
SimplePdo klase ir izstrādāta, lai padarītu darbu ar datubāzēm PHP daudz vieglāku. Tā vietā, lai žonglētu ar sagatavotiem paziņojumiem, iegūšanas režīmiem un verbāliem SQL operācijām, jūs saņemat tīras, vienkāršas metodes izplatītiem uzdevumiem. Katra rindiņa tiek atgriezta kā Collection, tāpēc jūs varat izmantot gan masīva notāciju ($row['name']), gan objekta notāciju ($row->name).
Šī klase ir PdoWrapper pārklājums, kas nozīmē, ka tā ietver visu PdoWrapper funkcionalitāti plus papildu palīgmēģenes, kas padara jūsu kodu tīrāku un vieglāk uzturamu. Ja jūs pašlaik izmantojat PdoWrapper, pāreja uz SimplePdo ir vienkārša, jo tā paplašina PdoWrapper.
Jūs varat reģistrēt SimplePdo kā kopīgu servisu Flight, un tad izmantot to jebkur savā lietojumprogrammā caur Flight::db().
Pamata Lietošana
Reģistrēšana SimplePdo
Vispirms reģistrējiet SimplePdo klasi Flight:
Flight::register('db', \flight\database\SimplePdo::class, [
'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8mb4\'',
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]
]);
PIEZĪME
Ja jūs ne norādāt
PDO::ATTR_DEFAULT_FETCH_MODE,SimplePdoautomātiski iestatīs to uzPDO::FETCH_ASSOCjūsu vietā.
Tagad jūs varat izmantot Flight::db() jebkur, lai iegūtu savienojumu ar datubāzi.
Vaicājumu Izpilde
runQuery()
function runQuery(string $sql, array $params = []): PDOStatement
Izmantojiet to INSERT, UPDATE vai kad vēlaties pašrocīgi iegūt rezultātus:
$db = Flight::db();
$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']);
while ($row = $statement->fetch()) {
// $row ir masīvs
}
Jūs varat izmantot to arī rakstīšanai:
$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']);
$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]);
fetchField()
function fetchField(string $sql, array $params = []): mixed
Iegūstiet vienu vērtību no datubāzes:
$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']);
fetchRow()
function fetchRow(string $sql, array $params = []): ?Collection
Iegūstiet vienu rindiņu kā Collection (masīva/objekta piekļuve):
$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]);
echo $user['name'];
// vai
echo $user->name;
PADOMS
SimplePdoautomātiski pievienoLIMIT 1vaicājumiemfetchRow(), ja tas vēl nav klāt, padarot jūsu vaicājumus efektīvākus.
fetchAll()
function fetchAll(string $sql, array $params = []): array<Collection>
Iegūstiet visas rindiņas kā Collection masīvu:
$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']);
foreach ($users as $user) {
echo $user['name'];
// vai
echo $user->name;
}
fetchColumn()
function fetchColumn(string $sql, array $params = []): array
Iegūstiet vienu kolonnu kā masīvu:
$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]);
// Atgriež: [1, 2, 3, 4, 5]
fetchPairs()
function fetchPairs(string $sql, array $params = []): array
Iegūstiet rezultātus kā atslēgu-vērtību pārus (pirmā kolonna kā atslēga, otrā kā vērtība):
$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users");
// Atgriež: [1 => 'John', 2 => 'Jane', 3 => 'Bob']
Izmantojot IN() Vietas Turētājus
Jūs varat izmantot vienu ? IN() klauzulā un nodot masīvu:
$ids = [1, 2, 3];
$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]);
Palīgmēģenes
Viens no galvenajiem SimplePdo priekšrocībām salīdzinājumā ar PdoWrapper ir ērtu palīgmēģeņu pievienošana izplatītām datubāzes operācijām.
insert()
function insert(string $table, array $data): string
Ievietojiet vienu vai vairākas rindiņas un atgrieziet pēdējo ievietošanas ID.
Viena ievietošana:
$id = Flight::db()->insert('users', [
'name' => 'John',
'email' => 'john@example.com'
]);
Masveida ievietošana:
$id = Flight::db()->insert('users', [
['name' => 'John', 'email' => 'john@example.com'],
['name' => 'Jane', 'email' => 'jane@example.com'],
]);
update()
function update(string $table, array $data, string $where, array $whereParams = []): int
Atjauniniet rindiņas un atgrieziet skarto rindiņu skaitu:
$affected = Flight::db()->update(
'users',
['name' => 'Jane', 'email' => 'jane@example.com'],
'id = ?',
[1]
);
PIEZĪME
SQLite
rowCount()atgriež skaitu rindiņu, kur dati patiešām mainījās. Ja jūs atjauninat rindiņu ar tām pašām vērtībām, kas tai jau ir,rowCount()atgriezīs 0. Tas atšķiras no MySQL uzvedības, izmantojotPDO::MYSQL_ATTR_FOUND_ROWS.
delete()
function delete(string $table, string $where, array $whereParams = []): int
Dzēsiet rindiņas un atgrieziet dzēsto rindiņu skaitu:
$deleted = Flight::db()->delete('users', 'id = ?', [1]);
transaction()
function transaction(callable $callback): mixed
Izpildiet atsaukumu transakcijas ietvaros. Transakcija automātiski apstiprina veiksmīgos gadījumos vai atgriežas kļūdas gadījumā:
$result = Flight::db()->transaction(function($db) {
$db->insert('users', ['name' => 'John']);
$db->insert('logs', ['action' => 'user_created']);
return $db->lastInsertId();
});
Ja jebkura izņēmuma tiek mestas atsaukuma ietvaros, transakcija automātiski atgriežas un izņēmums tiek atkārtoti mestas.
Padziļinātā Lietošana
Vaicājumu Žurnālveidošana & APM
Ja vēlaties izsekot vaicājuma veiktspēju, iespējiet APM izsekošanu reģistrēšanas laikā:
Flight::register('db', \flight\database\SimplePdo::class, [
'mysql:host=localhost;dbname=cool_db_name',
'user',
'pass',
[/* PDO opcijas */],
[
'trackApmQueries' => true,
'maxQueryMetrics' => 1000
]
]);
Pēc vaicājumu izpildes jūs varat žurnālveidot tos manuāli, bet APM tos žurnālveidos automātiski, ja iespējots:
Flight::db()->logQueries();
Tas izraisīs notikumu (flight.db.queries) ar savienojuma un vaicājuma metrikiem, ko jūs varat klausīties, izmantojot Flight notikumu sistēmu.
Pilns Piemērs
Flight::route('/users', function () {
// Iegūt visus lietotājus
$users = Flight::db()->fetchAll('SELECT * FROM users');
// Straumēt visus lietotājus
$statement = Flight::db()->runQuery('SELECT * FROM users');
while ($user = $statement->fetch()) {
echo $user['name'];
}
// Iegūt vienu lietotāju
$user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]);
// Iegūt vienu vērtību
$count = Flight::db()->fetchField('SELECT COUNT(*) FROM users');
// Iegūt vienu kolonnu
$ids = Flight::db()->fetchColumn('SELECT id FROM users');
// Iegūt atslēgu-vērtību pārus
$userNames = Flight::db()->fetchPairs('SELECT id, name FROM users');
// Īpaša IN() sintakse
$users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]);
// Ievietot jaunu lietotāju
$id = Flight::db()->insert('users', [
'name' => 'Bob',
'email' => 'bob@example.com'
]);
// Masveida ievietošana lietotājiem
Flight::db()->insert('users', [
['name' => 'Bob', 'email' => 'bob@example.com'],
['name' => 'Jane', 'email' => 'jane@example.com']
]);
// Atjaunināt lietotāju
$affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]);
// Dzēst lietotāju
$deleted = Flight::db()->delete('users', 'id = ?', [123]);
// Izmantot transakciju
$result = Flight::db()->transaction(function($db) {
$db->insert('users', ['name' => 'John', 'email' => 'john@example.com']);
$db->insert('audit_log', ['action' => 'user_created']);
return $db->lastInsertId();
});
});
Migrēšana no PdoWrapper
Ja jūs pašlaik izmantojat PdoWrapper, migrēšana uz SimplePdo ir vienkārša:
-
Atjauniniet savu reģistrāciju:
// Vecais Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); // Jaunais Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); -
Visas esošās
PdoWrappermetodes darbojasSimplePdo- Nav laušanas izmaiņu. Jūsu esošais kods turpinās darboties. -
Pēc izvēles izmantojiet jaunas palīgmēģenes - Sāciet izmantot
insert(),update(),delete()untransaction(), lai vienkāršotu savu kodu.
Skatīt Arī
- Collections - Uzziniet, kā izmantot Collection klasi vieglai datu piekļuvei.
- PdoWrapper - Mantotā PDO palīdze klase (novecojusi).
Traucējummeklēšana
- Ja saņemat kļūdu par datubāzes savienojumu, pārbaudiet savu DSN, lietotājvārdu, paroli un opcijas.
- Visas rindiņas tiek atgrieztas kā Collections—ja vajag vienkāršu masīvu, izmantojiet
$collection->getData(). - IN (?) vaicājumiem pārliecinieties, ka nodod masīvu.
- Ja rodas atmiņas problēmas ar vaicājumu žurnālveidošanu garos procesos, pielāgojiet
maxQueryMetricsopciju.
Izmaiņu Žurnāls
- v3.18.0 - Sākotnējā SimplePdo izlaišana ar palīgmēģenēm insert, update, delete un transakcijām.
Learn/collections
Kolekcijas
Pārskats
Collection klase Flight ietvaros ir ērts rīks datu kopu pārvaldīšanai. Tā ļauj piekļūt datiem un tos manipulēt, izmantojot gan masīvu, gan objektu pierakstu, padarot jūsu kodu tīrāku un elastīgāku.
Izpratne
Collection būtībā ir masīva iesaiņotājs, taču ar dažām papildu iespējām. Jūs to varat izmantot kā masīvu, veikt cilpu caur to, saskaitīt tā vienumus un pat piekļūt vienumiem tā, it kā tie būtu objekta īpašības. Tas ir īpaši noderīgi, ja vēlaties nodot strukturētus datus savā lietotnē vai padarīt savu kodu lasāmāku.
Kolekcijas implementē vairākas PHP saskarnes:
ArrayAccess(lai jūs varētu izmantot masīva sintaksi)Iterator(lai jūs varētu veikt cilpu arforeach)Countable(lai jūs varētu izmantotcount())JsonSerializable(lai jūs varētu viegli pārveidot uz JSON)
Pamata Lietošana
Kolekcijas Izveide
Jūs varat izveidot kolekciju, vienkārši nododot masīvu tās konstruktoram:
use flight\util\Collection;
$data = [
'name' => 'Flight',
'version' => 3,
'features' => ['routing', 'views', 'extending']
];
$collection = new Collection($data);
Piekļuve Vienumiem
Jūs varat piekļūt vienumiem, izmantojot vai nu masīva, vai objekta pierakstu:
// Masīva pieraksts
echo $collection['name']; // Izvade: FlightPHP
// Objekta pieraksts
echo $collection->version; // Izvade: 3
Vienumu Iestatīšana
Jūs varat iestatīt vienumus, izmantojot arī jebkuru no pierakstiem:
// Masīva pieraksts
$collection['author'] = 'Mike Cao';
// Objekta pieraksts
$collection->license = 'MIT';
Vienumu Pārbaude un Noņemšana
Pārbaudiet, vai vienums pastāv:
if (isset($collection['name'])) {
// Dariet kaut ko
}
if (isset($collection->version)) {
// Dariet kaut ko
}
Noņemiet vienumu:
unset($collection['author']);
unset($collection->license);
Cilpa Caur Kolekciju
Kolekcijas ir iterējamas, tāpēc jūs tās varat izmantot foreach cilpā:
foreach ($collection as $key => $value) {
echo "$key: $value\n";
}
Vienumu Skaitīšana
Jūs varat saskaitīt vienumu skaitu kolekcijā:
echo count($collection); // Izvade: 4
Visu Atslēgu vai Datu Iegūšana
Iegūt visas atslēgas:
$keys = $collection->keys(); // ['name', 'version', 'features', 'license']
Iegūt visus datus kā masīvu:
$data = $collection->getData();
Kolekcijas Notīrīšana
Noņemt visus vienumus:
$collection->clear();
JSON Serializācija
Kolekcijas var viegli pārveidot uz JSON:
echo json_encode($collection);
// Izvade: {"name":"FlightPHP","version":3,"features":["routing","views","extending"],"license":"MIT"}
Papildu Lietošana
Jūs varat pilnībā aizstāt iekšējo datu masīvu, ja nepieciešams:
$collection->setData(['foo' => 'bar']);
Kolekcijas ir īpaši noderīgas, ja vēlaties nodot strukturētus datus starp komponentiem vai nodrošināt vairāk objektorientētu saskarni masīvu datiem.
Skatīt Arī
- Pieprasījumi - Uzziniet, kā apstrādāt HTTP pieprasījumus un kā kolekcijas var izmantot pieprasījumu datu pārvaldīšanai.
- SimplePdo - Datu bāzes palīgs, kas atgriež vaicājumu rindas kā kolekcijas.
Problēmu Novēršana
- Ja mēģināt piekļūt atslēgai, kas neeksistē, jūs saņemsiet
null, nevis kļūdu. - Atcerieties, ka kolekcijas nav rekursīvas: ligzdotie masīvi netiek automātiski pārveidoti par kolekcijām.
- Ja nepieciešams atiestatīt kolekciju, izmantojiet
$collection->clear()vai$collection->setData([]).
Izmaiņu Žurnāls
- v3.0 - Uzlaboti tipu norādījumi un PHP 8+ atbalsts.
- v1.0 - Sākotnējais Collection klases laidiens.
Learn/flight_vs_fat_free
Flight pret Fat-Free
Kas ir Fat-Free?
Fat-Free (mīļi saukts par F3) ir jaudīgs, tomēr viegli lietojams PHP mikroietvars, kas izstrādāts, lai palīdzētu jums veidot dinamiskas un stabilas tīmekļa lietotnes - ātri!
Flight daudzējādā ziņā salīdzinās ar Fat-Free un, iespējams, ir vistuvākais radinieks funkciju un vienkāršības ziņā. Fat-Free ir daudz funkciju, kuru Flight nav, bet tam ir arī daudz funkciju, kuras Flight ir. Fat-Free sāk parādīt savu vecumu un vairs nav tik populārs kā tas bija kādreiz.
Atjauninājumi kļūst arvien retāki, un kopiena vairs nav tik aktīva kā agrāk. Kods ir pietiekami vienkāršs, bet dažkārt sintakses disciplīnas trūkums var apgrūtināt tā lasīšanu un saprašanu. Tas darbojas PHP 8.3, bet pats kods joprojām izskatās tā, it kā tas būtu no PHP 5.3 laikiem.
Plusi salīdzinājumā ar Flight
- Fat-Free GitHub ir nedaudz vairāk zvaigžņu nekā Flight.
- Fat-Free ir diezgan laba dokumentācija, bet dažās jomās tai trūkst skaidrības.
- Fat-Free ir daži reti resursi, piemēram, YouTube apmācības un tiešsaistes raksti, kurus var izmantot, lai apgūtu šo ietvaru.
- Fat-Free ir iebūvēti daži noderīgi spraudņi, kas dažkārt ir noderīgi.
- Fat-Free ir iebūvēts ORM ar nosaukumu Mapper, ko var izmantot, lai mijiedarbotos ar datu bāzi. Flight ir active-record.
- Fat-Free ir iebūvētas sesijas, kešatmiņa un lokalizācija. Flight prasa izmantot trešo pušu bibliotēkas, bet tas ir aprakstīts dokumentācijā.
- Fat-Free ir neliela kopienas veidotu spraudņu grupa, ko var izmantot ietvara paplašināšanai. Flight dažus no tiem apraksta dokumentācijas un piemēru lapās.
- Fat-Free, tāpat kā Flight, nav atkarību.
- Fat-Free, tāpat kā Flight, ir vērsts uz to, lai izstrādātājam dotu kontroli pār savu lietotni un vienkāršu izstrādātāja pieredzi.
- Fat-Free saglabā atpakaļejošu saderību, tāpat kā Flight (daļēji tāpēc, ka atjauninājumi kļūst retāki).
- Fat-Free, tāpat kā Flight, ir paredzēts izstrādātājiem, kuri pirmo reizi iepazīst ietvaru pasauli.
- Fat-Free ir iebūvēts veidņu dzinis, kas ir robustāks nekā Flight veidņu dzinis. Flight iesaka izmantot Latte, lai to sasniegtu.
- Fat-Free ir unikāla CLI tipa "route" komanda, kurā var veidot CLI lietotnes pašā Fat-Free un apstrādāt to līdzīgi kā
GETpieprasījumu. Flight to panāk ar runway.
Mīnusi salīdzinājumā ar Flight
- Fat-Free ir daži ieviešanas testi un pat sava testa klase, kas ir ļoti vienkārša. Tomēr tas nav 100% vienību testēts kā Flight.
- Lai meklētu dokumentācijas vietnē, jums ir jāizmanto meklētājprogramma, piemēram, Google.
- Flight dokumentācijas vietnē ir tumšais režīms. (mic drop)
- Fat-Free ir daži moduļi, kas ir nožēlojami nekopti.
- Flight ir SimplePdo datu bāzes piekļuvei, kas ir nedaudz vienkāršāks par Fat-Free iebūvēto
DB\SQLklasi (un ir ieteicams, nevis novecojušais PdoWrapper). - Flight ir tiesību spraudnis, ko var izmantot, lai aizsargātu savu lietotni. Fat-Free prasa izmantot trešās puses bibliotēku.
- Flight ir ORM ar nosaukumu active-record, kas vairāk izskatās pēc ORM nekā Fat-Free Mapper.
active-recordpapildu ieguvums ir tas, ka varat definēt attiecības starp ierakstiem automātiskai savienošanai, kamēr Fat-Free Mapper prasa izveidot SQL skatus. - Pārsteidzoši, bet Fat-Free nav saknes vārdtelpas. Flight ir pilnībā vārdtelpots, lai netiktu konfliktēts ar jūsu pašu kodu.
Cacheklase ir lielākais pārkāpējs šeit. - Fat-Free nav middleware. Tā vietā ir
beforerouteunafterrouteāķi, kurus var izmantot, lai kontrolētu pieprasījumus un atbildes kontrolieros. - Fat-Free nevar grupēt maršrutus.
- Fat-Free ir atkarību injekcijas konteinera apstrādātājs, bet dokumentācija par tā lietošanu ir ārkārtīgi skopa.
- Atkļūdošana var kļūt nedaudz sarežģīta, jo pamatā viss tiek glabāts tā sauktajā
HIVE.
Learn/extending
Paplašināšana
Pārskats
Flight ir izstrādāts kā paplašināms ietvars. Ietvars nāk ar kopu noklusējuma metožu un komponentu, bet tas ļauj jums kartēt savas metodes, reģistrēt savas klases vai pat pārrakstīt esošās klases un metodes.
Saprašana
Ir 2 veidi, kā jūs varat paplašināt Flight funkcionalitāti:
- Metožu kartēšana - Tas tiek izmantots, lai izveidotu vienkāršas pielāgotas metodes, kuras jūs varat izsaukt no jebkuras vietas savā lietojumprogrammā. Šīs parasti tiek izmantotas utilītas funkcijām, kuras jūs vēlaties varēt izsaukt no jebkuras vietas savā kodā.
- Klases reģistrēšana - Tas tiek izmantots, lai reģistrētu savas klases ar Flight. Šis parasti tiek izmantots klasēm, kurām ir atkarības vai nepieciešama konfigurācija.
Jūs varat arī pārrakstīt esošās ietvara metodes, lai mainītu to noklusējuma uzvedību, lai labāk atbilstu jūsu projekta vajadzībām.
Ja jūs meklējat DIC (Atkarību injekcijas konteineru), pārejiet uz Dependency Injection Container lapu.
Pamata lietošana
Ietvara metožu pārrakstīšana
Flight ļauj jums pārrakstīt tā noklusējuma funkcionalitāti, lai tā atbilstu jūsu vajadzībām, bez nepieciešamības modificēt jebkuru kodu. Jūs varat apskatīt visas metodes, kuras varat pārrakstīt zemāk.
Piemēram, kad Flight nevar saskaņot URL ar maršrutu, tas izsauc notFound
metodi, kas nosūta vispārīgu HTTP 404 atbildi. Jūs varat pārrakstīt šo uzvedību,
izmantojot map metodi:
Flight::map('notFound', function() {
// Rādīt pielāgotu 404 lapu
include 'errors/404.html';
});
Flight arī ļauj jums aizstāt ietvara kodola komponentus. Piemēram, jūs varat aizstāt noklusējuma Router klasi ar savu pielāgotu klasi:
// izveidot savu pielāgoto Router klasi
class MyRouter extends \flight\net\Router {
// pārrakstīt metodes šeit
// piemēram, saīsinājums GET pieprasījumiem, lai noņemtu
// pass route funkciju
public function get($pattern, $callback, $alias = '') {
return parent::get($pattern, $callback, false, $alias);
}
}
// Reģistrēt savu pielāgoto klasi
Flight::register('router', MyRouter::class);
// Kad Flight ielādē Router экземпlāru, tas ielādēs jūsu klasi
$myRouter = Flight::router();
$myRouter->get('/hello', function() {
echo "Hello World!";
}, 'hello_alias');
Tomēr ietvara metodes, piemēram map un register, nevar tikt pārrakstītas. Jūs saņemsiet
kļūdu, ja mēģināsiet to izdarīt (atkal skatiet zemāk metožu sarakstam).
Kartējamās ietvara metodes
Turpmāk ir pilnīga metožu kopa ietvaram. Tā sastāv no kodola metodēm, kuras ir regulāras statiskas metodes, un paplašināmām metodēm, kuras ir kartētas metodes, kuras var filtrēt vai pārrakstīt.
Kodola metodes
Šīs metodes ir kodola ietvaram un nevar tikt pārrakstītas.
Flight::map(string $name, callable $callback, bool $pass_route = false) // Izveido pielāgotu ietvara metodi.
Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // Reģistrē klasi ietvara metodē.
Flight::unregister(string $name) // Izslēdz klasi no ietvara metodes.
Flight::before(string $name, callable $callback) // Pievieno filtru pirms ietvara metodes.
Flight::after(string $name, callable $callback) // Pievieno filtru pēc ietvara metodes.
Flight::path(string $path) // Pievieno ceļu automātiskai klases ielādei.
Flight::get(string $key) // Iegūst mainīgo, ko iestatījis Flight::set().
Flight::set(string $key, mixed $value) // Iestata mainīgo Flight dzinējā.
Flight::has(string $key) // Pārbauda, vai mainīgais ir iestatīts.
Flight::clear(array|string $key = []) // Notīra mainīgo.
Flight::init() // Inicializē ietvaru ar tā noklusējuma iestatījumiem.
Flight::app() // Iegūst lietojumprogrammas objekta экземпlāru
Flight::request() // Iegūst pieprasījuma objekta экземпlāru
Flight::response() // Iegūst atbildes objekta экземпlāru
Flight::router() // Iegūst maršrutētāja objekta экземпlāru
Flight::view() // Iegūst skata objekta экземпlāru
Paplašināmas metodes
Flight::start() // Sāk ietvaru.
Flight::stop() // Aptur ietvaru un nosūta atbildi.
Flight::halt(int $code = 200, string $message = '') // Aptur ietvaru ar opcionālu statusa kodu un ziņu.
Flight::route(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Kartē URL paraugu ar atsaukumu.
Flight::post(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Kartē POST pieprasījuma URL paraugu ar atsaukumu.
Flight::put(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Kartē PUT pieprasījuma URL paraugu ar atsaukumu.
Flight::patch(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Kartē PATCH pieprasījuma URL paraugu ar atsaukumu.
Flight::delete(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Kartē DELETE pieprasījuma URL paraugu ar atsaukumu.
Flight::group(string $pattern, callable $callback) // Izveido grupēšanu URL, paraugam jābūt virknei.
Flight::getUrl(string $name, array $params = []) // Ģenerē URL, balstoties uz maršruta aliasu.
Flight::redirect(string $url, int $code) // Pāradresē uz citu URL.
Flight::download(string $filePath) // Lejupielādē failu.
Flight::render(string $file, array $data, ?string $key = null) // Renderē veidnes failu.
Flight::error(Throwable $error) // Nosūta HTTP 500 atbildi.
Flight::notFound() // Nosūta HTTP 404 atbildi.
Flight::etag(string $id, string $type = 'string') // Veic ETag HTTP kešošanu.
Flight::lastModified(int $time) // Veic pēdējās modificēšanas HTTP kešošanu.
Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Nosūta JSON atbildi.
Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Nosūta JSONP atbildi.
Flight::jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Nosūta JSON atbildi un aptur ietvaru.
Flight::onEvent(string $event, callable $callback) // Reģistrē notikuma klausītāju.
Flight::triggerEvent(string $event, ...$args) // Izsauc notikumu.
Jebkuras pielāgotas metodes, kas pievienotas ar map un register, var arī tikt filtrētas. Piemēriem, kā filtrēt šīs metodes, skatiet Filtering Methods rokasgrāmatu.
Paplašināmas ietvara klases
Ir vairākas klases, kurām jūs varat pārrakstīt funkcionalitāti, paplašinot tās un reģistrējot savu klasi. Šīs klases ir:
Flight::app() // Lietojumprogrammas klase - paplašiniet flight\Engine klasi
Flight::request() // Pieprasījuma klase - paplašiniet flight\net\Request klasi
Flight::response() // Atbildes klase - paplašiniet flight\net\Response klasi
Flight::router() // Maršrutētāja klase - paplašiniet flight\net\Router klasi
Flight::view() // Skata klase - paplašiniet flight\template\View klasi
Flight::eventDispatcher() // Notikuma dispečera klase - paplašiniet flight\core\Dispatcher klasi
Pielāgoto metožu kartēšana
Lai kartētu savu vienkāršo pielāgoto metodi, jūs izmantojat map funkciju:
// Kartēt savu metodi
Flight::map('hello', function (string $name) {
echo "hello $name!";
});
// Izsaukt savu pielāgoto metodi
Flight::hello('Bob');
Lai gan ir iespējams izveidot vienkāršas pielāgotas metodes, ieteicams tikai izveidot standarta funkcijas PHP. Tam ir autocomplēte IDE un tas ir vieglāk lasāms. Iepriekš minētā koda ekvivalents būtu:
function hello(string $name) {
echo "hello $name!";
}
hello('Bob');
Tas tiek izmantots vairāk, kad jums jānodod mainīgie jūsu metodē, lai iegūtu gaidīto
vērtību. Izmantojot register() metodi kā zemāk, tas ir vairāk par konfigurācijas nodošanu
un tad izsaukt savu iepriekš konfigurēto klasi.
Pielāto klases reģistrēšana
Lai reģistrētu savu klasi un konfigurētu to, jūs izmantojat register funkciju. Iepriekšējs ieguvums, ko tas sniedz pār map(), ir tas, ka jūs varat atkārtoti izmantot to pašu klasi, kad izsaucat šo funkciju (tas būtu noderīgi ar Flight::db(), lai dalītos tajā pašā экземпlārā).
// Reģistrēt savu klasi
Flight::register('user', User::class);
// Iegūt klases экземпlāru
$user = Flight::user();
Reģistrēšanas metode arī ļauj jums nodot parametrus jūsu klases konstruktoram. Tātad, kad jūs ielādējat savu pielāgoto klasi, tā nāks jau inicializēta. Jūs varat definēt konstruktora parametrus, nododot papildu masīvu. Šeit ir piemērs datubāzes savienojuma ielādei:
// Reģistrēt klasi ar konstruktora parametriem
Flight::register('db', PDO::class, ['mysql:host=localhost;dbname=test', 'user', 'pass']);
// Iegūt klases экземпlāru
// Tas izveidos objektu ar definētajiem parametriem
//
// new PDO('mysql:host=localhost;dbname=test','user','pass');
//
$db = Flight::db();
// un ja jums tas būtu vajadzīgs vēlāk savā kodā, jūs tikai izsaucat to pašu metodi vēlreiz
class SomeController {
public function __construct() {
$this->db = Flight::db();
}
}
Ja jūs nododit papildu atsauces parametru, tas tiks izpildīts uzreiz pēc klases konstrukcijas. Tas ļauj jums veikt jebkuru iestatīšanas procedūru jūsu jaunajam objektam. Atsauces funkcija ņem vienu parametru, jauna objekta экземпlāru.
// Atsauce tiks nodota konstrukcijas objekts
Flight::register(
'db',
PDO::class,
['mysql:host=localhost;dbname=test', 'user', 'pass'],
function (PDO $db) {
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
);
Pēc noklusējuma katru reizi, kad jūs ielādējat savu klasi, jūs iegūsit kopīgu экземпlāru.
Lai iegūtu jaunu klases экземпlāru, vienkārši nododit false kā parametru:
// Kopīgs klases экземпlārs
$shared = Flight::db();
// Jauns klases экземпlārs
$new = Flight::db(false);
Piezīme: Ņemiet vērā, ka kartētās metodes ir priekšroka pār reģistrētajām klasēm. Ja jūs deklarējat abas, izmantojot to pašu nosaukumu, tikai kartētā metode tiks izsaukta.
Piemēri
Šeit ir daži piemēri, kā jūs varat paplašināt Flight ar funkcionalitāti, kas nav iebūvēta kodolā.
Žurnālveide
Flight nav iebūvēta žurnālveides sistēma, tomēr ir patiešām viegli izmantot žurnālveides bibliotēku ar Flight. Šeit ir piemērs, izmantojot Monolog bibliotēku:
// services.php
// Reģistrēt žurnālu ar Flight
Flight::register('log', Monolog\Logger::class, [ 'name' ], function(Monolog\Logger $log) {
$log->pushHandler(new Monolog\Handler\StreamHandler('path/to/your.log', Monolog\Logger::WARNING));
});
Tagad, kad tas ir reģistrēts, jūs varat to izmantot savā lietojumprogrammā:
// Jūsu kontrolierī vai maršrutā
Flight::log()->warning('This is a warning message');
Tas ierakstīs ziņu norādītajā žurnāla failā. Ko tad, ja jūs vēlaties ierakstīt kaut ko, kad rodas
kļūda? Jūs varat izmantot error metodi:
// Jūsu kontrolierī vai maršrutā
Flight::map('error', function(Throwable $ex) {
Flight::log()->error($ex->getMessage());
// Rādīt savu pielāgoto kļūdas lapu
include 'errors/500.html';
});
Jūs arī varētu izveidot pamata APM (Lietojumprogrammas veiktspējas uzraudzību) sistēmu,
izmantojot before un after metodes:
// Jūsu services.php failā
Flight::before('start', function() {
Flight::set('start_time', microtime(true));
});
Flight::after('start', function() {
$end = microtime(true);
$start = Flight::get('start_time');
Flight::log()->info('Request '.Flight::request()->url.' took ' . round($end - $start, 4) . ' seconds');
// Jūs varētu arī pievienot savu pieprasījumu vai atbildes galvenes
// lai ierakstītu tās (esiet uzmanīgs, jo tas būtu daudz datu, ja jums ir daudz pieprasījumu)
Flight::log()->info('Request Headers: ' . json_encode(Flight::request()->headers));
Flight::log()->info('Response Headers: ' . json_encode(Flight::response()->headers));
});
Kešošana
Flight nav iebūvēta kešošanas sistēma, tomēr ir patiešām viegli izmantot kešošanas bibliotēku ar Flight. Šeit ir piemērs, izmantojot PHP File Cache bibliotēku:
// services.php
// Reģistrēt kešu ar Flight
Flight::register('cache', \flight\Cache::class, [ __DIR__ . '/../cache/' ], function(\flight\Cache $cache) {
$cache->setDevMode(ENVIRONMENT === 'development');
});
Tagad, kad tas ir reģistrēts, jūs varat to izmantot savā lietojumprogrammā:
// Jūsu kontrolierī vai maršrutā
$data = Flight::cache()->get('my_cache_key');
if (empty($data)) {
// Veikt kādu apstrādi, lai iegūtu datus
$data = [ 'some' => 'data' ];
Flight::cache()->set('my_cache_key', $data, 3600); // kešot uz 1 stundu
}
Viegla DIC objekta instantiācija
Ja jūs izmantojat DIC (Atkarību injekcijas konteineru) savā lietojumprogrammā, jūs varat izmantot Flight, lai palīdzētu jums instantiēt savus objektus. Šeit ir piemērs, izmantojot Dice bibliotēku:
// services.php
// izveidot jaunu konteineru
$container = new \Dice\Dice;
// neaizmirstiet to atkārtoti piešķirt sev pašam kā zemāk!
$container = $container->addRule('PDO', [
// shared nozīmē, ka tas pats objekts tiks atgriezts katru reizi
'shared' => true,
'constructParams' => ['mysql:host=localhost;dbname=test', 'user', 'pass' ]
]);
// tagad mēs varam izveidot kartējamu metodi, lai izveidotu jebkuru objektu.
Flight::map('make', function($class, $params = []) use ($container) {
return $container->create($class, $params);
});
// Tas reģistrē konteinera apstrādātāju, lai Flight zinātu to izmantot kontrolieriem/vidējai slānim
Flight::registerContainerHandler(function($class, $params) {
Flight::make($class, $params);
});
// pieņemsim, ka mums ir šāda parauga klase, kas ņem PDO objektu konstruktorā
class EmailCron {
protected PDO $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function send() {
// kods, kas nosūta e-pastu
}
}
// Un beidzot jūs varat izveidot objektus, izmantojot atkarību injekciju
$emailCron = Flight::make(EmailCron::class);
$emailCron->send();
Eleganti, vai ne?
Skatīt arī
- Dependency Injection Container - Kā izmantot DIC ar Flight.
- File Cache - Piemērs kešošanas bibliotēkas izmantošanai ar Flight.
Traucējummeklēšana
- Atcerieties, ka kartētām metodēm ir priekšroka pār reģistrētajām klasēm. Ja jūs deklarējat abas, izmantojot to pašu nosaukumu, tikai kartētā metode tiks izsaukta.
Izmaiņu žurnāls
- v2.0 - Sākotnējā izlaišana.
Learn/json
JSON Apvalks
Pārskats
Json klase Flight nodrošina vienkāršu, konsekventu veidu, kā kodēt un dekodēt JSON datus jūsu lietojumprogrammā. Tā apvalko PHP iebūvēto JSON funkciju ar labāku kļūdu apstrādi un dažām noderīgām noklusējuma vērtībām, padarot to vieglāku un drošāku strādāt ar JSON.
Saprašana
Darbs ar JSON ir ārkārtīgi izplatīts mūsdienu PHP lietojumprogrammās, īpaši, kad veidojat API vai apstrādājat AJAX pieprasījumus. Json klase centralizē visu jūsu JSON kodēšanu un dekodēšanu, tāpēc jums nav jāuztraucas par dīvainiem malu gadījumiem vai nesaprotamām kļūdām no PHP iebūvētajām funkcijām.
Galvenās funkcijas:
- Konsekventa kļūdu apstrāde (izmet izņēmumus kļūdas gadījumā)
- Noklusējuma opcijas kodēšanai/dekodēšanai (piemēram, neizbēgtas slīpsvītras)
- Palīgfunkcijas skaistai izdrukai un validācijai
Pamata Izmantošana
Datu Kodēšana uz JSON
Lai pārveidotu PHP datus uz JSON virkni, izmantojiet Json::encode():
use flight\util\Json;
$data = [
'framework' => 'Flight',
'version' => 3,
'features' => ['routing', 'views', 'extending']
];
$json = Json::encode($data);
echo $json;
// Output: {"framework":"Flight","version":3,"features":["routing","views","extending"]}
Ja kodēšana neizdodas, jūs saņemsiet izņēmumu ar noderīgu kļūdas ziņu.
Skaista Izdruka
Vai vēlaties, lai jūsu JSON būtu lasāms cilvēkiem? Izmantojiet prettyPrint():
echo Json::prettyPrint($data);
/*
{
"framework": "Flight",
"version": 3,
"features": [
"routing",
"views",
"extending"
]
}
*/
JSON Virkņu Dekodēšana
Lai pārveidotu JSON virkni atpakaļ uz PHP datiem, izmantojiet Json::decode():
$json = '{"framework":"Flight","version":3}';
$data = Json::decode($json);
echo $data->framework; // Output: Flight
Ja vēlaties asociatīvu masīvu nevis objektu, nododiet true kā otro argumentu:
$data = Json::decode($json, true);
echo $data['framework']; // Output: Flight
Ja dekodēšana neizdodas, jūs saņemsiet izņēmumu ar skaidru kļūdas ziņu.
JSON Validācija
Pārbaudiet, vai virkne ir derīgs JSON:
if (Json::isValid($json)) {
// Tas ir derīgs!
} else {
// Nav derīgs JSON
}
Pēdējās Kļūdas Iegūšana
Ja vēlaties pārbaudīt pēdējo JSON kļūdas ziņu (no iebūvētām PHP funkcijām):
$error = Json::getLastError();
if ($error !== '') {
echo "Last JSON error: $error";
}
Uzlabota Izmantošana
Jūs varat pielāgot kodēšanas un dekodēšanas opcijas, ja vajag vairāk kontroles (skatiet PHP json_encode opcijas):
// Kodēšana ar HEX_TAG opciju
$json = Json::encode($data, JSON_HEX_TAG);
// Dekodēšana ar pielāgotu dziļumu
$data = Json::decode($json, false, 1024);
Skatīt Arī
- Collections - Darbam ar strukturētiem datiem, kas viegli pārveidojami uz JSON.
- Configuration - Kā konfigurēt jūsu Flight lietojumprogrammu.
- Extending - Kā pievienot savas palīgfunkcijas vai pārdefinēt kodola klases.
Traucējummeklēšana
- Ja kodēšana vai dekodēšana neizdodas, tiek izmests izņēmums — i包ojiet savus izsaukumus try/catch, ja vēlaties apstrādāt kļūdas eleganti.
- Ja saņemat negaidītus rezultātus, pārbaudiet savus datus uz apļa atsaucēm vai ne-UTF8 rakstzīmēm.
- Izmantojiet
Json::isValid(), lai pārbaudītu, vai virkne ir derīgs JSON pirms dekodēšanas.
Izmaiņu Žurnāls
- v3.16.0 - Pievienota JSON apvalka palīgfunkciju klase.
Learn/flight_vs_slim
Flight pret Slim
Kas ir Slim?
Slim ir PHP mikro ietvars, kas palīdz ātri izveidot vienkāršas, bet jaudīgas tīmekļa lietojumprogrammas un API.
Daudz iedvesmas dažiem Flight v3 funkcijām faktiski nāca no Slim. Maršrutu grupēšana un starpprogrammatūras izpilde noteiktā secībā ir divas funkcijas, kuras iedvesmoja Slim. Slim v3 tika izlaists ar mērķi uz vienkāršību, bet par v4 ir pretrunīgi vērtējumi.
Priekšrocības salīdzinājumā ar Flight
- Slim ir lielāka izstrādātāju kopiena, kas savukārt veido ērtus moduļus, lai palīdzētu jums no jauna neizgudrot riteni.
- Slim ievēro daudzas saskarnes un standartus, kas ir izplatīti PHP kopienā, tādējādi palielinot savietojamību.
- Slim ir pienācīga dokumentācija un apmācības, kuras var izmantot, lai apgūtu ietvaru (lai gan nekas salīdzinājumā ar Laravel vai Symfony).
- Slim ir dažādi resursi, piemēram, YouTube apmācības un tiešsaistes raksti, kurus var izmantot ietvara apguvei.
- Slim ļauj izmantot jebkurus komponentus, ko vēlaties, lai apstrādātu galvenās maršrutēšanas funkcijas, jo tas atbilst PSR-7.
Trūkumi salīdzinājumā ar Flight
- Pārsteidzoši, ka Slim nav tik ātrs, kā jūs domātu, ka tam vajadzētu būt mikro-ietvaram. Skatiet TechEmpower etalonus, lai iegūtu vairāk informācijas.
- Flight ir paredzēts izstrādātājam, kurš vēlas izveidot vieglu, ātru un viegli lietojamu tīmekļa lietojumprogrammu.
- Flight nav atkarību, turpretim Slim ir dažas atkarības, kas jums ir jāinstalē.
- Flight ir vērsts uz vienkāršību un lietošanas ērtumu.
- Viena no Flight pamatfunkcijām ir tā, ka tā dara visu iespējamo, lai saglabātu atpakaļsavietojamību. Slim v3 uz v4 bija pārtraucošas izmaiņas.
- Flight ir paredzēts izstrādātājiem, kuri pirmo reizi iepazīst ietvaru pasauli.
- Flight var veidot arī uzņēmuma līmeņa lietojumprogrammas, bet tam nav tik daudz piemēru un apmācību kā Slim. Tas arī prasīs lielāku disciplīnu no izstrādātāja puses, lai saglabātu lietas organizētas un labi strukturētas.
- Flight dod izstrādātājam lielāku kontroli pār lietojumprogrammu, turpretim Slim var ieviest nedaudz maģijas aizkulisēs.
- Flight ir SimplePdo datubāzes piekļuvei (ieteicams, nevis novecojušais PdoWrapper). Slim prasa izmantot trešās puses bibliotēku.
- Flight ir atļauju spraudnis, ko var izmantot lietojumprogrammas aizsardzībai. Slim prasa izmantot trešās puses bibliotēku.
- Flight ir ORM ar nosaukumu active-record, ko var izmantot mijiedarbībai ar datubāzi. Slim prasa izmantot trešās puses bibliotēku.
- Flight ir CLI lietojumprogramma ar nosaukumu runway, ko var izmantot lietojumprogrammas palaišanai no komandrindas. Slim tādas nav.
Learn/autoloading
Automātiskā ielāde
Pārskats
Automatiskā ielāde ir PHP koncepcija, kurā norādāt direktoriju vai direktorijas, no kurām ielādēt klases. Tas ir daudz izdevīgāk nekā izmantot require vai include, lai ielādētu klases. Tas ir arī priekšnoteikums Composer pakotņu izmantošanai.
Pareiza automātiskās ielādes iestatīšana ir svarīga arī ar AI atbalstītu izstrādi: aģenti novieto failus tur, kur norāda nosaukumvieta. Ja mapes reģistrs un nosaukumvietas reģistrs nesakrīt, Linux sistēmā parādās kļūdas par klases neatrašanu, pat ja lietas "strādāja" uz Mac diska, kur reģistrs netiek nošķirts.
Izpratne
Pēc noklusējuma jebkura Flight klase tiek ielādēta automātiski, pateicoties Composer. Jūsu lietojumprogrammas klasēm ir divas izplatītas pieejas:
- Composer PSR-4 (ko izmanto oficiālais skeletons): kartējiet nosaukumvietas prefiksu uz direktoriju
composer.jsonfailā, pēc tam izpildietcomposer dump-autoload. Flight::path(): norādiet Flight ielādētājam direktorijas (noderīgi vienkāršām lietotnēm vai ja neizmantojat Composer lietojumprogrammas kodam).
Automatiskās ielādes izmantošana ievērojami vienkāršo jūsu kodu. Tā vietā, lai katra faila augšpusē būtu vesela siena ar include / require, klases tiek ielādētas, kad tās pirmo reizi izmantojat.
Reģistrjutība (izlasiet šo divreiz)
Nosaukumvietām ir jāatbilst direktoriju struktūrai un šo direktoriju burtu reģistram.
| Strādā | Nedarbojas Linux |
|---|---|
App\Controller\HomeController → app/Controller/HomeController.php |
App\Controller\… ar mapi app/controllers/ |
app\controllers\MyController → app/controllers/MyController.php |
Ja sajauc App\ ar mazajiem burtiem controllers |
PHP nosaukumvietas dažos kontekstos nav reģistrjutīgas, bet Composer un failu sistēma ir. Oficiālais skeletons standartizē šādi:
- Composer:
"App\\": "app/" - Mapes:
Controller,Middleware,Model,Utils(PascalCase), neviscontrollers/middlewares
Vecāki dokumenti un kopienas piemēri dažkārt izmantoja mazos burtus app\controllers. Tas joprojām darbojas, ja jūsu mapes ir mazajos burtos—bet jauni skeletona projekti izmanto App\ + PascalCase mapes. Izvēlieties vienu konvenciju projektam un pieturieties pie tās, lai cilvēki un AI rīki neizgudrotu otru izkārtojumu.
Skeletons (ieteicams jauniem projektiem)
Pēc composer create-project flightphp/skeleton komandas, lietojumprogrammas kods tiek ielādēts, izmantojot Composer—Flight::path() nav nepieciešams App\ klasēm:
{
"autoload": {
"psr-4": {
"App\\": "app/"
}
}
}
// app/Controller/HomeController.php
namespace App\Controller;
use flight\Engine;
class HomeController
{
protected Engine $app;
public function __construct(Engine $app)
{
$this->app = $app;
}
public function index(): void
{
$this->app->render('welcome', ['message' => 'Hello!']);
}
}
// app/config/routes.php — Dice atrisina App\Controller\… caur konteineru
$router->get('/', [HomeController::class, 'index']);
Skatiet Instalācija, lai redzētu pilnu koku, un AI & izstrādātāju pieredze, lai uzzinātu, kā AGENTS.md dokumentē šo izkārtojumu kodēšanas asistentiem.
Pamata lietošana (Flight::path())
Pieņemsim, ka mums ir šāds direktoriju koks:
# Piemēra ceļš
/home/user/project/my-flight-project/
├── app
│ ├── cache
│ ├── config
│ ├── controllers - satur šī projekta kontrollerus
│ ├── translations
│ ├── UTILS - satur klases tikai šai lietojumprogrammai (tas ir ar lielajiem burtiem speciāli, lai vēlāk izmantotu kā piemēru)
│ └── views
└── public
└── css
└── js
└── index.php
Jūs, iespējams, pamanījāt, ka tas ir līdzīgs tipiskam lietojumprogrammas kokam (pati dokumentācijas vietne izmanto strukturētu izkārtojumu). Mazie burti controllers šeit ir derīga izvēle—tas vienkārši nav skeletona pašreizējais noklusējums.
Jūs varat norādīt katru direktoriju, no kura ielādēt, šādi:
/**
* public/index.php
*/
// Pievienojiet ceļu automātiskajai ielādei
Flight::path(__DIR__.'/../app/controllers/');
Flight::path(__DIR__.'/../app/utils/');
/**
* app/controllers/MyController.php
*/
// nosaukumvieta nav nepieciešama
// Visām automātiski ielādētajām klasēm ieteicams izmantot Pascal Case (katrs vārds ar lielo sākumburtu, bez atstarpēm)
class MyController {
public function index() {
// dariet kaut ko
}
}
Nosaukumvietas ar Flight::path()
Ja jums ir nosaukumvietas, to faktiski ir ļoti viegli ieviest. Jums vajadzētu izmantot Flight::path() metodi, lai norādītu lietojumprogrammas saknes direktoriju (nevis dokumenta sakni vai public/ mapi).
/**
* public/index.php
*/
// Pievienojiet ceļu automātiskajai ielādei
Flight::path(__DIR__.'/../');
Tagad šādi varētu izskatīties jūsu kontrolieris. Apskatiet zemāk esošo piemēru, bet pievērsiet uzmanību komentāriem — tajos ir svarīga informācija.
/**
* app/controllers/MyController.php
*/
// nosaukumvietas ir obligātas
// nosaukumvietas ir tādas pašas kā direktoriju struktūra
// nosaukumvietām ir jāievēro tāds pats burtu reģistrs kā direktoriju struktūrai
// nosaukumvietās un direktorijos nevar būt apakšsvītras (ja vien nav iestatīts Loader::setV2ClassLoading(false))
namespace app\controllers;
// Visām automātiski ielādētajām klasēm ieteicams izmantot Pascal Case (katrs vārds ar lielo sākumburtu, bez atstarpēm)
// Sākot ar 3.7.2, varat izmantot Pascal_Snake_Case savu klašu nosaukumos, izpildot Loader::setV2ClassLoading(false);
class MyController {
public function index() {
// dariet kaut ko
}
}
Un, ja vēlaties automātiski ielādēt klasi savā utils direktorijā, jūs darītu pamatā to pašu:
/**
* app/UTILS/ArrayHelperUtil.php
*/
// nosaukumvietai ir jāatbilst direktoriju struktūrai un reģistram (ņemiet vērā, ka UTILS direktorijs ir ar lielajiem burtiem
// tāpat kā iepriekš redzamajā failu kokā)
namespace app\UTILS;
class ArrayHelperUtil {
public function changeArrayCase(array $array) {
// dariet kaut ko
}
}
Skeletona stila nosaukumvieta (tie paši noteikumi, cits reģistrs)
/**
* app/Controller/MyController.php
*/
namespace App\Controller;
class MyController {
// ...
}
Noteikumi nav mainījušies—tikai skeletona izvēlētais mapes/nosaukumvietas reģistrs. Neatkarīgi no tā, kādu reģistru izmantojat savās mapēs, jūsu namespace rindai ir jāatbilst.
Apakšsvītras klašu nosaukumos
Sākot ar 3.7.2, varat izmantot Pascal_Snake_Case savu klašu nosaukumos, izpildot Loader::setV2ClassLoading(false);.
Tas ļaus jums izmantot apakšsvītras klašu nosaukumos.
Tas nav ieteicams, bet ir pieejams tiem, kam tas ir nepieciešams.
use flight\core\Loader;
/**
* public/index.php
*/
// Pievienojiet ceļu automātiskajai ielādei
Flight::path(__DIR__.'/../app/controllers/');
Flight::path(__DIR__.'/../app/utils/');
Loader::setV2ClassLoading(false);
/**
* app/controllers/My_Controller.php
*/
// nosaukumvieta nav nepieciešama
class My_Controller {
public function index() {
// dariet kaut ko
}
}
Skatīt arī
- Instalācija - Skeletona koks un
App\noklusējumi jauniem projektiem. - Maršrutēšana - Kā kartēt maršrutus uz kontrolleriem un renderēt skatus.
- Atkarību ievadīšana - Kā kontrolleri saņem
Engineun pakalpojumus. - AI & izstrādātāju pieredze - Uzturiet aģentus saskaņotus ar jūsu izkārtojumu, izmantojot
AGENTS.md. - Kāpēc ietvars? - Izpratne par ieguvumiem, ko sniedz tāda ietvara kā Flight izmantošana.
Problēmu novēršana
- Ja nevarat saprast, kāpēc jūsu nosaukumvietu klases netiek atrastas, atcerieties: ar
Flight::path()norādiet uz projekta sakni (vai pareizo bāzi savai nosaukumvietai), nevis tikai uz ligzdotu mapi, kuru aizmirsāt atspoguļot nosaukumvietā. - Izmantojot Composer PSR-4, pēc
composer.jsonkartējumu maiņas izpildietcomposer dump-autoload. - Linux CI vai ražošanas vidē nepareizs mapes reģistrs ir ļoti izplatīta "manā mašīnā tas strādā" kļūme.
Klase nav atrasta (automātiskā ielāde nedarbojas)
Var būt vairāki iemesli, kāpēc tas nenotiek. Zemāk ir daži piemēri.
Nepareizs faila nosaukums
Visizplatītākais ir tas, ka klases nosaukums neatbilst faila nosaukumam.
Ja jums ir klase ar nosaukumu MyClass, failam ir jābūt nosauktam MyClass.php. Ja jums ir klase ar nosaukumu MyClass un fails ir nosaukts myclass.php, automātiskā ielāde nevarēs to atrast.
Nepareiza nosaukumvieta vai mapes reģistrs
Ja izmantojat nosaukumvietas, tad nosaukumvietai ir jāatbilst direktoriju struktūrai ieskaitot reģistru.
// ...kods...
// ja jūsu MyController atrodas app/Controller (skeletons) un ir nosaukumvietā App\Controller
// tas nedarbosies:
Flight::route('/hello', 'MyController->hello');
// Skeletona stils:
use App\Controller\MyController;
Flight::route('/hello', [ MyController::class, 'hello' ]);
// Vecāks izkārtojums ar mazajiem burtiem (tikai tad, ja jūsu mapes patiešām ir app/controllers):
use app\controllers\MyController;
Flight::route('/hello', [ MyController::class, 'hello' ]);
// vai pilnībā kvalificēts:
Flight::route('/hello', [ 'App\Controller\MyController', 'hello' ]);
path() nav definēts (ne-Composer lietojumprogrammas kods)
Ja paļaujaties uz Flight::path() nevis Composer lietojumprogrammas klasēm, definējiet ceļu pirms maršrutiem, kas atsaucas uz šīm klasēm (parasti agri bootstrap / public/index.php):
// Pievienojiet ceļu automātiskajai ielādei (projekta sakne nosaukumvietu lietotnēm)
Flight::path(__DIR__.'/../');
Oficiālais skeletons galvenokārt izmanto Composer PSR-4 App\ klasei, tāpēc parasti jums nebūs nepieciešams Flight::path() kontrolleriem un modeļiem.
Izmaiņu žurnāls
- Dokumentācija – dokumentēts skeletona
App\+ PascalCase mapju izkārtojums un reģistrjutības nepilnības cilvēkiem un AI rīkiem. - v3.7.2 - Varat izmantot Pascal_Snake_Case savu klašu nosaukumos, izpildot
Loader::setV2ClassLoading(false); - v2.0 - Pievienota automātiskās ielādes funkcionalitāte.
Learn/uploaded_file
Augšupielādētā faila apstrādātājs
Pārskats
UploadedFile klase Flight padara vieglu un drošu failu augšupielādes apstrādi jūsu lietojumprogrammā. Tā aptver PHP failu augšupielādes procesa detaļas, piedāvājot vienkāršu, objektorientētu veidu, kā piekļūt faila informācijai un pārvietot augšupielādētos failus.
Saprašana
Kad lietotājs augšupielādē failu caur formu, PHP saglabā informāciju par failu $_FILES superglobālajā mainīgajā. Flight vidē jūs reti mijiedarbojaties ar $_FILES tieši. Tā vietā Flight Request objekts (pieejams caur Flight::request()) nodrošina getUploadedFiles() metodi, kas atgriež UploadedFile objektu masīvu, padarot failu apstrādi daudz ērtāku un izturīgāku.
UploadedFile klase nodrošina metodes, lai:
- Iegūtu oriģinālo faila nosaukumu, MIME tipu, izmēru un pagaidu atrašanās vietu
- Pārbaudītu augšupielādes kļūdas
- Pārvietotu augšupielādēto failu uz pastāvīgu atrašanās vietu
Šī klase palīdz izvairīties no izplatītām kļūdām ar failu augšupielādi, piemēram, kļūdu apstrādes vai drošas failu pārvietošanas.
Pamata izmantošana
Piekļuve augšupielādētajiem failiem no pieprasījuma
Ieteicamais veids, kā piekļūt augšupielādētajiem failiem, ir caur pieprasījuma objektu:
Flight::route('POST /upload', function() {
// Par formu lauku ar nosaukumu <input type="file" name="myFile">
$uploadedFiles = Flight::request()->getUploadedFiles();
$file = $uploadedFiles['myFile'];
// Tagad jūs varat izmantot UploadedFile metodes
if ($file->getError() === UPLOAD_ERR_OK) {
$file->moveTo('/path/to/uploads/' . $file->getClientFilename());
echo "Fails augšupielādēts veiksmīgi!";
} else {
echo "Augšupielāde neizdevās: " . $file->getError();
}
});
Daudzu failu augšupielādes apstrāde
Ja jūsu forma izmanto name="myFiles[]" vairāku augšupielāžu gadījumā, jūs saņemsiet UploadedFile objektu masīvu:
Flight::route('POST /upload', function() {
// Par formu lauku ar nosaukumu <input type="file" name="myFiles[]">
$uploadedFiles = Flight::request()->getUploadedFiles();
foreach ($uploadedFiles['myFiles'] as $file) {
if ($file->getError() === UPLOAD_ERR_OK) {
$file->moveTo('/path/to/uploads/' . $file->getClientFilename());
echo "Augšupielādēts: " . $file->getClientFilename() . "<br>";
} else {
echo "Neizdevās augšupielādēt: " . $file->getClientFilename() . "<br>";
}
}
});
UploadedFile instances manuāla izveide
Parasti jūs neizveidosiet UploadedFile manuāli, bet to var izdarīt, ja nepieciešams:
use flight\net\UploadedFile;
$file = new UploadedFile(
$_FILES['myfile']['name'],
$_FILES['myfile']['type'],
$_FILES['myfile']['size'],
$_FILES['myfile']['tmp_name'],
$_FILES['myfile']['error']
);
Piekļuve faila informācijai
Jūs viegli varat iegūt detaļas par augšupielādēto failu:
echo $file->getClientFilename(); // Oriģinālais faila nosaukums no lietotāja datora
echo $file->getClientMediaType(); // MIME tips (piem., image/png)
echo $file->getSize(); // Faila izmērs baitos
echo $file->getTempName(); // Pagaidu faila ceļš uz servera
echo $file->getError(); // Augšupielādes kļūdas kods (0 nozīmē bez kļūdas)
Augšupielādētā faila pārvietošana
Pēc faila validēšanas pārvietojiet to uz pastāvīgu atrašanās vietu:
try {
$file->moveTo('/path/to/uploads/' . $file->getClientFilename());
echo "Fails augšupielādēts veiksmīgi!";
} catch (Exception $e) {
echo "Augšupielāde neizdevās: " . $e->getMessage();
}
moveTo() metode izmet izņēmumu, ja kaut kas noiet greizi (piemēram, augšupielādes kļūda vai atļauju problēma).
Augšupielādes kļūdu apstrāde
Ja augšupielādes laikā radās problēma, jūs varat iegūt lasāmu kļūdas ziņojumu cilvēkam:
if ($file->getError() !== UPLOAD_ERR_OK) {
// Jūs varat izmantot kļūdas kodu vai noķert izņēmumu no moveTo()
echo "Radās kļūda, augšupielādējot failu.";
}
Skatīt arī
- Requests - Uzziniet, kā piekļūt augšupielādētajiem failiem no HTTP pieprasījumiem un redzēt vairāk failu augšupielādes piemēru.
- Configuration - Kā konfigurēt augšupielādes ierobežojumus un direktorijas PHP.
- Extending - Kā pielāgot vai paplašināt Flight kodola klases.
Traucējummeklēšana
- Vienmēr pārbaudiet
$file->getError()pirms faila pārvietošanas. - Pārliecinieties, ka jūsu augšupielādes direktorija ir rakstāma tīmekļa serverim.
- Ja
moveTo()neizdodas, pārbaudiet izņēmuma ziņojumu detaļām. - PHP
upload_max_filesizeunpost_max_sizeiestatījumi var ierobežot failu augšupielādi. - Vairāku failu augšupielādes gadījumā vienmēr iterējiet caur
UploadedFileobjektu masīvu.
Izmaiņu žurnāls
- v3.12.0 - Pievienota
UploadedFileklase pieprasījuma objektam vieglākai failu apstrādei.
Guides/unit_testing
Vienību testēšana Flight PHP ar PHPUnit
Šis ceļvedis iepazīstina ar vienību testēšanu Flight PHP, izmantojot PHPUnit, un ir paredzēts iesācējiem, kuri vēlas saprast, kāpēc vienību testēšanai ir nozīme un kā to praktiski pielietot. Mēs koncentrēsimies uz uzvedības testēšanu — nodrošinot, ka jūsu lietotne dara to, ko jūs sagaidāt, piemēram, nosūta e-pastu vai saglabā ierakstu — nevis uz triviāliem aprēķiniem. Sāksim ar vienkāršu maršruta apstrādātāju un pāriesim uz sarežģītāku kontrolleri, iekļaujot atkarību injekciju (DI) un trešo pušu pakalpojumu atdarināšanu.
Kāpēc vienību testēšana?
Vienību testēšana nodrošina, ka jūsu kods darbojas, kā paredzēts, atklājot kļūdas, pirms tās nonāk ražošanā. Tas ir īpaši vērtīgi Flight, kur vieglā maršrutēšana un elastība var novest pie sarežģītām mijiedarbībām. Atsevišķiem izstrādātājiem vai komandām vienību testi kalpo kā drošības tīkls, dokumentējot paredzamo uzvedību un novēršot regresijas, kad vēlāk atgriežaties pie sava koda. Tie arī uzlabo dizainu: grūti testējams kods bieži norāda uz pārāk sarežģītām vai cieši saistītām klasēm.
Atšķirībā no vienkāršotiem piemēriem (piemēram, testējot x * y = z), mēs koncentrēsimies uz reālās pasaules uzvedību, piemēram, ievades validāciju, datu saglabāšanu vai darbību aktivizēšanu, piemēram, e-pastus. Mūsu mērķis ir padarīt testēšanu pieejamu un jēgpilnu.
Vispārīgi vadošie principi
- Testējiet uzvedību, nevis ieviešanu: Koncentrējieties uz rezultātiem (piemēram, "e-pasts nosūtīts" vai "ieraksts saglabāts"), nevis uz iekšējām detaļām. Tas padara testus izturīgus pret refaktorēšanu.
- Pārtrauciet lietot
Flight::: Flight statiskās metodes ir ļoti ērtas, bet apgrūtina testēšanu. Jums vajadzētu pierast lietot$appmainīgo no$app = Flight::app();.$appir visas tās pašas metodes, kas irFlight::. Jūs joprojām varēsiet lietot$app->route()vai$this->app->json()savā kontrollerī utt. Tāpat izmantojiet īsto Flight maršrutētāju ar$router = $app->router()un pēc tam varat lietot$router->get(),$router->post(),$router->group()utt. Skatiet Maršrutēšana. - Turiet testus ātrus: Ātri testi veicina biežu izpildi. Izvairieties no lēnām darbībām, piemēram, datubāzes izsaukumiem vienību testos. Ja jums ir lēns tests, tā ir zīme, ka rakstāt integrācijas testu, nevis vienību testu. Integrācijas testi ir tad, kad faktiski iesaistāt reālas datubāzes, reālus HTTP izsaukumus, reālu e-pasta sūtīšanu utt. Tiem ir sava vieta, bet tie ir lēni un var būt nestabili, kas nozīmē, ka tie dažkārt neizdodas nezināma iemesla dēļ.
- Izmantojiet aprakstošus nosaukumus: Testu nosaukumiem skaidri jāapraksta pārbaudāmā uzvedība. Tas uzlabo lasāmību un uzturējamību.
- Izvairieties no globālajiem mainīgajiem kā no mēra: Samaziniet
$app->set()un$app->get()lietošanu, jo tie darbojas kā globālais stāvoklis, prasot atdarinājumus katrā testā. Dodiet priekšroku DI vai DI konteineram (skatiet Atkarību injekcijas konteiners). Pat$app->map()metodes izmantošana tehniski ir "globāla", un no tās vajadzētu izvairīties par labu DI. Izmantojiet sesijas bibliotēku, piemēram, flightphp/session, lai testos varētu atdarināt sesijas objektu. Neizsauciet$_SESSIONtieši savā kodā, jo tā ir globālā mainīgā ieviešana jūsu kodā, kas apgrūtina testēšanu. - Izmantojiet atkarību injekciju: Injicējiet atkarības (piemēram,
PDO, e-pasta sūtītājus) kontrolleros, lai izolētu loģiku un vienkāršotu atdarināšanu. Ja jums ir klase ar pārāk daudz atkarībām, apsveriet iespēju to refaktorēt mazākās klasēs, no kurām katra ir atbildīga par vienu lietu, ievērojot SOLID principus. - Atdariniet trešo pušu pakalpojumus: Atdariniet datubāzes, HTTP klientus (cURL) vai e-pasta pakalpojumus, lai izvairītos no ārējiem izsaukumiem. Testējiet vienu vai divus slāņus dziļi, bet ļaujiet savai pamatloģikai darboties. Piemēram, ja jūsu lietotne sūta īsziņas, jūs NEVĒLATIES patiešām sūtīt īsziņu katru reizi, kad palaižat testus, jo šīs izmaksas uzkrāsies (un būs lēnāk). Tā vietā atdariniet īsziņu pakalpojumu un vienkārši pārbaudiet, vai jūsu kods izsauca īsziņu pakalpojumu ar pareizajiem parametriem.
- Tiecieties uz augstu pārklājumu, nevis pilnību: 100% rindu pārklājums ir labs, bet tas nenozīmē, ka viss jūsu kodā ir testēts tā, kā vajadzētu (izpētiet zaru/ceļu pārklājumu PHPUnit). Prioritāti piešķiriet kritiskajai uzvedībai (piemēram, lietotāja reģistrācijai, API atbildēm un neveiksmīgu atbilžu tveršanai).
- Izmantojiet kontrollerus maršrutiem: Maršrutu definīcijās izmantojiet kontrollerus, nevis slēgumus.
flight\Engine $apppēc noklusējuma tiek injicēts katrā kontrollerī caur konstruktoru. Testos izmantojiet$app = new Flight\Engine(), lai testa ietvaros izveidotu Flight instanci, injicētu to savā kontrollerī un izsauktu metodes tieši (piemēram,$controller->register()). Skatiet Flight paplašināšana un Maršrutēšana. - Izvēlieties atdarināšanas stilu un pieturieties pie tā: PHPUnit atbalsta vairākus atdarināšanas stilus (piemēram, prophecy, iebūvētos atdarinājumus), vai arī varat izmantot anonīmās klases, kurām ir savas priekšrocības, piemēram, koda pabeigšana, lūšana, ja maināt metodes definīciju, utt. Vienkārši esiet konsekventi savos testos. Skatiet PHPUnit Mock Objects.
- Izmantojiet
protectedredzamību metodēm/īpašībām, kuras vēlaties testēt apakšklasēs: Tas ļauj tās pārdefinēt testa apakšklasēs, nepadarot tās publiskas; tas ir īpaši noderīgi anonīmu klašu atdarinājumiem.
PHPUnit iestatīšana
Pirmkārt, iestatiet PHPUnit savā Flight PHP projektā, izmantojot Composer, lai atvieglotu testēšanu. Skatiet PHPUnit sākšanas rokasgrāmatu, lai iegūtu vairāk informācijas.
-
Sava projekta direktorijā izpildiet:
composer require --dev phpunit/phpunitTas instalē jaunāko PHPUnit kā izstrādes atkarību.
-
Izveidojiet
testsdirektoriju sava projekta saknē testa failiem. -
Pievienojiet testa skriptu failam
composer.jsonērtībai:// cits composer.json saturs "scripts": { "test": "phpunit --configuration phpunit.xml" } -
Izveidojiet failu
phpunit.xmlsaknē:<?xml version="1.0" encoding="UTF-8"?> <phpunit bootstrap="vendor/autoload.php"> <testsuites> <testsuite name="Flight Tests"> <directory>tests</directory> </testsuite> </testsuites> </phpunit>
Tagad, kad jūsu testi ir izveidoti, varat palaist composer test, lai izpildītu testus.
Vienkārša maršruta apstrādātāja testēšana
Sāksim ar pamata maršrutu, kas validē lietotāja e-pasta ievadi. Mēs testēsim tā uzvedību: veiksmes ziņojuma atgriešanu derīgiem e-pastiem un kļūdas ziņojumu nederīgiem. E-pasta validācijai mēs izmantojam filter_var.
// index.php
$app->route('POST /register', [ UserController::class, 'register' ]);
// UserController.php
class UserController {
protected $app;
public function __construct(flight\Engine $app) {
$this->app = $app;
}
public function register() {
$email = $this->app->request()->data->email;
$responseArray = [];
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$responseArray = ['status' => 'error', 'message' => 'Invalid email'];
} else {
$responseArray = ['status' => 'success', 'message' => 'Valid email'];
}
$this->app->json($responseArray);
}
}
Lai to testētu, izveidojiet testa failu. Skatiet Vienību testēšana un SOLID principi, lai uzzinātu vairāk par testu strukturēšanu:
// tests/UserControllerTest.php
use PHPUnit\Framework\TestCase;
use Flight;
use flight\Engine;
class UserControllerTest extends TestCase {
public function testValidEmailReturnsSuccess() {
$app = new Engine();
$request = $app->request();
$request->data->email = 'test@example.com'; // Simulē POST datus
$UserController = new UserController($app);
$UserController->register($request->data->email);
$response = $app->response()->getBody();
$output = json_decode($response, true);
$this->assertEquals('success', $output['status']);
$this->assertEquals('Valid email', $output['message']);
}
public function testInvalidEmailReturnsError() {
$app = new Engine();
$request = $app->request();
$request->data->email = 'invalid-email'; // Simulē POST datus
$UserController = new UserController($app);
$UserController->register($request->data->email);
$response = $app->response()->getBody();
$output = json_decode($response, true);
$this->assertEquals('error', $output['status']);
$this->assertEquals('Invalid email', $output['message']);
}
}
Galvenie punkti:
- Mēs simulējam POST datus, izmantojot pieprasījuma klasi. Neizmantojiet globālus mainīgos, piemēram,
$_POST,$_GETutt., jo tas padara testēšanu sarežģītāku (jums vienmēr ir jāatiestata šīs vērtības, pretējā gadījumā citi testi var neizdoties). - Visi kontrolleri pēc noklusējuma saņem
flight\Engineinstanci, kas tiek injicēta tajos pat bez DIC konteinera iestatīšanas. Tas ievērojami atvieglo kontrolleru tiešu testēšanu. - Nav vispār izmantots
Flight::, padarot kodu vieglāk testējamu. - Testi pārbauda uzvedību: pareizu statusu un ziņojumu derīgiem/nederīgiem e-pastiem.
Izpildiet composer test, lai pārliecinātos, ka maršruts darbojas, kā paredzēts. Lai uzzinātu vairāk par pieprasījumiem un atbildēm Flight, skatiet attiecīgo dokumentāciju.
Atkarību injekcijas izmantošana testējamiem kontrolleriem
Sarežģītākiem scenārijiem izmantojiet atkarību injekciju (DI), lai kontrollerus padarītu testējamus. Izvairieties no Flight globālajiem mainīgajiem (piemēram, Flight::set(), Flight::map(), Flight::register()), jo tie darbojas kā globālais stāvoklis, prasot atdarinājumus katrā testā. Tā vietā izmantojiet Flight DI konteineru, DICE, PHP-DI vai manuālo DI.
Izmantosim flight\database\SimplePdo, nevis tiešu PDO. Šo palīgu ir daudz vieglāk atdarināt un vienību testēt (un tas ir vēlamāks par novecojušo PdoWrapper).
Šeit ir kontrolleris, kas saglabā lietotāju datubāzē un nosūta sagaidīšanas e-pastu:
use flight\database\SimplePdo;
class UserController {
protected $app;
protected $db;
protected $mailer;
public function __construct(Engine $app, SimplePdo $db, MailerInterface $mailer) {
$this->app = $app;
$this->db = $db;
$this->mailer = $mailer;
}
public function register() {
$email = $this->app->request()->data->email;
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
// return pievienošana šeit palīdz apturēt izpildi vienību testēšanā
return $this->app->jsonHalt(['status' => 'error', 'message' => 'Invalid email']);
}
$this->db->runQuery('INSERT INTO users (email) VALUES (?)', [$email]);
$this->mailer->sendWelcome($email);
return $this->app->json(['status' => 'success', 'message' => 'User registered']);
}
}
Galvenie punkti:
- Kontrolleris ir atkarīgs no
SimplePdoinstances unMailerInterface(izdomāta trešās puses e-pasta pakalpojuma). - Atkarības tiek injicētas caur konstruktoru, izvairoties no globālajiem mainīgajiem.
Kontrollera testēšana ar atdarinājumiem (mocks)
Tagad testēsim UserController uzvedību: e-pastu validāciju, saglabāšanu datubāzē un e-pastu sūtīšanu. Mēs atdarināsim datubāzi un e-pasta sūtītāju, lai izolētu kontrolleri.
// tests/UserControllerDICTest.php
use flight\database\SimplePdo;
use PHPUnit\Framework\TestCase;
class UserControllerDICTest extends TestCase {
public function testValidEmailSavesAndSendsEmail() {
// Dažreiz ir nepieciešams sajaukt atdarināšanas stilus
// Šeit mēs izmantojam PHPUnit iebūvēto atdarinājumu PDOStatement
$statementMock = $this->createMock(PDOStatement::class);
$statementMock->method('execute')->willReturn(true);
// Anonīmas klases izmantošana, lai atdarinātu SimplePdo
$mockDb = new class($statementMock) extends SimplePdo {
protected $statementMock;
public function __construct($statementMock) {
$this->statementMock = $statementMock;
}
// Kad mēs to atdarinām šādi, mēs īsti neveicam datubāzes izsaukumu.
// Mēs varam to tālāk konfigurēt, lai mainītu PDOStatement atdarinājumu, simulējot kļūmes utt.
public function runQuery(string $sql, array $params = []): PDOStatement {
return $this->statementMock;
}
};
$mockMailer = new class implements MailerInterface {
public $sentEmail = null;
public function sendWelcome($email): bool {
$this->sentEmail = $email;
return true;
}
};
$app = new Engine();
$app->request()->data->email = 'test@example.com';
$controller = new UserControllerDIC($app, $mockDb, $mockMailer);
$controller->register();
$response = $app->response()->getBody();
$result = json_decode($response, true);
$this->assertEquals('success', $result['status']);
$this->assertEquals('User registered', $result['message']);
$this->assertEquals('test@example.com', $mockMailer->sentEmail);
}
public function testInvalidEmailSkipsSaveAndEmail() {
$mockDb = new class() extends SimplePdo {
// Tukšs konstruktors apiet vecāka konstruktoru
public function __construct() {}
public function runQuery(string $sql, array $params = []): PDOStatement {
throw new Exception('Should not be called');
}
};
$mockMailer = new class implements MailerInterface {
public $sentEmail = null;
public function sendWelcome($email): bool {
throw new Exception('Should not be called');
}
};
$app = new Engine();
$app->request()->data->email = 'invalid-email';
// Nepieciešams kartēt jsonHalt, lai izvairītos no izejas
$app->map('jsonHalt', function($data) use ($app) {
$app->json($data, 400);
});
$controller = new UserControllerDIC($app, $mockDb, $mockMailer);
$controller->register();
$response = $app->response()->getBody();
$result = json_decode($response, true);
$this->assertEquals('error', $result['status']);
$this->assertEquals('Invalid email', $result['message']);
}
}
Galvenie punkti:
- Mēs atdarinām
SimplePdounMailerInterface, lai izvairītos no reāliem datubāzes vai e-pasta izsaukumiem. - Testi pārbauda uzvedību: derīgi e-pasti aktivizē datubāzes ievietošanu un e-pasta sūtīšanu; nederīgi e-pasti izlaiž abus.
- Atdariniet trešo pušu atkarības (piemēram,
SimplePdo,MailerInterface), ļaujot kontrollera loģikai darboties.
Pārāk liela atdarināšana
Esiet uzmanīgi, lai neatdarinātu pārāk lielu daļu sava koda. Tālāk es sniegšu piemēru, kāpēc tas varētu būt slikti, izmantojot mūsu UserController. Mēs mainīsim šo pārbaudi uz metodi ar nosaukumu isEmailValid (izmantojot filter_var), bet pārējos jaunos papildinājumus — uz atsevišķu metodi registerUser.
use flight\database\SimplePdo;
use flight\Engine;
// UserControllerDICV2.php
class UserControllerDICV2 {
protected $app;
protected $db;
protected $mailer;
public function __construct(Engine $app, SimplePdo $db, MailerInterface $mailer) {
$this->app = $app;
$this->db = $db;
$this->mailer = $mailer;
}
public function register() {
$email = $this->app->request()->data->email;
if (!$this->isEmailValid($email)) {
// return pievienošana šeit palīdz apturēt izpildi vienību testēšanā
return $this->app->jsonHalt(['status' => 'error', 'message' => 'Invalid email']);
}
$this->registerUser($email);
$this->app->json(['status' => 'success', 'message' => 'User registered']);
}
protected function isEmailValid($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
protected function registerUser($email) {
$this->db->runQuery('INSERT INTO users (email) VALUES (?)', [$email]);
$this->mailer->sendWelcome($email);
}
}
Un tagad pārāk atdarinātais vienību tests, kas īsti neko netesta:
use PHPUnit\Framework\TestCase;
class UserControllerTest extends TestCase {
public function testValidEmailSavesAndSendsEmail() {
$app = new Engine();
$app->request()->data->email = 'test@example.com';
// mēs šeit izlaižam papildu atkarību injekciju, jo tas ir "viegli"
$controller = new class($app) extends UserControllerDICV2 {
protected $app;
// Apiet atkarības konstruktorā
public function __construct($app) {
$this->app = $app;
}
// Mēs vienkārši piespiedīsim, lai tas būtu derīgs.
protected function isEmailValid($email) {
return true; // Vienmēr atgriež true, apejot reālo validāciju
}
// Apiet faktiskos datubāzes un e-pasta sūtītāja izsaukumus
protected function registerUser($email) {
return false;
}
};
$controller->register();
$response = $app->response()->getBody();
$result = json_decode($response, true);
$this->assertEquals('success', $result['status']);
$this->assertEquals('User registered', $result['message']);
}
}
Urrā, mums ir vienību testi un tie izdodas! Bet pagaidiet, kas notiktu, ja es faktiski mainītu isEmailValid vai registerUser iekšējo darbību? Mani testi joprojām izdotos, jo es esmu atdarinājis visu funkcionalitāti. Ļaujiet man parādīt, ko es domāju.
// UserControllerDICV2.php
class UserControllerDICV2 {
// ... citas metodes ...
protected function isEmailValid($email) {
// Mainītā loģika
$validEmail = filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
// Tagad tam vajadzētu būt tikai noteiktam domēnam
$validDomain = strpos($email, '@example.com') !== false;
return $validEmail && $validDomain;
}
}
Ja es palaistu savus iepriekš minētos vienību testus, tie joprojām izdotos! Bet, tā kā es netestēju uzvedību (faktiski neļaujot daļai koda izpildīties), es, iespējams, esmu ieprogrammējis kļūdu, kas gaida, lai notiktu ražošanā. Tests būtu jāmaina, lai ņemtu vērā jauno uzvedību, kā arī pretējo gadījumu, kad uzvedība nav tāda, kādu mēs sagaidām.
Pilns piemērs
Pilnu Flight PHP projekta piemēru ar vienību testiem varat atrast GitHub: n0nag0n/flight-unit-tests-guide. Lai iegūtu dziļāku izpratni, skatiet Vienību testēšana un SOLID principi.
Biežākās kļūdas
- Pārāk liela atdarināšana: Neatdariniet katru atkarību; ļaujiet daļai loģikas (piemēram, kontrollera validācijai) izpildīties, lai testētu reālu uzvedību. Skatiet Vienību testēšana un SOLID principi.
- Globālais stāvoklis: Bieža globālo PHP mainīgo (piemēram,
$_SESSION,$_COOKIE) izmantošana padara testus trauslus. Tas pats attiecas uzFlight::. Refaktorējiet, lai atkarības tiktu nodotas tieši. - Sarežģīta iestatīšana: Ja testa iestatīšana ir apgrūtinoša, jūsu klasei, iespējams, ir pārāk daudz atkarību vai pienākumu, pārkāpjot SOLID principus.
Mērogošana ar vienību testiem
Vienību testi noder lielākos projektos vai tad, kad pēc mēnešiem atgriežaties pie koda. Tie dokumentē uzvedību un atklāj regresijas, glābjot jūs no lietotnes no jauna apgūšanas. Atsevišķiem izstrādātājiem testējiet kritiskos ceļus (piemēram, lietotāja reģistrāciju, maksājumu apstrādi). Komandām testi nodrošina konsekventu uzvedību visās izmaiņās. Skatiet Kāpēc ietvari?, lai uzzinātu vairāk par ieguvumiem, ko sniedz ietvari un testi.
Dalieties ar saviem testēšanas padomiem Flight PHP dokumentācijas krātuvē!
Rakstījis n0nag0n 2025
Guides/blog
Vienkārša emuāra izveide ar Flight PHP
Šis ceļvedis palīdzēs jums izveidot vienkāršu emuāru, izmantojot Flight PHP ietvaru. Jūs izveidosiet projektu, definēsiet maršrutus, pārvaldīsiet ierakstus ar JSON un atveidosiet tos ar Latte šablonu dzinēju—vienlaikus parādot Flight vienkāršību un elastīgumu. Līdz beigām jums būs funkcionējošs emuārs ar sākumlapu, atsevišķu ierakstu lapām un izveides formu.
Priekšnosacījumi
- PHP 7.4+: Instalēts jūsu sistēmā.
- Composer: Atkarību pārvaldībai.
- Teksta redaktors: Jebkurš redaktors, piemēram, VS Code vai PHPStorm.
- Pamatzināšanas par PHP un tīmekļa izstrādi.
1. solis: Projekta iestatīšana
Sāciet, izveidojot jaunu projekta direktoriju un instalējot Flight, izmantojot Composer.
-
Izveidojiet direktoriju:
mkdir flight-blog cd flight-blog -
Instalējiet Flight:
composer require flightphp/core -
Izveidojiet publisko direktoriju: Flight izmanto vienu ieejas punktu (
index.php). Izveidojiet tampublic/mapi:mkdir public -
Vienkāršs
index.php: Izveidojietpublic/index.phpar vienkāršu “hello world” maršrutu:<?php require '../vendor/autoload.php'; Flight::route('/', function () { echo 'Hello, Flight!'; }); Flight::start(); -
Palaidiet iebūvēto serveri: Pārbaudiet savu iestatījumu ar PHP izstrādes serveri:
php -S localhost:8000 -t public/Apmeklējiet
http://localhost:8000, lai redzētu “Hello, Flight!”.
2. solis: Projekta struktūras organizēšana
Lai iegūtu tīru iestatījumu, strukturējiet projektu šādi:
flight-blog/
├── app/
│ ├── config/
│ └── views/
├── data/
├── public/
│ └── index.php
├── vendor/
└── composer.json
app/config/: Konfigurācijas faili (piemēram, notikumi, maršruti).app/views/: Veidnes lapu atveidošanai.data/: JSON fails emuāra ierakstu glabāšanai.public/: Tīmekļa sakne arindex.php.
3. solis: Latte instalēšana un konfigurēšana
Latte ir viegls šablonu dzinējs, kas labi integrējas ar Flight.
-
Instalējiet Latte:
composer require latte/latte -
Konfigurējiet Latte Flight: Atjauniniet
public/index.php, lai reģistrētu Latte kā skatu dzinēju:<?php require '../vendor/autoload.php'; use Latte\Engine; Flight::register('view', Engine::class, [], function ($latte) { $latte->setTempDirectory(__DIR__ . '/../cache/'); $latte->setLoader(new \Latte\Loaders\FileLoader(__DIR__ . '/../app/views/')); }); Flight::route('/', function () { Flight::view()->render('home.latte', ['title' => 'My Blog']); }); Flight::start(); -
Izveidojiet izkārtojuma veidni: Failā
app/views/layout.latte:<!DOCTYPE html> <html> <head> <title>{$title}</title> </head> <body> <header> <h1>My Blog</h1> <nav> <a href="/">Home</a> | <a href="/create">Create a Post</a> </nav> </header> <main> {block content}{/block} </main> <footer> <p>© {date('Y')} Flight Blog</p> </footer> </body> </html> -
Izveidojiet sākumlapas veidni: Failā
app/views/home.latte:{extends 'layout.latte'} {block content} <h2>{$title}</h2> <ul> {foreach $posts as $post} <li><a href="/post/{$post['slug']}">{$post['title']}</a></li> {/foreach} </ul> {/block}Restartējiet serveri, ja esat no tā izgājis, un apmeklējiet
http://localhost:8000, lai redzētu atveidoto lapu. -
Izveidojiet datu failu: Izmantojiet JSON failu, lai vienkāršības labad simulētu datubāzi. Failā
data/posts.json:[ { "slug": "first-post", "title": "My First Post", "content": "This is my very first blog post with Flight PHP!" } ]
4. solis: Maršrutu definēšana
Atdaliet savus maršrutus konfigurācijas failā, lai nodrošinātu labāku organizāciju.
-
Izveidojiet
routes.php: Failāapp/config/routes.php:<?php Flight::route('/', function () { Flight::view()->render('home.latte', ['title' => 'My Blog']); }); Flight::route('/post/@slug', function ($slug) { Flight::view()->render('post.latte', ['title' => 'Post: ' . $slug, 'slug' => $slug]); }); Flight::route('GET /create', function () { Flight::view()->render('create.latte', ['title' => 'Create a Post']); }); -
Atjauniniet
index.php: Iekļaujiet maršrutu failu:<?php require '../vendor/autoload.php'; use Latte\Engine; Flight::register('view', Engine::class, [], function ($latte) { $latte->setTempDirectory(__DIR__ . '/../cache/'); $latte->setLoader(new \Latte\Loaders\FileLoader(__DIR__ . '/../app/views/')); }); require '../app/config/routes.php'; Flight::start();
5. solis: Emuāra ierakstu glabāšana un ielāde
Pievienojiet metodes ierakstu ielādei un saglabāšanai.
-
Pievienojiet ierakstu metodi: Failā
index.phppievienojiet metodi ierakstu ielādei:Flight::map('posts', function () { $file = __DIR__ . '/../data/posts.json'; return json_decode(file_get_contents($file), true); }); -
Atjauniniet maršrutus: Modificējiet
app/config/routes.php, lai izmantotu ierakstus:<?php Flight::route('/', function () { $posts = Flight::posts(); Flight::view()->render('home.latte', [ 'title' => 'My Blog', 'posts' => $posts ]); }); Flight::route('/post/@slug', function ($slug) { $posts = Flight::posts(); $post = array_filter($posts, fn($p) => $p['slug'] === $slug); $post = reset($post) ?: null; if (!$post) { Flight::notFound(); return; } Flight::view()->render('post.latte', [ 'title' => $post['title'], 'post' => $post ]); }); Flight::route('GET /create', function () { Flight::view()->render('create.latte', ['title' => 'Create a Post']); });
6. solis: Veidņu izveide
Atjauniniet savas veidnes, lai attēlotu ierakstus.
-
Ieraksta lapa (
app/views/post.latte):{extends 'layout.latte'} {block content} <h2>{$post['title']}</h2> <div class="post-content"> <p>{$post['content']}</p> </div> {/block}
7. solis: Ierakstu izveides pievienošana
Apstrādājiet veidlapas iesniegšanu, lai pievienotu jaunus ierakstus.
-
Izveidojiet veidlapu (
app/views/create.latte):{extends 'layout.latte'} {block content} <h2>{$title}</h2> <form method="POST" action="/create"> <div class="form-group"> <label for="title">Title:</label> <input type="text" name="title" id="title" required> </div> <div class="form-group"> <label for="content">Content:</label> <textarea name="content" id="content" required></textarea> </div> <button type="submit">Save Post</button> </form> {/block} -
Pievienojiet POST maršrutu: Failā
app/config/routes.php:Flight::route('POST /create', function () { $request = Flight::request(); $title = $request->data['title']; $content = $request->data['content']; $slug = strtolower(str_replace(' ', '-', $title)); $posts = Flight::posts(); $posts[] = ['slug' => $slug, 'title' => $title, 'content' => $content]; file_put_contents(__DIR__ . '/../../data/posts.json', json_encode($posts, JSON_PRETTY_PRINT)); Flight::redirect('/'); }); -
Izmēģiniet to:
- Apmeklējiet
http://localhost:8000/create. - Iesniedziet jaunu ierakstu (piemēram, “Otrais ieraksts” ar kādu saturu).
- Pārbaudiet sākumlapu, lai redzētu to sarakstā.
- Apmeklējiet
8. solis: Kļūdu apstrādes uzlabošana
Pārdefinējiet notFound metodi, lai nodrošinātu labāku 404 pieredzi.
Failā index.php:
Flight::map('notFound', function () {
Flight::view()->render('404.latte', ['title' => 'Page Not Found']);
});
Izveidojiet app/views/404.latte:
{extends 'layout.latte'}
{block content}
<h2>404 - {$title}</h2>
<p>Sorry, that page doesn't exist!</p>
{/block}
Turpmākās darbības
- Pievienojiet stilus: Izmantojiet CSS savās veidnēs, lai iegūtu labāku izskatu.
- Datubāze: Aizstājiet
posts.jsonar datubāzi, piemēram, SQLite, izmantojot SimplePdo. - Validācija: Pievienojiet pārbaudes dublikātu slug vai tukšu ievades lauku noteikšanai.
- Starpniekprogrammatūra: Ieviesiet autentifikāciju ierakstu izveidei.
Secinājums
Jūs esat izveidojuši vienkāršu emuāru ar Flight PHP! Šis ceļvedis demonstrē galvenās funkcijas, piemēram, maršrutēšanu, šablonu izmantošanu ar Latte un veidlapu iesniegumu apstrādi—vienlaikus saglabājot vieglumu. Izpētiet Flight dokumentāciju, lai uzzinātu par papildu funkcijām, kas palīdzēs attīstīt jūsu emuāru tālāk!
License
MIT licences (MIT)
=====================
Autortiesības © 2024 @mikecao, @n0nag0n
Atļauja tiek piešķirta bez maksas jebkuram personai, kas iegūst šīs programmatūras kopiju un saistītos dokumentus (turpmāk - "Programmatūra"), izmantot Programmatūru jebkurā veidā bez ierobežojumiem, ieskaitot tiesības izmantot, kopēt, modificēt, apvienot, publicēt, izplatīt, licencēt un/vai pārdot Programmatūras kopijas, un atļaut personas, kam Programmatūra tiek nodrošināta to darīt, pakļautas zemāk minētajām nosacījumiem:
Minētās autortiesību paziņojums un šī atļaujas paziņojums ir jāiekļauj visās kopijās vai būtiskajos Programmatūras daļās.
PROGRAMMATŪRA TIEK NODROŠINĀTA "KĀ TĀDA", BEZ JEBKĀDAS GARANTIJAS IZTEIKTAS VAI IMPLICITAS, IETVEROT, BET NEIEROBEŽOTI, MERCHANTĀLĀS KVALITĀTES UN PIEMĒROTĪBAS KONKRĒTIEM MĒRĶIEM UN NEPĀRKĀPJUMS. NEVIENĀ GADĪJUMĀ AUTORI VAI AUTORTIESĪBU IEDZĪVOTĀJI NAV ATBILDĪGI PAR JEBKURU PRASĪBU, KAITĒJUMU VAI CITĀM SAISTĪBĀM, NEATKARĪGI NO TĀ, VAI TĀS IERAKSTS, IAUCIENS VAI CITĀDI RADIES SAISTĪBĀ AR PROGRAMMATŪRU VAI LIETOŠANU VAI CITĀDĀM DARĪBĀM AR PROGRAMMATŪRU.
About
Flight PHP Framework
Flight ir ātrs, vienkāršs, paplašināms PHP ietvars — izveidots izstrādātājiem, kuri vēlas ātri paveikt darbu bez liekām grūtībām. Neatkarīgi no tā, vai veidojat klasisku tīmekļa lietotni, zibenīgi ātru API vai strādājat kopā ar mākslīgā intelekta kodēšanas palīgiem, Flight nelielais apjoms un vienkāršais dizains padara to par ideālu izvēli. Flight ir veidots kā viegls, bet var arī apmierināt uzņēmuma līmeņa arhitektūras prasības.
Kāpēc Izvēlēties Flight?
- Draudzīgs Iesācējiem: Flight ir lieliska sākuma vieta jauniem PHP izstrādātājiem. Tā skaidrā struktūra un vienkāršā sintakse palīdz apgūt tīmekļa izstrādi, nenokļūstot zaudējumā standarta kodā.
- Iemīļots Profesionāļu Vidū: Pieredzējuši izstrādātāji Flight mīl tā elastības un kontroles dēļ. Jūs varat mērogot no neliela prototipa līdz pilnvērtīgai lietotnei, nemainot ietvarus.
- Atpakaļsavietojams: Mēs novērtējam jūsu laiku. Flight v3 ir v2 papildinājums, saglabājot gandrīz visu to pašu API. Mēs ticam evolūcijai, nevis revolūcijai — vairs nav "pasaules salaušanas" katru reizi, kad iznāk jauna galvenā versija.
- Nulles Atkarības: Flight kodols ir pilnībā bez atkarībām — bez polifilliem, bez ārējām paketēm, pat bez PSR saskarnēm. Tas nozīmē mazāk uzbrukuma vektoru, mazāku pēdu un negaidītas pārtraucošas izmaiņas no augšupējām atkarībām. Izvēles spraudņi var ietvert atkarības, bet kodols vienmēr paliks viegls un drošs.
- AI Draudzīgs: Flight mazā API virsma un oficiālais skelets (viens izkārtojums,
AGENTS.md, konstruktora injekcija) atvieglo AI kodēšanas rīkiem sekot modelim. Tā pati koda bāze neatkarīgi no tā, vai rakstāt katru rindu vai strādājat ar aģentu. Uzziniet vairāk par AI izmantošanu ar Flight.
Video Pārskats
Ātrais Starts
Lai veiktu ātru minimālu instalāciju, instalējiet to ar Composer:
composer require flightphp/core
Vai arī varat lejupielādēt repozitorija zip failu šeit. Tad jums būs pamata index.php fails kā tālāk:
<?php
// if installed with composer
require 'vendor/autoload.php';
// or if installed manually by zip file
// require 'flight/Flight.php';
Flight::route('/', function() {
echo 'hello world!';
});
Flight::route('/json', function() {
Flight::json([
'hello' => 'world'
]);
});
Flight::start();
Tas ir viss! Jums ir pamata Flight lietotne. Tagad varat palaist šo failu ar php -S localhost:8000 un apmeklēt http://localhost:8000 savā pārlūkprogrammā, lai redzētu izvadi.
Īsi Flight:: piemēri kā šis ir lieliski mācībām un mikro lietotnēm. Pilnīgam projekta izkārtojumam, ko dalās cilvēki un AI rīki, izmantojiet tālāk minēto skeletu.
Skelets/Boilerplate Lietotne
Ir oficiāls starteris, kas palīdz sākt jebkuru jaunu Flight projektu. Tas izveido struktūru, konfigurāciju, Composer skriptus un AI draudzīgas instrukcijas no paša sākuma.
Apskatiet flightphp/skeleton, lai iegūtu gatavu projektu, vai apmeklējiet piemērus lapu, lai gūtu iedvesmu. Vēlaties AI darba plūsmas detaļas? Izpētiet AI un izstrādātāja pieredzi.
Ko jūs iegūstat (augsta līmeņa):
App\vārdtelpas ar PascalCase mapēm (app/Controller/,app/Middleware/,app/Model/, …)—mapes reģistram jāatbilst vārdtelpai (skatiet Autoloading)- Dice +
Engineinjekcija lai kontrolieri paliktu testējami (dodiet priekšroku$this->apppārFlight::lietotnes kodā) - Twig skati, SimplePdo + ActiveRecord paraugs, Runway migrate
- Saknes
AGENTS.md(plus scoped kopijas) unSECURITY.mdpalīgiem un drošības politikai
Skelet Lietotnes Instalēšana
Pietiekami vienkārši!
# Create the new project
composer create-project flightphp/skeleton my-project/
# Enter your new project directory
cd my-project/
# Bring up the local dev-server to get started right away!
composer start
Tas izveido projekta struktūru, kopē config_sample.php → config.php (un .env.example → .env, ja tāds ir), un jūs esat gatavs sākt. Izvēles parauga dati:
php runway migrate
# then visit /posts and /api/posts
Augsta Veiktspēja
Flight ir viens no ātrākajiem PHP ietvariem. Tā vieglais kodols nozīmē mazāku pieskaitāmību un lielāku ātrumu — ideāli gan tradicionālām lietotnēm, gan modernām AI atbalstītām darba plūsmām. Visus etalonus varat redzēt TechEmpower
Skatiet etalonu zemāk ar dažiem citiem populāriem PHP ietvariem.
| Framework | Plaintext Reqs/sec | JSON Reqs/sec |
|---|---|---|
| Flight | 190,421 | 182,491 |
| Yii | 145,749 | 131,434 |
| Fat-Free | 139,238 | 133,952 |
| Slim | 89,588 | 87,348 |
| Phalcon | 95,911 | 87,675 |
| Symfony | 65,053 | 63,237 |
| Lumen | 40,572 | 39,700 |
| Laravel | 26,657 | 26,901 |
| CodeIgniter | 20,628 | 19,901 |
Flight un AI
Vai esat ziņkārīgs, kā Flight sadarbojas ar kodēšanas LLM? Atklājiet, kā AGENTS.md, Runway ai:* komandas un skeleta izkārtojums uztur palīgus uz pareizā ceļa.
Stabilitāte un Atpakaļsavietojamība
Mēs novērtējam jūsu laiku. Mēs visi esam redzējuši ietvarus, kas pilnībā pārvērtē sevi ik pēc pāris gadiem, atstājot izstrādātājus ar salauztu kodu un dārgām migrācijām. Flight ir citāds. Flight v3 tika izstrādāts kā v2 papildinājums, kas nozīmē, ka API, ko jūs zināt un mīlat, nav noņemts. Patiesībā lielākā daļa v2 projektu darbosies bez jebkādām izmaiņām v3.
Mēs esam apņēmušies uzturēt Flight stabilu, lai jūs varētu koncentrēties uz savas lietotnes izveidi, nevis sava ietvara labošanu. Skelets var būt uzskatu balstīts jauniem projektiem; kodola API paliek pazīstami visiem citiem.
Kopiena
Mēs esam Matrix Chat
Un Discord
Ieguldījums
Ir divi veidi, kā varat ieguldīt Flight:
- Ieguldīt kodola ietvarā, apmeklējot kodola repozitoriju.
- Palīdzēt padarīt dokumentāciju labāku! Šī dokumentācijas vietne tiek mitināta Github. Ja pamanāt kļūdu vai vēlaties kaut ko uzlabot, droši iesniedziet pull request. Mēs mīlam atjauninājumus un jaunas idejas — īpaši par AI un jaunām tehnoloģijām!
Prasības
Flight prasa PHP 7.4 vai jaunāku versiju.
Piezīme: PHP 7.4 tiek atbalstīts, jo pašreizējā rakstīšanas laikā (2024) PHP 7.4 ir noklusējuma versija dažām LTS Linux distribūcijām. Piespiežot pāriet uz PHP >8, radītu daudz problēmu šiem lietotājiem. Ietvars arī atbalsta PHP >8.
Licence
Flight tiek izlaists saskaņā ar MIT licenci.
Awesome-plugins/php_cookie
Sīkfaili
overclokk/cookie ir vienkārša bibliotēka sīkfailu pārvaldībai jūsu lietotnē.
Instalēšana
Instalēšana ir vienkārša ar komponistu.
composer require overclokk/cookie
Izmantos̄ana
Lietošana ir tik vienkārša kā jaunas metodes reģistrēšana Flight klases.
use Overclokk\Cookie\Cookie;
/*
* Iestatiet savā palaišanas vai public/index.php failā
*/
Flight::register('cookie', Cookie::class);
/**
* ExampleController.php
*/
class ExampleController {
public function login() {
// Iestatiet sīkfailu
// jums vajadzētu, lai tas būtu false, tādēļ, lai jūs saņemtu jaunu instanci
// izmantojiet zemāk esošo komentāru, ja vēlaties autovērstjanu
/** @var \Overclokk\Cookie\Cookie $cookie */
$cookie = Flight::cookie(false);
$cookie->set(
'stay_logged_in', // sīkfaila nosaukums
'1', // vērtība, kuru vēlaties iestatīt
86400, // cik sekundes sīkfailam būtu jāpastāv
'/', // ceļš, kurā būs pieejams sīkfails
'example.com', // domēns, kurā būs pieejams sīkfails
true, // sīkfails tiks pārraidīts tikai pār šifrētu HTTPS savienojumu
true // sīkfails būs pieejams tikai caur HTTP protokolu
);
// pēc izvēles, ja vēlaties saglabāt noklusējuma vērtības
// un ātri iestatīt sīkfailu ilgu laiku
$cookie->forever('stay_logged_in', '1');
}
public function home() {
// Pārbaudiet, vai jums ir sīkfails
if (Flight::cookie()->has('stay_logged_in')) {
// ielieciet tos piemēram, informācijas panelī.
Flight::redirect('/dashboard');
}
}
}Awesome-plugins/php_encryption
PHP Šifrēšana
defuse/php-encryption ir bibliotēka, kas var tikt izmantota datu šifrēšanai un atšifrēšanai. Uzsākšana ir diezgan vienkārša, lai sāktu šifrēt un atšifrēt datus. Viņiem ir lielisks rokasgrāmata, kas palīdz izskaidrot pamatus par to, kā izmantot bibliotēku, kā arī svarīgu drošības aspektu, kas saistīti ar šifrēšanu.
Instalēšana
Instalēšana ir vienkārša ar komponistu.
composer require defuse/php-encryption
Iestatījumi
Pēc tam jums būs jāģenerē šifrēšanas atslēga.
vendor/bin/generate-defuse-key
Tas izvadīs atslēgu, ko būsiet jāsargā. Jūs varētu saglabāt atslēgu savā app/config/config.php failā masīvā faila apakšdaļā. Lai gan tas nav ideāla vieta, tas vismaz ir kaut kas.
Lietošana
Tagad, kad jums ir bibliotēka un šifrēšanas atslēga, varat sākt šifrēt un atšifrēt datus.
use Defuse\Crypto\Crypto;
use Defuse\Crypto\Key;
/*
* Uzstādiet savā bootstrap vai public/index.php failā
*/
// Šifrēšanas metode
Flight::map('encrypt', function($sastāvs_dati) {
$šifrēšanas_atslēga = /* $config['encryption_key'] vai file_get_contents no vietas, kur likāt atslēgu */;
return Crypto::encrypt($sastāvs_dati, Key::loadFromAsciiSafeString($šifrēšanas_atslēga));
});
// Atšifrēšanas metode
Flight::map('decrypt', function($šifrētie_dati) {
$šifrēšanas_atslēga = /* $config['encryption_key'] vai file_get_contents no vietas, kur likāt atslēgu */;
try {
$sastāvs_dati = Crypto::decrypt($šifrētie_dati, Key::loadFromAsciiSafeString($šifrēšanas_atslēga));
} catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
// Uzbrukums! Vai nu tika ielādēta nepareizā atslēga, vai arī šifrētais teksts ir mainījies, kopš tas tika izveidots - vai nu sabojājies datu bāzē vai nodomāti modificējis Eva, mēģinot veikt uzbrukumu.
// ... apstrādājiet šo gadījumu tādā veidā, kas ir piemērots jūsu lietojumprogrammai ...
}
return $sastāvs_dati;
});
Flight::route('/encrypt', function() {
$šifrētie_dati = Flight::encrypt('Šis ir noslēpums');
echo $šifrētie_dati;
});
Flight::route('/decrypt', function() {
$šifrētie_dati = '...'; // Iegūstiet šifrētos datus no kaut kurienes
$atšifrētie_dati = Flight::decrypt($šifrētie_dati);
echo $atšifrētie_dati;
});Awesome-plugins/php_file_cache
flightphp/cache
Viegls, vienkāršs un patstāvīgs PHP failu kešatmiņas klase, kas atdalīta no Wruczek/PHP-File-Cache
Priekšrocības
- Viegls, patstāvīgs un vienkāršs
- Viss kods vienā failā - nav lieku draiveru
- Drošs - katram ģenerētajam kešatmiņas failam ir PHP galvene ar die, padarot tiešu piekļuvi neiespējamu pat tad, ja kāds zina ceļu un jūsu serveris nav pareizi konfigurēts
- Labi dokumentēts un testēts
- Pareizi apstrādā vienlaicīgumu, izmantojot flock
- Atbalsta PHP 7.4+
- Bezmaksas saskaņā ar MIT licenci
Šī dokumentācijas vietne izmanto šo bibliotēku, lai kešotu katru lapu!
Noklikšķiniet šeit, lai skatītu kodu.
Instalācija
Instalējiet, izmantojot composer:
composer require flightphp/cache
Izmantošana
Izmantošana ir diezgan vienkārša. Tas saglabā kešatmiņas failu kešatmiņas direktorijā.
use flight\Cache;
$app = Flight::app();
// Jūs nododat direktoriju, kurā tiks saglabāta kešatmiņa, konstruktorā
$app->register('cache', Cache::class, [ __DIR__ . '/../cache/' ], function(Cache $cache) {
// Tas nodrošina, ka kešatmiņa tiek izmantota tikai ražošanas režīmā
// ENVIRONMENT ir konstante, kas tiek iestatīta jūsu bootstrap failā vai citur jūsu lietotnē
$cache->setDevMode(ENVIRONMENT === 'development');
});
Iegūt kešatmiņas vērtību
Jūs izmantojat metodi get(), lai iegūtu kešotu vērtību. Ja vēlaties ērtu metodi, kas atsvaidzinās kešatmiņu, ja tā ir beigusies, varat izmantot refreshIfExpired().
// Iegūt kešatmiņas instanci
$cache = Flight::cache();
$data = $cache->refreshIfExpired('simple-cache-test', function () {
return date("H:i:s"); // atgriezt datus, kas jākešo
}, 10); // 10 sekundes
// vai
$data = $cache->get('simple-cache-test');
if(empty($data)) {
$data = date("H:i:s");
$cache->set('simple-cache-test', $data, 10); // 10 sekundes
}
Saglabāt kešatmiņas vērtību
Jūs izmantojat metodi set(), lai saglabātu vērtību kešatmiņā.
Flight::cache()->set('simple-cache-test', 'my cached data', 10); // 10 sekundes
Dzēst kešatmiņas vērtību
Jūs izmantojat metodi delete(), lai dzēstu vērtību kešatmiņā.
Flight::cache()->delete('simple-cache-test');
Pārbaudīt, vai kešatmiņas vērtība pastāv
Jūs izmantojat metodi exists(), lai pārbaudītu, vai vērtība pastāv kešatmiņā.
if(Flight::cache()->exists('simple-cache-test')) {
// darīt kaut ko
}
Notīrīt kešatmiņu
Jūs izmantojat metodi flush(), lai notīrītu visu kešatmiņu.
Flight::cache()->flush();
Iegūt metadatus ar kešatmiņu
Ja vēlaties iegūt laika zīmogus un citus metadatus par kešatmiņas ierakstu, pārliecinieties, ka nododat true kā pareizo parametru.
$data = $cache->refreshIfExpired("simple-cache-meta-test", function () {
echo "Refreshing data!" . PHP_EOL;
return date("H:i:s"); // atgriezt datus, kas jākešo
}, 10, true); // true = atgriezt ar metadatiem
// vai
$data = $cache->get("simple-cache-meta-test", true); // true = atgriezt ar metadatiem
/*
Kehšatmiņas vienuma piemērs, kas iegūts ar metadatiem:
{
"time":1511667506, <-- saglabāt unix laika zīmogu
"expire":10, <-- derīguma laiks sekundēs
"data":"04:38:26", <-- deserializēti dati
"permanent":false
}
Izmantojot metadatus, mēs varam, piemēram, aprēķināt, kad vienums tika saglabāts vai kad tas beidzas
Mēs varam arī piekļūt pašiem datiem, izmantojot atslēgu "data"
*/
$expiresin = ($data["time"] + $data["expire"]) - time(); // iegūt unix laika zīmogu, kad dati beidzas, un atņemt no tā pašreizējo laika zīmogu
$cacheddate = $data["data"]; // mēs piekļūstam pašiem datiem, izmantojot atslēgu "data"
echo "Latest cache save: $cacheddate, expires in $expiresin seconds";
Avota kods
Apmeklējiet https://github.com/flightphp/cache, lai skatītu kodu.
Awesome-plugins/permissions
FlightPHP/Permissions
Šis ir piekļuves tiesību modulis, kuru var izmantot savos projektos, ja jūsu lietotnē ir vairākas lomas un katrai lomai ir nedaudz atšķirīga funkcionalitāte. Šis modulis ļauj definēt piekļuves tiesības katrai lomai un pēc tam pārbaudīt, vai pašreizējam lietotājam ir tiesības piekļūt noteiktai lapai vai veikt noteiktu darbību.
Noklikšķiniet šeit, lai atvērtu repozitoriju GitHub.
Instalācija
Izpildiet composer require flightphp/permissions un esat gatavs!
Lietošana
Vispirms jāizveido piekļuves tiesības, pēc tam jāpastāsta lietotnei, ko tās nozīmē. Galu galā piekļuves tiesības pārbaudīsiet ar $Permissions->has(), ->can() vai is(). has() un can() ir vienāda funkcionalitāte, bet tiem ir atšķirīgi nosaukumi, lai jūsu kods būtu lasāmāks.
Pamata piemērs
Pieņemsim, ka jūsu lietotnē ir funkcija, kas pārbauda, vai lietotājs ir pieteicies. Jūs varat izveidot piekļuves tiesību objektu šādi:
// index.php
require 'vendor/autoload.php';
// kāds kods
// tad jūs droši vien kaut ko izmantojat, kas jums pasaka, kāda ir pašreizējā lietotāja loma
// visticamāk, jums ir kaut kas, kas izvelk pašreizējo lomu
// no sesijas mainīgā, kas to definē
// pēc tam, kad kāds piesakās, pretējā gadījumā viņam būs 'guest' vai 'public' loma.
$current_role = 'admin';
// piekļuves tiesību iestatīšana
$permission = new \flight\Permission($current_role);
$permission->defineRule('loggedIn', function($current_role) {
return $current_role !== 'guest';
});
// Jūs droši vien vēlaties saglabāt šo objektu Flight kaut kur
Flight::set('permission', $permission);
Tad kādā kontrolierī varētu būt kaut kas līdzīgs šim.
<?php
// kāds kontrolieris
class SomeController {
public function someAction() {
$permission = Flight::get('permission');
if ($permission->has('loggedIn')) {
// darīt kaut ko
} else {
// darīt kaut ko citu
}
}
}
To varat izmantot arī, lai izsekotu, vai viņiem ir tiesības kaut ko darīt jūsu lietotnē. Piemēram, ja jums ir veids, kā lietotāji var mijiedarboties ar ziņām jūsu programmatūrā, varat pārbaudīt, vai viņiem ir tiesības veikt noteiktas darbības.
$current_role = 'admin';
// piekļuves tiesību iestatīšana
$permission = new \flight\Permission($current_role);
$permission->defineRule('post', function($current_role) {
if($current_role === 'admin') {
$permissions = ['create', 'read', 'update', 'delete'];
} else if($current_role === 'editor') {
$permissions = ['create', 'read', 'update'];
} else if($current_role === 'author') {
$permissions = ['create', 'read'];
} else if($current_role === 'contributor') {
$permissions = ['create'];
} else {
$permissions = [];
}
return $permissions;
});
Flight::set('permission', $permission);
Tad kādā kontrolierī...
class PostController {
public function create() {
$permission = Flight::get('permission');
if ($permission->can('post.create')) {
// darīt kaut ko
} else {
// darīt kaut ko citu
}
}
}
Atkarību ievadīšana
Atkarības var ievadīt slēgtā funkcijā, kas definē piekļuves tiesības. Tas ir noderīgi, ja jums ir kāds slēdzis, id vai jebkurš cits datu punkts, pret kuru vēlaties pārbaudīt. Tas pats attiecas uz Class->Method tipa izsaukumiem, izņemot to, ka argumentus definējat metodē.
Slēgtās funkcijas
$Permission->defineRule('order', function(string $current_role, MyDependency $MyDependency = null) {
// ... kods
});
// jūsu kontrolierī
public function createOrder() {
$MyDependency = Flight::myDependency();
$permission = Flight::get('permission');
if ($permission->can('order.create', $MyDependency)) {
// darīt kaut ko
} else {
// darīt kaut ko citu
}
}
Klases
namespace MyApp;
class Permissions {
public function order(string $current_role, MyDependency $MyDependency = null) {
// ... kods
}
}
Īsceļš piekļuves tiesību iestatīšanai ar klasēm
Piekļuves tiesības var definēt arī ar klasēm. Tas ir noderīgi, ja jums ir daudz piekļuves tiesību un vēlaties saglabāt kodu tīru. Varat darīt kaut ko līdzīgu šim:
<?php
// inicializācijas kods
$Permissions = new \flight\Permission($current_role);
$Permissions->defineRule('order', 'MyApp\Permissions->order');
// myapp/Permissions.php
namespace MyApp;
class Permissions {
public function order(string $current_role, int $user_id) {
// Pieņemot, ka esat to iestatījis iepriekš
/** @var \flight\database\SimplePdo $db */
$db = Flight::db();
$allowed_permissions = [ 'read' ]; // visi var skatīt pasūtījumu
if($current_role === 'manager') {
$allowed_permissions[] = 'create'; // menedžeri var izveidot pasūtījumus
}
$some_special_toggle_from_db = $db->fetchField('SELECT some_special_toggle FROM settings WHERE id = ?', [ $user_id ]);
if($some_special_toggle_from_db) {
$allowed_permissions[] = 'update'; // ja lietotājam ir speciāls slēdzis, viņš var atjaunināt pasūtījumus
}
if($current_role === 'admin') {
$allowed_permissions[] = 'delete'; // administratori var dzēst pasūtījumus
}
return $allowed_permissions;
}
}
Interesantākais ir tas, ka ir arī īsceļš, ko var izmantot (ko var arī kešot!!!), kur vienkārši pasaka piekļuves tiesību klasei, lai tā kartētu visas metodes klasē uz piekļuves tiesībām. Tātad, ja jums ir metode ar nosaukumu order() un metode ar nosaukumu company(), tās automātiski tiks kartētas, lai jūs varētu vienkārši palaist $Permissions->has('order.read') vai $Permissions->has('company.read') un tas darbosies. To definēt ir ļoti grūti, tāpēc sekojiet man. Jums vienkārši jādara šādi:
Izveidojiet piekļuves tiesību klasi, ko vēlaties grupēt kopā.
class MyPermissions {
public function order(string $current_role, int $order_id = 0): array {
// kods piekļuves tiesību noteikšanai
return $permissions_array;
}
public function company(string $current_role, int $company_id): array {
// kods piekļuves tiesību noteikšanai
return $permissions_array;
}
}
Pēc tam padariet piekļuves tiesības atklājamas, izmantojot šo bibliotēku.
$Permissions = new \flight\Permission($current_role);
$Permissions->defineRulesFromClassMethods(MyApp\Permissions::class);
Flight::set('permissions', $Permissions);
Visbeidzot, izsauciet piekļuves tiesības savā kodā, lai pārbaudītu, vai lietotājam ir atļauts veikt noteiktu darbību.
class SomeController {
public function createOrder() {
if(Flight::get('permissions')->can('order.create') === false) {
die('You can\'t create an order. Sorry!');
}
}
}
Kešatmiņa
Lai iespējotu kešatmiņu, skatiet vienkāršo wruczak/phpfilecache bibliotēku. Zemāk ir piemērs tās iespējotai.
// šis $app var būt daļa no jūsu koda vai
// varat vienkārši nodot null un tas
// iegūs no Flight::app() konstruktorā
$app = Flight::app();
// Pašlaik tas pieņem failu kešatmiņu. Citi var viegli
// tikt pievienoti nākotnē.
$Cache = new Wruczek\PhpFileCache\PhpFileCache;
$Permissions = new \flight\Permission($current_role, $app, $Cache);
$Permissions->defineRulesFromClassMethods(MyApp\Permissions::class, 3600); // 3600 ir, cik sekundes to kešot. Atstājiet to tukšu, lai neizmantotu kešatmiņu
Un uz priekšu!
Awesome-plugins/simple_job_queue
Vienkārša Darba Rinda
Vienkārša Darba Rinda ir bibliotēka, ko var izmantot, lai apstrādātu darbus asinkroni. To var izmantot ar beanstalkd, MySQL/MariaDB, SQLite un PostgreSQL.
Instalēt
composer require n0nag0n/simple-job-queue
Izmantošana
Lai tas darbotos, jums nepieciešams veids, kā pievienot darbus rindai un veids, kā apstrādāt darbus (darbinieks). Tālāk ir sniegti piemēri, kā pievienot darbu rindai un kā apstrādāt darbu.
Pievienošana Flight
Šīs pievienošana Flight ir vienkārša un tiek veikta, izmantojot metodi register(). Tālāk ir piemērs, kā to pievienot Flight.
<?php
require 'vendor/autoload.php';
// Mainiet ['mysql'] uz ['beanstalkd'], ja vēlaties izmantot beanstalkd
Flight::register('queue', n0nag0n\Job_Queue::class, ['mysql'], function($Job_Queue) {
// ja jums jau ir PDO savienojums ar Flight::db();
$Job_Queue->addQueueConnection(Flight::db());
// vai, ja izmantojat beanstalkd/Pheanstalk
$pheanstalk = Pheanstalk\Pheanstalk::create('127.0.0.1');
$Job_Queue->addQueueConnection($pheanstalk);
});
Jauna darba pievienošana
Kad pievienojat darbu, jums jānorāda caurule (rinda). Tas ir salīdzināms ar kanālu RabbitMQ vai cauruli beanstalkd.
<?php
Flight::queue()->selectPipeline('send_important_emails');
Flight::queue()->addJob(json_encode([ 'something' => 'that', 'ends' => 'up', 'a' => 'string' ]));
Darbinieka palaišana
Šeit ir piemēra fails, kā palaist darbinieku.
<?php
require 'vendor/autoload.php';
$Job_Queue = new n0nag0n\Job_Queue('mysql');
// PDO savienojums
$PDO = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'user', 'pass');
$Job_Queue->addQueueConnection($PDO);
// vai, ja izmantojat beanstalkd/Pheanstalk
$pheanstalk = Pheanstalk\Pheanstalk::create('127.0.0.1');
$Job_Queue->addQueueConnection($pheanstalk);
$Job_Queue->watchPipeline('send_important_emails');
while(true) {
$job = $Job_Queue->getNextJobAndReserve();
// pielāgojiet, kā jums labāk guļ naktī (tikai datu bāzu rindām, beanstalkd šī instrukcija nav nepieciešama)
if(empty($job)) {
usleep(500000);
continue;
}
echo "Apstrādā {$job['id']}\n";
$payload = json_decode($job['payload'], true);
try {
$result = doSomethingThatDoesSomething($payload);
if($result === true) {
$Job_Queue->deleteJob($job);
} else {
// tas izņem to no gatavo rindu un ievieto citā rindā, kuru var paņemt un "izsist" vēlāk.
$Job_Queue->buryJob($job);
}
} catch(Exception $e) {
$Job_Queue->buryJob($job);
}
}
Ilgu Procesu Apstrāde ar Supervisord
Supervisord ir procesu kontroles sistēma, kas nodrošina, ka jūsu darbinieku procesi paliek aktīvi nepārtraukti. Šeit ir detalizētāks ceļvedis, kā to iestatīt ar savu Vienkāršo Darba Rindu darbinieku:
Supervisord instalēšana
# Uz Ubuntu/Debian
sudo apt-get install supervisor
# Uz CentOS/RHEL
sudo yum install supervisor
# Uz macOS ar Homebrew
brew install supervisor
Darbinieka skripta izveide
Vispirms saglabājiet savu darbinieka kodu veltītā PHP failā:
<?php
require 'vendor/autoload.php';
$Job_Queue = new n0nag0n\Job_Queue('mysql');
// PDO savienojums
$PDO = new PDO('mysql:dbname=your_database;host=127.0.0.1', 'username', 'password');
$Job_Queue->addQueueConnection($PDO);
// Iestatiet cauruli, kuru vēlaties uzraudzīt
$Job_Queue->watchPipeline('send_important_emails');
// Ierakstiet darbinieka sākumu
echo date('Y-m-d H:i:s') . " - Darbinieks uzsākts\n";
while(true) {
$job = $Job_Queue->getNextJobAndReserve();
if(empty($job)) {
usleep(500000); // Miega 0.5 sekundes
continue;
}
echo date('Y-m-d H:i:s') . " - Apstrādā darba {$job['id']}\n";
$payload = json_decode($job['payload'], true);
try {
$result = doSomethingThatDoesSomething($payload);
if($result === true) {
$Job_Queue->deleteJob($job);
echo date('Y-m-d H:i:s') . " - Darbs {$job['id']} veiksmīgi pabeigts\n";
} else {
$Job_Queue->buryJob($job);
echo date('Y-m-d H:i:s') . " - Darbs {$job['id']} neizdevās, aprakts\n";
}
} catch(Exception $e) {
$Job_Queue->buryJob($job);
echo date('Y-m-d H:i:s') . " - Izņēmums apstrādājot darbu {$job['id']}: {$e->getMessage()}\n";
}
}
Supervisord konfigurēšana
Izveidojiet konfigurācijas failu savam darbiniekam:
[program:email_worker]
command=php /path/to/worker.php
directory=/path/to/project
autostart=true
autorestart=true
startretries=3
stderr_logfile=/var/log/simple_job_queue_err.log
stdout_logfile=/var/log/simple_job_queue.log
user=www-data
numprocs=2
process_name=%(program_name)s_%(process_num)02d
Galvenās konfigurācijas opcijas:
command: Komanda, lai palaistu jūsu darbiniekudirectory: Darba direktorija darbiniekamautostart: Sākt automātiski, kad supervisord sākautorestart: Automātiski restartēt, ja process izbeidzasstartretries: Cik reizes mēģināt sākt, ja tas neizdodasstderr_logfile/stdout_logfile: Ieraksta failu atrašanās vietasuser: Sistēmas lietotājs, kas palaiž procesunumprocs: Darbinieku instanču skaitsprocess_name: Nosaukuma formāts vairākiem darbinieku procesiem
Darbinieku pārvaldība ar Supervisorctl
Pēc konfigurācijas izveides vai modificēšanas:
# Pārlādēt supervisor konfigurāciju
sudo supervisorctl reread
sudo supervisorctl update
# Kontrolēt konkrētus darbinieku procesus
sudo supervisorctl start email_worker:*
sudo supervisorctl stop email_worker:*
sudo supervisorctl restart email_worker:*
sudo supervisorctl status email_worker:*
Vairāku Cauruļu Palaišana
Vairāku cauruļu gadījumā izveidojiet atsevišķus darbinieku failus un konfigurācijas:
[program:email_worker]
command=php /path/to/email_worker.php
# ... citas konfigurācijas ...
[program:notification_worker]
command=php /path/to/notification_worker.php
# ... citas konfigurācijas ...
Uzraudzība un Ieraksti
Pārbaudiet ierakstus, lai uzraudzītu darbinieku aktivitāti:
# Apskatīt ierakstus
sudo tail -f /var/log/simple_job_queue.log
# Pārbaudīt statusu
sudo supervisorctl status
Šis iestatījums nodrošina, ka jūsu darba darbinieki turpina darboties, pat pēc avārijām, servera restartēšanas vai citiem jautājumiem, padarot jūsu rindu sistēmu uzticamu ražošanas vidēm.
Awesome-plugins/jwt
Firebase JWT - JSON Web Token autentifikācija
JWT (JSON Web Tokens) ir kompakts, URL-drošs veids, kā attēlot apgalvojumus starp jūsu lietojumprogrammu un klientu. Tie ir ideāli piemēroti bezstāvokļa API autentifikācijai — nav nepieciešama servera puses sesijas uzglabāšana! Šis ceļvedis parāda, kā integrēt Firebase JWT ar Flight drošai, tokenu balstītai autentifikācijai.
Apmeklējiet Github krātuvi, lai iegūtu pilnu dokumentāciju un detaļas.
Kas ir JWT?
JSON Web Token ir virkne, kas satur trīs daļas:
- Galvene: Metadati par tokenu (algoritms, tips)
- Ladējums: Jūsu dati (lietotāja ID, lomas, termiņš utt.)
- Paraksts: Kriptogrāfisks paraksts autentiskuma pārbaudei
Piemērs JWT: eyJ0eXAiOiJKV1QiLCJhbGc... (izskatās kā neskaidrs teksts, bet tas ir strukturēti dati!)
Kāpēc izmantot JWT?
- Bezstāvokļa: Nav nepieciešama servera puses sesijas uzglabāšana — ideāli piemērots mikroservisiem un API
- Izmērojams: Labi darbojas ar slodzes līdzsvarotājiem, jo nav sesijas saistības prasības
- Pārrobežu: Var izmantot dažādās domēnos un servisā
- Mobilajām ierīcēm draudzīgs: Lieliski piemērots mobilajām lietotnēm, kur cepumi var nedarboties labi
- Standartizēts: Nozares standarta pieeja (RFC 7519)
Instalēšana
Instalējiet, izmantojot Composer:
composer require firebase/php-jwt
Pamata izmantošana
Šeit ir ātrs piemērs JWT izveidei un pārbaudei:
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
// Jūsu slepenā atslēga (SAGLABĀJIE TO DROŠU!)
$secretKey = 'your-256-bit-secret-key-here-keep-it-safe';
// Izveidojiet tokenu
$payload = [
'user_id' => 123,
'username' => 'johndoe',
'role' => 'admin',
'iat' => time(), // Izsniegts
'exp' => time() + 3600 // Beigsies pēc 1 stundas
];
$jwt = JWT::encode($payload, $secretKey, 'HS256');
echo "Token: " . $jwt;
// Pārbaudiet un atšifrējiet tokenu
try {
$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));
echo "User ID: " . $decoded->user_id;
} catch (Exception $e) {
echo "Nederīgs tokens: " . $e->getMessage();
}
JWT starpprogrammatūra Flight (Ieteicamā pieeja)
Biežākais un noderīgākais veids, kā izmantot JWT ar Flight, ir kā starpprogrammatūru, lai aizsargātu jūsu API maršrutus. Šeit ir pilnīgs, ražošanai gatavs piemērs:
1. solis: Izveidojiet JWT starpprogrammatūras klasi
// app/middleware/JwtMiddleware.php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\SignatureInvalidException;
use flight\Engine;
class JwtMiddleware {
protected Engine $app;
protected string $secretKey;
public function __construct(Engine $app) {
$this->app = $app;
// Saglabājiet savu slepeno atslēgu app/config/config.php, nevis cietkodus!
$this->secretKey = $app->get('config')['jwt_secret'];
}
public function before(array $params) {
$authHeader = $this->app->request()->getHeader('Authorization');
// Pārbaudiet, vai pastāv Authorization galvene
if (empty($authHeader)) {
$this->app->jsonHalt(['error' => 'Nav nodrošināts autorizācijas tokens'], 401);
}
// Izvilciet tokenu no "Bearer <token>" formāta
if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) {
$this->app->jsonHalt(['error' => 'Nederīgs autorizācijas formāts. Izmantojiet: Bearer <token>'], 401);
}
$jwt = $matches[1];
try {
// Atšifrējiet un pārbaudiet tokenu
$decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256'));
// Saglabājiet lietotāja datus pieprasījumā, lai izmantotu maršruta apstrādātājos
$this->app->request()->data->user = $decoded;
} catch (ExpiredException $e) {
$this->app->jsonHalt(['error' => 'Tokens ir beidzies'], 401);
} catch (SignatureInvalidException $e) {
$this->app->jsonHalt(['error' => 'Nederīgs tokena paraksts'], 401);
} catch (Exception $e) {
$this->app->jsonHalt(['error' => 'Nederīgs tokens: ' . $e->getMessage()], 401);
}
}
}
2. solis: Reģistrējiet JWT slepeno atslēgu savā konfigurācijā
// app/config/config.php
return [
'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development'
];
// app/config/bootstrap.php vai index.php
// pārliecinieties, ka pievienojat šo rindu, ja vēlaties pakļaut konfigurāciju lietotnei
$app->set('config', $config);
Drošības piezīme: Nekad necietkodējiet savu slepeno atslēgu! Izmantojiet vides mainīgos ražošanā.
3. solis: Aizsargājiet savus maršrutus ar starpprogrammatūru
// Aizsargājiet vienu maršrutu
Flight::route('GET /api/user/profile', function() {
$user = Flight::request()->data->user; // Iestatīts ar starpprogrammatūru
Flight::json([
'user_id' => $user->user_id,
'username' => $user->username,
'role' => $user->role
]);
})->addMiddleware(JwtMiddleware::class);
// Aizsargājiet veselu maršrutu grupu (biežāk!)
Flight::group('/api', function() {
Flight::route('GET /users', function() { /* ... */ });
Flight::route('GET /posts', function() { /* ... */ });
Flight::route('POST /posts', function() { /* ... */ });
Flight::route('DELETE /posts/@id', function($id) { /* ... */ });
}, [ JwtMiddleware::class ]); // Visi maršruti šajā grupā ir aizsargāti!
Lai iegūtu vairāk detaļu par starpprogrammatūru, skatiet starpprogrammatūras dokumentāciju.
Biežas izmantošanas gadījumi
1. Pieteikšanās galapunkts (Tokenu ģenerēšana)
Izveidojiet maršrutu, kas ģenerē JWT pēc veiksmīgas autentifikācijas:
Flight::route('POST /api/login', function() {
$data = Flight::request()->data;
$username = $data->username ?? '';
$password = $data->password ?? '';
// Validējiet akreditācijas datus (piemērs — izmantojiet savu loģiku!)
$user = validateUserCredentials($username, $password);
if (!$user) {
Flight::jsonHalt(['error' => 'Nederīgas akreditācijas'], 401);
}
// Ģenerējiet JWT
$secretKey = Flight::get('config')['jwt_secret'];
$payload = [
'user_id' => $user->id,
'username' => $user->username,
'role' => $user->role,
'iat' => time(),
'exp' => time() + (60 * 60) // 1 stundas termiņš
];
$jwt = JWT::encode($payload, $secretKey, 'HS256');
Flight::json([
'success' => true,
'token' => $jwt,
'expires_in' => 3600
]);
});
function validateUserCredentials($username, $password) {
// Jūsu datubāzes meklēšana un paroles pārbaude šeit
// Piemērs:
$db = Flight::db();
$user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]);
if ($user && password_verify($password, $user['password_hash'])) {
return (object) [
'id' => $user['id'],
'username' => $user['username'],
'role' => $user['role']
];
}
return null;
}
2. Tokenu atjaunošanas plūsma
Implementējiet atjaunošanas tokenu sistēmu ilgstošām sesijām:
Flight::route('POST /api/login', function() {
// ... validējiet akreditācijas datus ...
$secretKey = Flight::get('config')['jwt_secret'];
$refreshSecret = Flight::get('config')['jwt_refresh_secret'];
// Īsa mūža piekļuves tokens (15 minūtes)
$accessToken = JWT::encode([
'user_id' => $user->id,
'type' => 'access',
'iat' => time(),
'exp' => time() + (15 * 60)
], $secretKey, 'HS256');
// Ilga mūža atjaunošanas tokens (7 dienas)
$refreshToken = JWT::encode([
'user_id' => $user->id,
'type' => 'refresh',
'iat' => time(),
'exp' => time() + (7 * 24 * 60 * 60)
], $refreshSecret, 'HS256');
Flight::json([
'access_token' => $accessToken,
'refresh_token' => $refreshToken,
'expires_in' => 900
]);
});
Flight::route('POST /api/refresh', function() {
$refreshToken = Flight::request()->data->refresh_token ?? '';
$refreshSecret = Flight::get('config')['jwt_refresh_secret'];
try {
$decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256'));
// Pārbaudiet, vai tas ir atjaunošanas tokens
if ($decoded->type !== 'refresh') {
Flight::jsonHalt(['error' => 'Nederīgs tokena tips'], 401);
}
// Ģenerējiet jaunu piekļuves tokenu
$secretKey = Flight::get('config')['jwt_secret'];
$accessToken = JWT::encode([
'user_id' => $decoded->user_id,
'type' => 'access',
'iat' => time(),
'exp' => time() + (15 * 60)
], $secretKey, 'HS256');
Flight::json([
'access_token' => $accessToken,
'expires_in' => 900
]);
} catch (Exception $e) {
Flight::jsonHalt(['error' => 'Nederīgs atjaunošanas tokens'], 401);
}
});
3. Lomu balstīta piekļuves kontrole
Paplašiniet savu starpprogrammatūru, lai pārbaudītu lietotāja lomas:
class JwtRoleMiddleware {
protected Engine $app;
protected array $allowedRoles;
public function __construct(Engine $app, array $allowedRoles = []) {
$this->app = $app;
$this->allowedRoles = $allowedRoles;
}
public function before(array $params) {
// Pieņemiet, ka JwtMiddleware jau darbojās un iestatīja lietotāja datus
$user = $this->app->request()->data->user ?? null;
if (!$user) {
$this->app->jsonHalt(['error' => 'Nepieciešama autentifikācija'], 401);
}
// Pārbaudiet, vai lietotājam ir nepieciešamā loma
if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) {
$this->app->jsonHalt(['error' => 'Nepietiekamas atļaujas'], 403);
}
}
}
// Lietojums: Administrātora tikai maršruts
Flight::route('DELETE /api/users/@id', function($id) {
// Dzēst lietotāja loģika
})->addMiddleware([
JwtMiddleware::class,
new JwtRoleMiddleware(Flight::app(), ['admin'])
]);
4. Publiskais API ar ātruma ierobežošanu pa lietotāju
Izmantojiet JWT, lai izsekotu un ierobežotu ātrumu lietotājiem bez sesijām:
class RateLimitMiddleware {
public function before(array $params) {
$user = Flight::request()->data->user ?? null;
$userId = $user ? $user->user_id : Flight::request()->ip;
$cacheKey = "rate_limit:$userId";
// Pārliecinieties, ka iestatāt kešošanas servisu app/config/services.php
$requests = Flight::cache()->get($cacheKey, 0);
if ($requests >= 100) { // 100 pieprasījumi stundā
Flight::jsonHalt(['error' => 'Ātruma ierobežojums pārsniegts'], 429);
}
Flight::cache()->set($cacheKey, $requests + 1, 3600);
}
}
Drošības labākās prakses
1. Izmantojiet stipras slepenās atslēgas
// Ģenerējiet drošu slepeno atslēgu (izpildiet vienreiz, saglabājiet .env failā)
$secretKey = base64_encode(random_bytes(32));
echo $secretKey; // Saglabājiet to savā .env failā!
2. Saglabājiet noslēpumus vides mainīgajos
// Nekad neiekļaujiet noslēpumus versiju kontrolē!
// Izmantojiet .env failu un bibliotēku, piemēram, vlucas/phpdotenv
// .env fails:
// JWT_SECRET=your-base64-encoded-secret-here
// JWT_REFRESH_SECRET=another-base64-encoded-secret-here
// Jūs varat arī izmantot app/config/config.php failu, lai saglabātu savus noslēpumus
// tikai pārliecinieties, ka konfigurācijas fails nav iekļauts versiju kontrolē
// return [
// 'jwt_secret' => 'your-base64-encoded-secret-here',
// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here',
// ];
// Savā lietotnē:
$secretKey = getenv('JWT_SECRET');
3. Iestatiet piemērotus termiņus
// Labā prakse: īsa mūža piekļuves tokeni
'exp' => time() + (15 * 60) // 15 minūtes
// Atjaunošanas tokeniem: ilgāks termiņš
'exp' => time() + (7 * 24 * 60 * 60) // 7 dienas
4. Izmantojiet HTTPS ražošanā
JWT vienmēr jāpārsūta pār HTTPS. Nekad nesūtiet tokenus pār vienkāršu HTTP ražošanā!
5. Validējiet tokena apgalvojumus
Vienmēr validējiet apgalvojumus, kas jums rūp:
$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));
// Pārbaude par termiņu tiek apstrādāta automātiski bibliotēkas
// Bet jūs varat pievienot pielāgotas validācijas:
if ($decoded->iat > time()) {
throw new Exception('Tokens izmantots pirms izsniegšanas');
}
if (isset($decoded->nbf) && $decoded->nbf > time()) {
throw new Exception('Tokens vēl nav derīgs');
}
6. Apsveriet tokenu melno sarakstu izrakstīšanai
Papildu drošībai uzturiet nederīgu tokenu melno sarakstu:
Flight::route('POST /api/logout', function() {
$authHeader = Flight::request()->getHeader('Authorization');
preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches);
$jwt = $matches[1];
// Izvilciet tokena termiņu
$decoded = Flight::request()->data->user;
$ttl = $decoded->exp - time();
// Saglabājiet kešā/redis līdz termiņam
Flight::cache()->set("blacklist:$jwt", true, $ttl);
Flight::json(['message' => 'Veiksmīgi izrakstījies']);
});
// Pievienojiet savai JwtMiddleware:
public function before(array $params) {
// ... izvilciet JWT ...
// Pārbaudiet melno sarakstu
if (Flight::cache()->get("blacklist:$jwt")) {
$this->app->jsonHalt(['error' => 'Tokens ir atcelts'], 401);
}
// ... pārbaudiet tokenu ...
}
Algoritmi un atslēgu tipi
Firebase JWT atbalsta vairākus algoritmus:
Simetriskie algoritmi (HMAC)
- HS256 (Ieteicams lielākajai daļai lietotņu): Izmanto vienu slepeno atslēgu
- HS384, HS512: Stiprāki varianti
$jwt = JWT::encode($payload, $secretKey, 'HS256');
$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));
Asimetriskie algoritmi (RSA/ECDSA)
- RS256, RS384, RS512: Izmanto publiskās/privātās atslēgu pārus
- ES256, ES384, ES512: Elipses līknes varianti
// Ģenerējiet atslēgas: openssl genrsa -out private.key 2048
// openssl rsa -in private.key -pubout -out public.key
$privateKey = file_get_contents('/path/to/private.key');
$publicKey = file_get_contents('/path/to/public.key');
// Kodējiet ar privāto atslēgu
$jwt = JWT::encode($payload, $privateKey, 'RS256');
// Atšifrējiet ar publisko atslēgu
$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
Kad izmantot RSA: Izmantojiet RSA, kad jums jāizplata publiskā atslēga pārbaudei (piem., mikroservisi, trešo pušu integrācijas). Vienai lietotnei HS256 ir vienkāršāks un pietiekams.
Traucējummeklēšana
"Beidzies tokens" kļūda
Jūsu tokena exp apgalvojums ir pagātnē. Izsniedziet jaunu tokenu vai implementējiet tokenu atjaunošanu.
"Paraksta pārbaude neizdevās"
- Jūs izmantojat citu slepeno atslēgu atšifrēšanai nekā kodēšanai
- Tokens ir modificēts
- Laika nobīde starp serveriem (pievienojiet buferi)
use Firebase\JWT\JWT;
JWT::$leeway = 60; // Atļaujiet 60 sekunžu laika nobīdi
$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));
Tokens netiek nosūtīts pieprasījumos
Pārliecinieties, ka jūsu klients nosūta Authorization galveni:
// JavaScript piemērs
fetch('/api/users', {
headers: {
'Authorization': 'Bearer ' + token
}
});
Metodes
Firebase JWT bibliotēka nodrošina šīs pamatmetodes:
JWT::encode(array $payload, string $key, string $alg): Izveido JWT no ladējumaJWT::decode(string $jwt, Key $key): Atšifrē un pārbauda JWTJWT::urlsafeB64Encode(string $input): Base64 URL-drošs kodējumsJWT::urlsafeB64Decode(string $input): Base64 URL-drošs atšifrējumsJWT::$leeway: Statiska īpašība, lai iestatītu laika buferi validācijai (sekundēs)
Kāpēc izmantot šo bibliotēku?
- Nozares standarts: Firebase JWT ir populārākā un visvairāk uzticamā JWT bibliotēka PHP
- Aktīva uzturēšana: Uztur Google/Firebase komanda
- Drošībai veltīta: Regulāri atjauninājumi un drošības labojumi
- Vienkārša API: Viegli saprast un ieviest
- Labu dokumentēšana: Plaša dokumentācija un kopienas atbalsts
- Elastīga: Atbalsta vairākus algoritmus un konfigurējamu opciju
Skatīt arī
- Firebase JWT Github krātuve
- JWT.io - Debugošana un atšifrēšana JWT
- RFC 7519 - Oficiālā JWT specifikācija
- Flight Starpprogrammatūras dokumentācija
- Flight Sesijas spraudnis - Tradicionālai sesiju balstītai autentifikācijai
Licence
Firebase JWT bibliotēka ir licencēta saskaņā ar BSD 3-Klauzulas licenci. Skatiet Github krātuvi detaļām.
Awesome-plugins/n0nag0n_wordpress
WordPress Integrācija: n0nag0n/wordpress-integration-for-flight-framework
Vai vēlaties izmantot Flight PHP savā WordPress vietnē? Šis spraudnis to padara vienkāršu! Ar n0nag0n/wordpress-integration-for-flight-framework, jūs varat palaist pilnu Flight lietotni tieši blakus jūsu WordPress instalācijai—ideāli piemērots pielāgotu API, mikropakalpojumu vai pat pilnvērtīgu lietotņu izveidošanai, neizejot no WordPress komforta.
Ko tas dara?
- Bezšuvju integrācija Flight PHP ar WordPress
- Novirza pieprasījumus uz Flight vai WordPress, pamatojoties uz URL modeļiem
- Organizējiet savu kodu ar kontrolieriem, modeļiem un skatiem (MVC)
- Vienkārši iestatiet ieteikto Flight mapju struktūru
- Izmantojiet WordPress datu bāzes savienojumu vai savu pašu
- Precīzi noregulējiet, kā Flight un WordPress mijiedarbojas
- Vienkārša administrācijas saskarne konfigurācijai
Instalācija
- Augšupielādējiet
flight-integrationmapi uz jūsu/wp-content/plugins/direktoriju. - Aktivizējiet spraudni WordPress administrācijā (Plugins izvēlnē).
- Dodieties uz Settings > Flight Framework, lai konfigurētu spraudni.
- Iestatiet piegādātāja ceļu uz savu Flight instalāciju (vai izmantojiet Composer, lai instalētu Flight).
- Konfigurējiet savu lietotnes mapes ceļu un izveidojiet mapju struktūru (spraudnis var palīdzēt ar to!).
- Sāciet veidot savu Flight lietotni!
Izmantošanas piemēri
Pamata maršrutēšanas piemērs
Jūsu app/config/routes.php failā:
Flight::route('GET /api/hello', function() {
Flight::json(['message' => 'Hello World!']);
});
Kontroliera piemērs
Izveidojiet kontrolieri app/controllers/ApiController.php:
namespace app\controllers;
use Flight;
class ApiController {
public function getUsers() {
// Jūs varat izmantot WordPress funkcijas iekš Flight!
$users = get_users();
$result = [];
foreach($users as $user) {
$result[] = [
'id' => $user->ID,
'name' => $user->display_name,
'email' => $user->user_email
];
}
Flight::json($result);
}
}
Pēc tam jūsu routes.php:
Flight::route('GET /api/users', [app\controllers\ApiController::class, 'getUsers']);
BUJ
J: Vai man jāzina Flight, lai izmantotu šo spraudni?
A: Jā, tas ir domāts izstrādātājiem, kuri vēlas izmantot Flight iekš WordPress. Ieteicams pamata zināšanas par Flight maršrutēšanu un pieprasījumu apstrādi.
J: Vai tas palēninās manu WordPress vietni?
A: Nē! Spraudnis apstrādā tikai pieprasījumus, kas atbilst jūsu Flight maršrutiem. Visi citi pieprasījumi tiek novirzīti uz WordPress kā parasti.
J: Vai es varu izmantot WordPress funkcijas savā Flight lietotnē?
A: Protams! Jums ir pilna piekļuve visām WordPress funkcijām, āķiem un globālajiem mainīgajiem no Flight maršrutiem un kontrolieriem.
J: Kā es varu izveidot pielāgotus maršrutus?
A: Definējiet savus maršrutus config/routes.php failā savā lietotnes mapē. Skatiet parauga failu, ko izveido mapju struktūras ģenerators, piemēriem.
Izmaiņu žurnāls
1.0.0
Sākotnējais izlaidums.
Papildus informācijai skatiet GitHub repo.
Awesome-plugins/ghost_session
Ghostff/Session
PHP Sesijas pārvaldnieks (nebloķējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl, lai pēc izvēles šifrētu/dešifrētu sesijas datus. Atbalsta File, MySQL, Redis un Memcached.
Noklikšķiniet here, lai apskatītu kodu.
Instalācija
Instalējiet ar composer.
composer require ghostff/session
Pamata konfigurācija
Jums nav nepieciešams neko nodot, lai izmantotu noklusējuma iestatījumus ar savu sesiju. Vairāk par iestatījumiem varat lasīt Github Readme.
use Ghostff\Session\Session;
require 'vendor/autoload.php';
$app = Flight::app();
$app->register('session', Session::class);
// viena lieta, ko atcerēties, ir tā, ka jums ir jāapstiprina sava sesija katrā lapas ielādē
// vai jums būs nepieciešams izpildīt auto_commit savā konfigurācijā.
Vienkāršs piemērs
Šeit ir vienkāršs piemērs, kā jūs varētu to izmantot.
Flight::route('POST /login', function() {
$session = Flight::session();
// veiciet savu pieteikšanās loģiku šeit
// validējiet paroli utt.
// ja pieteikšanās ir veiksmīga
$session->set('is_logged_in', true);
$session->set('user', $user);
// jebkurā laikā, kad jūs rakstāt uz sesiju, jums tas jāapstiprina apzināti.
$session->commit();
});
// Šo pārbaudi varētu veikt ierobežotās lapas loģikā vai ietīt ar vidējo programmu.
Flight::route('/some-restricted-page', function() {
$session = Flight::session();
if(!$session->get('is_logged_in')) {
Flight::redirect('/login');
}
// veiciet savu ierobežotās lapas loģiku šeit
});
// vidējās programmas versija
Flight::route('/some-restricted-page', function() {
// regulāra lapas loģika
})->addMiddleware(function() {
$session = Flight::session();
if(!$session->get('is_logged_in')) {
Flight::redirect('/login');
}
});
Sarežģītāks piemērs
Šeit ir sarežģītāks piemērs, kā jūs varētu to izmantot.
use Ghostff\Session\Session;
require 'vendor/autoload.php';
$app = Flight::app();
// iestatiet pielāgotu ceļu uz savu sesijas konfigurācijas failu kā pirmo argumentu
// vai dodiet tam pielāgotu masīvu
$app->register('session', Session::class, [
[
// ja vēlaties glabāt savu sesijas datus datu bāzē (labi, ja vēlaties kaut ko tādu kā "izrakstīties no visām ierīcēm" funkcionalitāti)
Session::CONFIG_DRIVER => Ghostff\Session\Drivers\MySql::class,
Session::CONFIG_ENCRYPT_DATA => true,
Session::CONFIG_SALT_KEY => hash('sha256', 'my-super-S3CR3T-salt'), // lūdzu, mainiet to uz kaut ko citu
Session::CONFIG_AUTO_COMMIT => true, // dariet to tikai tad, ja tas ir nepieciešams un/vai grūti izpildīt commit() savu sesiju.
// turklāt jūs varētu izdarīt Flight::after('start', function() { Flight::session()->commit(); });
Session::CONFIG_MYSQL_DS => [
'driver' => 'mysql', # Datu bāzes draiveris PDO dns, piem. (mysql:host=...;dbname=...)
'host' => '127.0.0.1', # Datu bāzes hosts
'db_name' => 'my_app_database', # Datu bāzes nosaukums
'db_table' => 'sessions', # Datu bāzes tabula
'db_user' => 'root', # Datu bāzes lietotājvārds
'db_pass' => '', # Datu bāzes parole
'persistent_conn'=> false, # Izvairieties no jaunas savienojuma izveidošanas katru reizi, kad skriptam jārunā ar datu bāzi, kas padara tīmekļa lietojumprogrammu ātrāku. ATRASTIET SEVI PAŠI
]
]
]);
Palīdzība! Mana sesijas dati netiek saglabāti!
Vai jūs iestatāt savus sesijas datus un tie netiek saglabāti starp pieprasījumiem? Jūs, iespējams, esat aizmirsis apstiprināt savus sesijas datus. Jūs varat to izdarīt, izsaucot $session->commit() pēc tam, kad esat iestatījis savus sesijas datus.
Flight::route('POST /login', function() {
$session = Flight::session();
// veiciet savu pieteikšanās loģiku šeit
// validējiet paroli utt.
// ja pieteikšanās ir veiksmīga
$session->set('is_logged_in', true);
$session->set('user', $user);
// jebkurā laikā, kad jūs rakstāt uz sesiju, jums tas jāapstiprina apzināti.
$session->commit();
});
Cits veids, kā to apiet, ir tad, kad jūs iestatāt savu sesijas servisu, jums ir jāiestata auto_commit uz true savā konfigurācijā. Tas automātiski apstiprinās jūsu sesijas datus pēc katra pieprasījuma.
$app->register('session', Session::class, [ 'path/to/session_config.php', bin2hex(random_bytes(32)) ], function(Session $session) {
$session->updateConfiguration([
Session::CONFIG_AUTO_COMMIT => true,
]);
}
);
Turklāt jūs varētu izdarīt Flight::after('start', function() { Flight::session()->commit(); });, lai apstiprinātu savus sesijas datus pēc katra pieprasījuma.
Dokumentācija
Apmeklējiet Github Readme pilnai dokumentācijai. Konfigurācijas opcijas ir labi dokumentētas noklusējuma_config.php failā pašā. Kods ir vienkārši saprotams, ja jūs gribētu to izpētīt pats.
Awesome-plugins/mcp
FlightPHP MCP Server
FlightPHP MCP Server nodrošina jebkuram MCP savietojamam AI kodēšanas asistentam tūlītēju, strukturētu piekļuvi visai FlightPHP dokumentācijai — maršrutizācijai, starpprogrammatūrai, spraudņiem, ceļvežiem un citam. Tā vietā, lai jūsu AI izdomātu API detaļas vai minētos metožu parakstus, tas iegūst īsto dokumentāciju pēc pieprasījuma. Nav nepieciešamas API atslēgas, nav nepieciešama instalēšana viesotajai versijai.
Apmeklējiet Github repository, lai iegūtu pilnu avota kodu un detaļas.
Ātrais starts
Serveris ir publiski viesots un gatavs lietošanai:
https://mcp.flightphp.com/mcp
Vienkārši pievienojiet šo URL jūsu AI kodēšanas paplašinājumam. Nav reģistrācijas, nav akreditācijas datu. Skatiet sadaļu IDE Configuration zemāk, lai iegūtu kopēšanas-līmēšanas konfigurācijas populārākajām rīkiem.
Ko tas dara
Pēc savienojuma jūsu AI asistents var:
- Pārlūkot visas pieejamās dokumentācijas — uzskaitīt katru galveno tēmu, ceļvedi un spraudņu lapu
- Iegūt jebkuru dokumentācijas lapu — iegūt pilnu saturu maršrutizācijai, starpprogrammatūrai, pieprasījumiem, drošībai un citam
- Meklēt spraudņu dokumentāciju — iegūt pilnu dokumentāciju ActiveRecord, Session, Tracy, Runway un visiem citiem oficiālajiem spraudņiem
- Sekot soli pa solim ceļvežiem — piekļūt pilniem soļu pa soļiem ceļvežiem blogu, REST API un testēto lietojumprogrammu izveidei
- Meklēt visā — atrast saistītās lapas visā galvenajā dokumentācijā, ceļvežos un spraudņos vienlaikus
Galvenie punkti
- Nulles uzstādīšana — viesotais serveris
https://mcp.flightphp.com/mcpneprasa instalēšanu vai API atslēgas. - Vienmēr aktuāls — serveris iegūst dokumentāciju tiešraidē no docs.flightphp.com, tāpēc tas vienmēr ir atjaunināts.
- Darbojas visur — jebkurš rīks, kas atbalsta MCP Streamable HTTP transportu, var savienoties.
- Pašviesojams — palaidiet savu instances ar PHP >= 8.1 un Composer, ja vēlaties.
IDE / AI Paplašinājuma konfigurācija
Serveris izmanto Streamable HTTP transportu. Izvēlieties savu paplašinājumu zemāk un ielīmējiet konfigurāciju.
Claude Code (CLI)
Palaidiet šādu komandu, lai pievienotu to savam projektam:
claude mcp add --transport http flightphp-docs https://mcp.flightphp.com/mcp
Vai pievienojiet manuāli sava projekta .mcp.json:
{
"mcpServers": {
"flightphp-docs": {
"type": "http",
"url": "https://mcp.flightphp.com/mcp"
}
}
}
GitHub Copilot (VS Code)
Pievienojiet .vscode/mcp.json savā darba telpā:
{
"servers": {
"flightphp-docs": {
"type": "http",
"url": "https://mcp.flightphp.com/mcp"
}
}
}
Kilo Code (VS Code)
Pievienojiet savam VS Code settings.json:
{
"kilocode.mcpServers": {
"flightphp-docs": {
"url": "https://mcp.flightphp.com/mcp",
"transport": "streamable-http"
}
}
}
Continue.dev (VS Code / JetBrains)
Pievienojiet ~/.continue/config.json:
{
"mcpServers": [
{
"name": "flightphp-docs",
"transport": {
"type": "http",
"url": "https://mcp.flightphp.com/mcp"
}
}
]
}
Pieejamie rīki
MCP serveris piedāvā šādus rīkus jūsu AI asistentam:
| Rīks | Apraksts |
|---|---|
list_docs_pages |
Uzskaita visas pieejamās galvenās dokumentācijas tēmas ar slugiem un aprakstiem |
get_docs_page |
Iegūst galvenās dokumentācijas lapu pēc tēmas slug (piem., routing, middleware, security) |
list_guide_pages |
Uzskaita visus pieejamos soli pa solim ceļvežus |
get_guide_page |
Iegūst pilnu ceļvedi pēc slug (piem., blog, unit-testing) |
list_plugin_pages |
Uzskaita visas pieejamās spraudņu un paplašinājumu lapas |
get_plugin_docs |
Iegūst pilnu spraudņu dokumentāciju pēc slug (piem., active-record, session, jwt) |
search_docs |
Meklē visā dokumentācijā, ceļvežos un spraudņos pēc atslēgvārda vai tēmas |
fetch_url |
Iegūst jebkuru lapu tieši pēc pilna docs.flightphp.com URL |
Pašviesojums
Vēlaties palaidiet savu instances? Jums būs nepieciešams PHP >= 8.1 un Composer.
git clone https://github.com/flightphp/mcp.git
cd mcp
composer install
php server.php
Serveris palaižas uz http://0.0.0.0:8890/mcp pēc noklusējuma. Atjauniniet savu IDE konfigurāciju, lai norādītu uz jūsu lokālo adresi:
{
"mcpServers": {
"flightphp-docs": {
"type": "http",
"url": "http://localhost:8890/mcp"
}
}
}Awesome-plugins/async
Async
Async ir mazs pakotnes Flight ietvaram, kas ļauj palaist jūsu Flight lietotnes asinhronos serveros un vidēs, piemēram, Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman utt. No kastes tas ietver adapterus Swoole un AdapterMan.
Mērķis: izstrādāt un atkļūdot ar PHP-FPM (vai iebūvēto serveri) un pārslēgties uz Swoole (vai citu asinhrono draiveri) ražošanā ar minimālām izmaiņām.
Prasības
- PHP 7.4 vai augstāka
- Flight ietvars 3.16.1 vai augstāka
- Swoole paplašinājums
Instalēšana
Instalējiet caur composer:
composer require flightphp/async
Ja plānojat palaist ar Swoole, instalējiet paplašinājumu:
# izmantojot pecl
pecl install swoole
# vai openswoole
pecl install openswoole
# vai ar pakotņu pārvaldnieku (Debian/Ubuntu piemērs)
sudo apt-get install php-swoole
Ātrs Swoole piemērs
Zemāk ir minimāla iestatīšana, kas parāda, kā atbalstīt gan PHP-FPM (vai iebūvēto serveri), gan Swoole, izmantojot to pašu koda bāzi.
Faili, kas būs nepieciešami jūsu projektā:
- index.php
- swoole_server.php
- SwooleServerDriver.php
index.php
Šis fails ir vienkāršs slēdzis, kas piespiež lietotni palaist PHP režīmā izstrādei.
// index.php
<?php
define('NOT_SWOOLE', true);
include 'swoole_server.php';
swoole_server.php
Šis fails inicializē jūsu Flight lietotni un sāks Swoole draiveri, kad NOT_SWOOLE nav definēts.
// swoole_server.php
<?php
require_once __DIR__ . '/vendor/autoload.php';
$app = Flight::app();
$app->route('/', function() use ($app) {
$app->json(['hello' => 'world']);
});
if (!defined('NOT_SWOOLE')) {
// Nepieciešams SwooleServerDriver klase, kad darbojas Swoole režīmā.
require_once __DIR__ . '/SwooleServerDriver.php';
Swoole\Runtime::enableCoroutine();
$Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app);
$Swoole_Server->start();
} else {
$app->start();
}
SwooleServerDriver.php
Īss draiveris, kas parāda, kā savienot Swoole pieprasījumus ar Flight, izmantojot AsyncBridge un Swoole adapterus.
// SwooleServerDriver.php
<?php
use flight\adapter\SwooleAsyncRequest;
use flight\adapter\SwooleAsyncResponse;
use flight\AsyncBridge;
use flight\Engine;
use Swoole\HTTP\Server as SwooleServer;
use Swoole\HTTP\Request as SwooleRequest;
use Swoole\HTTP\Response as SwooleResponse;
class SwooleServerDriver {
protected $Swoole;
protected $app;
public function __construct(string $host, int $port, Engine $app) {
$this->Swoole = new SwooleServer($host, $port);
$this->app = $app;
$this->setDefault();
$this->bindWorkerEvents();
$this->bindHttpEvent();
}
protected function setDefault() {
$this->Swoole->set([
'daemonize' => false,
'dispatch_mode' => 1,
'max_request' => 8000,
'open_tcp_nodelay' => true,
'reload_async' => true,
'max_wait_time' => 60,
'enable_reuse_port' => true,
'enable_coroutine' => true,
'http_compression' => false,
'enable_static_handler' => true,
'document_root' => __DIR__,
'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'],
'buffer_output_size' => 4 * 1024 * 1024,
'worker_num' => 4,
]);
$app = $this->app;
$app->map('stop', function (?int $code = null) use ($app) {
if ($code !== null) {
$app->response()->status($code);
}
});
}
protected function bindHttpEvent() {
$app = $this->app;
$AsyncBridge = new AsyncBridge($app);
$this->Swoole->on('Start', function(SwooleServer $server) {
echo "Swoole http server is started at http://127.0.0.1:9501\n";
});
$this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) {
$SwooleAsyncRequest = new SwooleAsyncRequest($request);
$SwooleAsyncResponse = new SwooleAsyncResponse($response);
$AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse);
$response->end();
gc_collect_cycles();
});
}
protected function bindWorkerEvents() {
$createPools = function() {
// izveidojiet darbinieka specifiskas savienojumu kopas šeit
};
$closePools = function() {
// aizveriet kopas / tīriet šeit
};
$this->Swoole->on('WorkerStart', $createPools);
$this->Swoole->on('WorkerStop', $closePools);
$this->Swoole->on('WorkerError', $closePools);
}
public function start() {
$this->Swoole->start();
}
}
Servera palaišana
- Izstrāde (PHP iebūvētais serveris / PHP-FPM):
- php -S localhost:8000 (vai pievienojiet -t public/ ja jūsu index ir public/)
- Ražošana (Swoole):
- php swoole_server.php
Padoms: Ražošanā izmantojiet reverso proxy (Nginx) Swoole priekšā, lai apstrādātu TLS, statiskos failus un slodzes līdzsvarošanu.
Konfigurācijas piezīmes
Swoole draiveris piedāvā vairākas konfigurācijas opcijas:
- worker_num: darbinieku procesu skaits
- max_request: pieprasījumi uz darbinieku pirms restartēšanas
- enable_coroutine: izmantojiet korutīnas vienlaicībai
- buffer_output_size: izvades bufera izmērs
Pielāgojiet šos, lai atbilstu jūsu resursiem un trafika modeļiem.
Kļūdu apstrāde
AsyncBridge pārvērš Flight kļūdas pareizās HTTP atbildēs. Jūs varat arī pievienot maršruta līmeņa kļūdu apstrādi:
$app->route('/*', function() use ($app) {
try {
// maršruta loģika
} catch (Exception $e) {
$app->response()->status(500);
$app->json(['error' => $e->getMessage()]);
}
});
AdapterMan un citas vidēs
AdapterMan tiek atbalstīts kā alternatīvs vidēs adapteris. Pakotne ir paredzēta pielāgošanai — pievienošana vai izmantošana citu adapteru parasti seko tam pašam modelim: pārveido servera pieprasījumu/atbildi par Flight pieprasījumu/atbildi caur AsyncBridge un vidēs specifiskajiem adapteriem.
Awesome-plugins/migrations
Migrācijas
Migrācija jūsu projektam uzrauga visus datu bāzes izmaiņas, kas saistītas ar jūsu projektu.
byjg/php-migration ir ļoti noderīga kodola bibliotēka, lai jūs varētu sākt.
Instalēšana
PHP bibliotēka
Ja vēlaties izmantot tikai PHP bibliotēku savā projektā:
composer require "byjg/migration"
Komandrindas interfeiss
Komandrindas interfeiss ir patstāvīgs un neprasa to instalēt kopā ar jūsu projektu.
Jūs varat instalēt globāli un izveidot simbolisko saiti.
composer require "byjg/migration-cli"
Lūdzu, apmeklējiet byjg/migration-cli, lai iegūtu vairāk informācijas par Migrācijas CLI.
Atbalstītās datu bāzes
| Datu bāze | Dzinējs | Savienojuma virkne |
|---|---|---|
| Sqlite | pdo_sqlite | sqlite:///path/to/file |
| MySql/MariaDb | pdo_mysql | mysql://lietotāja_vārds:parole@hostname:ports/datu_bāze |
| Postgres | pdo_pgsql | pgsql://lietotāja_vārds:parole@hostname:ports/datu_bāze |
| Sql Server | pdo_dblib, pdo_sysbase Linux | dblib://lietotāja_vārds:parole@hostname:ports/datu_bāze |
| Sql Server | pdo_sqlsrv Windows | sqlsrv://lietotāja_vārds:parole@hostname:ports/datu_bāze |
Kā tas darbojas?
Datu bāzes migrācija izmanto TĪRU SQL, lai pārvaldītu datu bāzes versijas.
Lai tas darbotos, jums nepieciešams:
- Izveidot SQL skriptus
- Pārvaldīt, izmantojot komandrindas vai API.
SQL skripti
Skripti ir sadalīti trīs skriptu grupās:
- BAZES skripts satur VISAS SQL komandas, lai izveidotu jaunu datu bāzi;
- UP skripti satur visas SQL migrācijas komandas, lai "paaugstinātu" datu bāzes versiju;
- DOWN skripti satur visas SQL migrācijas komandas, lai "samazinātu" vai atgrieztu datu bāzes versiju;
Skriptu direktorija ir:
<root dir>
|
+-- base.sql
|
+-- /migrations
|
+-- /up
|
+-- 00001.sql
+-- 00002.sql
+-- /down
|
+-- 00000.sql
+-- 00001.sql
- "base.sql" ir bāzes skripts
- "up" mape satur skriptus, lai migrētu uz augšu versiju.
Piemēram: 00002.sql ir skripts, lai pārvietotu datu bāzi no versijas '1' uz '2'. - "down" mape satur skriptus, lai migrētu uz leju versiju.
Piemēram: 00001.sql ir skripts, lai pārvietotu datu bāzi no versijas '2' uz '1'.
"down" mape ir opcionala.
Multi izstrādes vide
Ja strādājat ar vairākiem izstrādātājiem un vairākiem zara, ir grūti noteikt nākamo numuru.
Šajā gadījumā jums ir papildinājums "-dev" pēc versijas numura.
Skatiet scenāriju:
- Izstrādātājs 1 izveido zaru un visjaunākā versija ir, piemēram, 42.
- Izstrādātājs 2 izveido zaru vienlaikus un ir tāds pats datu bāzes versijas numurs.
Abos gadījumos izstrādātāji izveidos failu ar nosaukumu 43-dev.sql. Abi izstrādātāji pārskatīs UP un DOWN bez problēmām, un jūsu lokālā versija būs 43.
Bet izstrādātājs 1 apvieno jūsu izmaiņas un izveido gala versiju 43.sql (git mv 43-dev.sql 43.sql). Ja izstrādātājs 2 atjauninās jūsu vietējo zaru, viņam būs fails 43.sql (no izstrādātāja 1) un jūsu fails 43-dev.sql.
Ja viņš mēģina migrēt UP vai DOWN, migrācijas skripts uzrakstīs un brīdinās viņu, ka ir DIVAS versijas 43. Šajā gadījumā izstrādātājam 2 būs jāatjaunina jūsu fails uz 44-dev.sql un jāturpina strādāt līdz apvienojat jūsu izmaiņas un ģenerējat gala versiju.
PHP API izmantošana un integrēšana savos projektos
Pamatlietošana ir
- Izveidot savienojumu ar ConnectionManagement objektu. Vairāk informācijas skatiet "byjg/anydataset" komponentā.
- Izveidot migrācijas objektu ar šo savienojumu un mapi, kur atrodas SQL skripti.
- Izmantot pareizo komandu priekš "reset", "up" vai "down" migrācijas skriptiem.
Skatiet piemēru:
<?php
// Izveidojiet savienojuma URI
// Skatiet vairāk: https://github.com/byjg/anydataset#connection-based-on-uri
$connectionUri = new \ByJG\Util\Uri('mysql://migrateuser:migratepwd@localhost/migratedatabase');
// Reģistrējiet datu bāzi vai datu bāzes, kas var apstrādāt šo URI:
\ByJG\DbMigration\Migration::registerDatabase(\ByJG\DbMigration\Database\MySqlDatabase::class);
// Izveidojiet migrācijas instance
$migration = new \ByJG\DbMigration\Migration($connectionUri, '.');
// Pievienojiet atgriezenisko saiti progresam, lai saņemtu informāciju par izpildi
$migration->addCallbackProgress(function ($action, $currentVersion, $fileInfo) {
echo "$action, $currentVersion, ${fileInfo['description']}\n";
});
// Atjaunojiet datu bāzi, izmantojot "base.sql" skriptu
// un palaidiet VISUS esošos skriptus, lai paaugstinātu datu bāzes versiju līdz jaunākajai versijai
$migration->reset();
// Palaidiet VISUS esošos skriptus, lai paaugstinātu vai samazinātu datu bāzes versiju
// no pašreizējās versijas līdz $version numuram;
// Ja versijas numurs nav noteikts, migrējiet līdz pēdējai datu bāzes versijai
$migration->update($version = null);
Migrācijas objekts kontrolē datu bāzes versiju.
Izstrādājot versiju kontroli savā projektā
<?php
// Reģistrējiet datu bāzi vai datu bāzes, kas var apstrādāt šo URI:
\ByJG\DbMigration\Migration::registerDatabase(\ByJG\DbMigration\Database\MySqlDatabase::class);
// Izveidojiet migrācijas instance
$migration = new \ByJG\DbMigration\Migration($connectionUri, '.');
// Šī komanda izveidos versijas tabulu jūsu datu bāzē
$migration->createVersion();
Iegūstot pašreizējo versiju
<?php
$migration->getCurrentVersion();
Pievienojiet atgriezenisko saiti, lai kontrolētu progresu
<?php
$migration->addCallbackProgress(function ($command, $version, $fileInfo) {
echo "Veicot komandu: $command pie versijas $version - ${fileInfo['description']}, ${fileInfo['exists']}, ${fileInfo['file']}, ${fileInfo['checksum']}\n";
});
Iegūstot Db Dzinēja instanci
<?php
$migration->getDbDriver();
Lai to izmantotu, lūdzu, apmeklējiet: https://github.com/byjg/anydataset-db
Daļēju migrāciju novēršana (nav pieejama MySQL)
Daļēja migrācija ir tad, ja migrācijas skripts tiek pārtraukts procesa vidū kļūdas vai manuālas pārtraukšanas dēļ.
Migrācijas tabula būs ar statusu daļējs uz augšu vai daļējs uz leju, un to nepieciešams labot manuāli, pirms var atkārtoti migrēt.
Lai izvairītos no šīs situācijas, jūs varat norādīt, ka migrācija tiks izpildīta transakcijas kontekstā.
Ja migrācijas skripts neizdodas, transakcija tiks atcelta, un migrācijas tabula tiks iezīmēta kā pabeigta, un versija būs tūlītēji iepriekšējā versija pirms skripta, kas izraisīja kļūdu.
Lai šo funkciju aktivizētu, jums jāizsauc metode withTransactionEnabled, nododot true kā parametru:
<?php
$migration->withTransactionEnabled(true);
PIEZĪME: Šī funkcija nav pieejama MySQL, jo tas neatbalsta DDL komandas transakcijas ietvaros.
Ja jūs izmantosiet šo metodi ar MySQL, migrācija to klusi ignorēs.
Vairāk informācijas: https://dev.mysql.com/doc/refman/8.0/en/cannot-roll-back.html
Ieteikumi SQL migrāciju rakstīšanai Postgres
Par trigeru un SQL funkciju izveidi
-- DARI
CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
BEGIN
-- Pārbaudiet, vai ir norādīts empname un alga
IF NEW.empname IS NULL THEN
RAISE EXCEPTION 'empname nedrīkst būt null'; -- nav svarīgi, vai šie komentāri ir tukši vai nē
END IF; --
IF NEW.salary IS NULL THEN
RAISE EXCEPTION '% nedrīkst būt null alga', NEW.empname; --
END IF; --
-- Kas strādā pie mums, kad viņiem par to jāmaksā?
IF NEW.salary < 0 THEN
RAISE EXCEPTION '% nedrīkst būt negatīva alga', NEW.empname; --
END IF; --
-- Atcerieties, kurš izmainīja algu, kad
NEW.last_date := current_timestamp; --
NEW.last_user := current_user; --
RETURN NEW; --
END; --
$emp_stamp$ LANGUAGE plpgsql;
-- NEDARI
CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
BEGIN
-- Pārbaudiet, vai ir norādīts empname un alga
IF NEW.empname IS NULL THEN
RAISE EXCEPTION 'empname nedrīkst būt null';
END IF;
IF NEW.salary IS NULL THEN
RAISE EXCEPTION '% nedrīkst būt null alga', NEW.empname;
END IF;
-- Kas strādā pie mums, kad viņiem par to jāmaksā?
IF NEW.salary < 0 THEN
RAISE EXCEPTION '% nedrīkst būt negatīva alga', NEW.empname;
END IF;
-- Atcerieties, kurš izmainīja algu, kad
NEW.last_date := current_timestamp;
NEW.last_user := current_user;
RETURN NEW;
END;
$emp_stamp$ LANGUAGE plpgsql;
Tā kā PDO datu bāzes abstrakcijas slānis nevar izpildīt SQL komandu partijas, kad byjg/migration lasa migrācijas failu, tas ir jāizdala visus SQL faila saturus pie semikolu un jāizpilda komandas viena pa viena.
Tomēr ir viens veids, kā komanda var saturēt vairākas semikolas tās ķermenī: funkcijas.
Lai pareizi analizētu funkcijas, byjg/migration 2.1.0 sāka sadalīt migrācijas failus pēc semikola + EOL secības, nevis tikai pēc semikolas.
Šādā veidā, ja jūs pievienojat tukšu komentāru pēc katra iekšējā semikola funkcijas definīcijā, byjg/migration to varēs pareizi analizēt.
Diemžēl, ja jūs aizmirsīsiet pievienot kādu no šiem komentāriem, bibliotēka sadalīs CREATE FUNCTION paziņojumu multiple parts, un migrācija neizdosies.
Izvairieties no kolonnas rakstzīmes (:)
-- DARI
CREATE TABLE bookings (
booking_id UUID PRIMARY KEY,
booked_at TIMESTAMPTZ NOT NULL CHECK (CAST(booked_at AS DATE) <= check_in),
check_in DATE NOT NULL
);
-- NEDARI
CREATE TABLE bookings (
booking_id UUID PRIMARY KEY,
booked_at TIMESTAMPTZ NOT NULL CHECK (booked_at::DATE <= check_in),
check_in DATE NOT NULL
);
Tā kā PDO izmanto kolonnas rakstzīmi, lai prefixētu nosauktos parametrus sagatavotās komandas, tās izmantošana izraisa to, ka tas aptrūkst citos kontekstos.
Piemēram, PostgreSQL komandas var izmantot ::, lai konvertētu vērtības starp tipiem.
No otras puses, PDO to uztvers kā nederīgu nosauktu parametru nederīgā kontekstā un neizdosies, kad tas mēģinās to izpildīt.
Vienīgā veida, kā izlabot šo neatbilstību, ir pilnībā izvairīties no kolonnām (šajā gadījumā PostgreSQL ir alternatīva sintakse: CAST(value AS type)).
Izmantojiet SQL redaktoru
Visbeidzot, manuālas SQL migrāciju rakstīšana var būt nogurdinoša, taču to ir ievērojami vieglāk izdarīt, ja izmantojat redaktoru, kas spēj saprast SQL sintaksi, piedāvā pabeigšanu, introspektē jūsu pašreizējo datu bāzes shēmu un / vai automātiski formatē jūsu kodu.
Dažādu migrāciju apstrāde vienā shēmā
Ja jums ir jāizveido dažādi migrācijas skripti un versijas vienā shēmā, tas ir iespējams, bet tas ir ļoti riskanti un es neieteiktu to darīt.
Lai to izdarītu, jums jāizveido dažādas "migrācijas tabulas", nododot parametru konstruktora parametrā.
<?php
$migration = new \ByJG\DbMigration\Migration("db:/uri", "/path", true, "JAUNA_MIGRĀCIJAS_TABULAS_NOSAUKUMS");
Drošības apsvērumu dēļ šī funkcija nav pieejama komandrindā, bet jūs varat izmantot vides mainīgo MIGRATION_VERSION, lai glabātu nosaukumu.
Mēs patiešām iesakām neizmantot šo funkciju. Ieteikums ir viena migrācija vienai shēmā.
Vienības testu izpilde
Pamatvienības testus var izpildīt ar:
vendor/bin/phpunit
Datu bāzu testu izpilde
Lai veiktu integrācijas testus, jums jābūt datu bāzēm, kas darbojas. Mēs esam nodrošinājuši pamata docker-compose.yml, un jūs varat to izmantot, lai uzsāktu datu bāzes testēšanai.
Datu bāzu palaidīšana
docker-compose up -d postgres mysql mssql
Testu izpilde
vendor/bin/phpunit
vendor/bin/phpunit tests/SqliteDatabase*
vendor/bin/phpunit tests/MysqlDatabase*
vendor/bin/phpunit tests/PostgresDatabase*
vendor/bin/phpunit tests/SqlServerDblibDatabase*
vendor/bin/phpunit tests/SqlServerSqlsrvDatabase*
Pēc izvēles jūs varat iestatīt resursdatora un paroles iestatījumus, ko izmanto vienības testos.
export MYSQL_TEST_HOST=localhost # noklusējums uz localhost
export MYSQL_PASSWORD=newpassword # izmantojiet '.', ja vēlaties nulles paroli
export PSQL_TEST_HOST=localhost # noklusējums uz localhost
export PSQL_PASSWORD=newpassword # izmantojiet '.', ja vēlaties nulles paroli
export MSSQL_TEST_HOST=localhost # noklusējums uz localhost
export MSSQL_PASSWORD=Pa55word
export SQLITE_TEST_HOST=/tmp/test.db # noklusējums uz /tmp/test.dbAwesome-plugins/comment_template
CommentTemplate
CommentTemplate ir jaudīgs PHP veidņu dzinējs ar resursu kompilāciju, veidņu mantojumu un mainīgo apstrādi. Tas nodrošina vienkāršu, bet elastīgu veidu, kā pārvaldīt veidnes ar iebūvētu CSS/JS minimizāciju un kešošanu.
Funkcijas
- Veidņu mantojums: Izmantojiet izkārtojumus un iekļaujiet citas veidnes
- Resursu kompilācija: Automātiska CSS/JS minimizācija un kešošana
- Mainīgo apstrāde: Veidņu mainīgie ar filtrēšanu un komandām
- Base64 kodēšana: Iekšējie resursi kā datu URI
- Flight Framework integrācija: Neobligātā integrācija ar Flight PHP framework
Instalēšana
Instalējiet ar composer.
composer require knifelemon/comment-template
Pamata konfigurācija
Ir dažas pamata konfigurācijas opcijas, lai sāktu. Vairāk par tām var lasīt CommentTemplate Repo.
1. metode: Izmantojot atgriezeniskās saites funkciju
<?php
require_once 'vendor/autoload.php';
use KnifeLemon\CommentTemplate\Engine;
$app = Flight::app();
$app->register('view', Engine::class, [], function (Engine $engine) use ($app) {
// Saknes direktorija (kur ir index.php) - jūsu tīmekļa lietojumprogrammas dokumentu sakne
$engine->setPublicPath(__DIR__);
// Veidņu failu direktorija - atbalsta gan relatīvās, gan absolūtās ceļus
$engine->setSkinPath('views'); // Relatīvi pret publisko ceļu
// Kur tiks glabāti kompilētie resursi - atbalsta gan relatīvās, gan absolūtās ceļus
$engine->setAssetPath('assets'); // Relatīvi pret publisko ceļu
// Veidnes faila paplašinājums
$engine->setFileExtension('.php');
});
$app->map('render', function(string $template, array $data) use ($app): void {
echo $app->view()->render($template, $data);
});
2. metode: Izmantojot konstruktoru parametrus
<?php
require_once 'vendor/autoload.php';
use KnifeLemon\CommentTemplate\Engine;
$app = Flight::app();
// __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "")
$app->register('view', Engine::class, [
__DIR__, // publicPath - saknes direktorija (kur ir index.php)
'views', // skinPath - veidņu ceļš (atbalsta relatīvos/absolūtos)
'assets', // assetPath - kompilēto resursu ceļš (atbalsta relatīvos/absolūtos)
'.php' // fileExtension - veidnes faila paplašinājums
]);
$app->map('render', function(string $template, array $data) use ($app): void {
echo $app->view()->render($template, $data);
});
Ceļu konfigurācija
CommentTemplate nodrošina inteliģentu ceļu apstrādi gan relatīvajiem, gan absolūtajiem ceļiem:
Publiskais ceļš
Publiskais ceļš ir jūsu tīmekļa lietojumprogrammas saknes direktorija, parasti tur, kur atrodas index.php. Tas ir dokumentu saknes ceļš, no kura tīmekļa serveri pasniedz failus.
// Piemērs: ja jūsu index.php ir /var/www/html/myapp/index.php
$template->setPublicPath('/var/www/html/myapp'); // Saknes direktorija
// Windows piemērs: ja jūsu index.php ir C:\xampp\htdocs\myapp\index.php
$template->setPublicPath('C:\\xampp\\htdocs\\myapp');
Veidņu ceļa konfigurācija
Veidņu ceļš atbalsta gan relatīvos, gan absolūtos ceļus:
$template = new Engine();
$template->setPublicPath('/var/www/html/myapp'); // Saknes direktorija (kur ir index.php)
// Relatīvie ceļi - automātiski apvienoti ar publisko ceļu
$template->setSkinPath('views'); // → /var/www/html/myapp/views/
$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/
// Absolūtie ceļi - izmantoti kā ir (Unix/Linux)
$template->setSkinPath('/var/www/templates'); // → /var/www/templates/
$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/
// Windows absolūtie ceļi
$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\
$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/
// UNC ceļi (Windows tīkla koplietošana)
$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\
Resursu ceļa konfigurācija
Resursu ceļš arī atbalsta gan relatīvos, gan absolūtos ceļus:
// Relatīvie ceļi - automātiski apvienoti ar publisko ceļu
$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/
$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/
// Absolūtie ceļi - izmantoti kā ir (Unix/Linux)
$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/
$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/
// Windows absolūtie ceļi
$template->setAssetPath('C:\\www\\static'); // → C:\www\static\
$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/
// UNC ceļi (Windows tīkla koplietošana)
$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\
Inteliģenta ceļu noteikšana:
- Relatīvie ceļi: Nav vadītājsimbolu (
/,\) vai disketes burtiem - Unix absolūtie: Sākas ar
/(piem.,/var/www/assets) - Windows absolūtie: Sākas ar diska burtu (piem.,
C:\www,D:/assets) - UNC ceļi: Sākas ar
\\(piem.,\\server\share)
Kā tas darbojas:
- Visi ceļi tiek automātiski atrisināti, balstoties uz tipu (relatīvs pret absolūto)
- Relatīvie ceļi tiek apvienoti ar publisko ceļu
@cssun@jsizveido minimizētus failus:{resolvedAssetPath}/css/vai{resolvedAssetPath}/js/@assetkopē atsevišķus failus uz:{resolvedAssetPath}/{relativePath}@assetDirkopē direktorijas uz:{resolvedAssetPath}/{relativePath}- Inteliģenta kešošana: faili tiek kopēti tikai tad, kad avots ir jaunāks par mērķi
Tracy atkļūdotāja integrācija
CommentTemplate ietver integrāciju ar Tracy Debugger izstrādes reģistrēšanai un atkļūdošanai.

Instalācija
composer require tracy/tracy
Lietošana
<?php
use KnifeLemon\CommentTemplate\Engine;
use Tracy\Debugger;
// Iespējot Tracy (jāizsauc pirms jebkuras izvades)
Debugger::enable(Debugger::DEVELOPMENT);
Flight::set('flight.content_length', false);
// Veidnes pārrakstīšana
$app->register('view', Engine::class, [], function (Engine $builder) use ($app) {
$builder->setPublicPath($app->get('flight.views.topPath'));
$builder->setAssetPath($app->get('flight.views.assetPath'));
$builder->setSkinPath($app->get('flight.views.path'));
$builder->setFileExtension($app->get('flight.views.extension'));
});
$app->map('render', function(string $template, array $data) use ($app): void {
echo $app->view()->render($template, $data);
});
$app->start();
Atkļūdošanas paneļa funkcijas
CommentTemplate pievieno pielāgotu paneli Tracy atkļūdošanas joslai ar četrām cilnēm:
- Overview: Konfigurācija, veiktspējas metrika un skaitītāji
- Assets: CSS/JS kompilācijas detaļas ar saspiešanas proporcijām
- Variables: Oriģinālās un pārveidotās vērtības ar lietotajiem filtriem
- Timeline: Hronoloģisks visu veidņu operāciju skats
Kas tiek reģistrēts
- Veidņu renderēšana (sākums/beigas, ilgums, izkārtojumi, importi)
- Aktīvu kompilācija (CSS/JS faili, izmēri, saspiešanas proporcijas)
- Mainīgo apstrāde (oriģinālās/pārveidotās vērtības, filtri)
- Aktīvu operācijas (base64 kodēšana, failu kopēšana)
- Veiktspējas metrika (ilgums, atmiņas izmantošana)
Piezīme: Nulles ietekme uz veiktspēju, ja Tracy nav instalēts vai ir atspējots.
Skatiet pilnīgu darba piemēru ar Flight PHP.
Veidnes direktīvas
Izkārtojuma mantojums
Izmantojiet izkārtojumus, lai izveidotu kopīgu struktūru:
layout/global_layout.php:
<!DOCTYPE html>
<html>
<head>
<title>{$title}</title>
</head>
<body>
<!--@contents-->
</body>
</html>
view/page.php:
<!--@layout(layout/global_layout)-->
<h1>{$title}</h1>
<p>{$content}</p>
Resursu pārvaldība
CSS faili
<!--@css(/css/styles.css)--> <!-- Minimizēts un kešots -->
<!--@cssSingle(/css/critical.css)--> <!-- Atsevišķs fails, ne minimizēts -->
JavaScript faili
CommentTemplate atbalsta dažādas JavaScript ielādes stratēģijas:
<!--@js(/js/script.js)--> <!-- Minimizēts, ielādēts apakšā -->
<!--@jsAsync(/js/analytics.js)--> <!-- Minimizēts, ielādēts apakšā ar async -->
<!--@jsDefer(/js/utils.js)--> <!-- Minimizēts, ielādēts apakšā ar defer -->
<!--@jsTop(/js/critical.js)--> <!-- Minimizēts, ielādēts galvā -->
<!--@jsTopAsync(/js/tracking.js)--> <!-- Minimizēts, ielādēts galvā ar async -->
<!--@jsTopDefer(/js/polyfill.js)--> <!-- Minimizēts, ielādēts galvā ar defer -->
<!--@jsSingle(/js/widget.js)--> <!-- Atsevišķs fails, ne minimizēts -->
<!--@jsSingleAsync(/js/ads.js)--> <!-- Atsevišķs fails, ne minimizēts, async -->
<!--@jsSingleDefer(/js/social.js)--> <!-- Atsevišķs fails, ne minimizēts, defer -->
Resursu direktīvas CSS/JS failos
CommentTemplate arī apstrādā resursu direktīvas CSS un JavaScript failos kompilācijas laikā:
CSS piemērs:
/* Jūsu CSS failos */
/* Fontu definīcijas */
@font-face {
font-family: 'CustomFont';
src: url('<!--@asset(fonts/custom.woff2)-->') format('woff2');
}
.background-image {
background: url('<!--@asset(images/bg.jpg)-->');
}
.inline-icon {
background: url('<!--@base64(icons/star.svg)-->');
}
JavaScript piemērs:
/* Jūsu JS failos */
const fontUrl = '<!--@asset(fonts/custom.woff2)-->';
const imageData = '<!--@base64(images/icon.png)-->';
Base64 kodēšana
<!--@base64(images/logo.png)--> <!-- Iekšēji kā datu URI -->
Piemērs:
<!-- Iekšēji mazas bildes kā datu URI ātrākai ielādei -->
<img src="<!--@base64(images/logo.png)-->" alt="Logo">
<div style="background-image: url('<!--@base64(icons/star.svg)-->');">
Mazs ikona kā fons
</div>
Resursu kopēšana
<!--@asset(images/photo.jpg)--> <!-- Kopē atsevišķu resursu uz publisko direktoriju -->
<!--@assetDir(assets)--> <!-- Kopē visu direktoriju uz publisko direktoriju -->
Piemērs:
<!-- Kopē un atsaucas uz statiskajiem resursiem -->
<img src="<!--@asset(images/hero-banner.jpg)-->" alt="Hero Banner">
<a href="<!--@asset(documents/brochure.pdf)-->" download>Lejupielādēt Brošūru</a>
<!-- Kopē visu direktoriju (fonti, ikonas utt.) -->
<!--@assetDir(assets/fonts)-->
<!--@assetDir(assets/icons)-->
Veidnes iekļaušana
<!--@import(components/header)--> <!-- Iekļauj citas veidnes -->
Piemērs:
<!-- Iekļauj atkārtoti izmantojamas sastāvdaļas -->
<!--@import(components/header)-->
<main>
<h1>Sveiki mūsu vietnē</h1>
<!--@import(components/sidebar)-->
<div class="content">
<p>Galvenais saturs šeit...</p>
</div>
</main>
<!--@import(components/footer)-->
Mainīgo apstrāde
Pamata mainīgie
<h1>{$title}</h1>
<p>{$description}</p>
Mainīgo filtri
{$title|upper} <!-- Pārvērš uz lielajiem burtiem -->
{$content|lower} <!-- Pārvērš uz mazajiem burtiem -->
{$html|striptag} <!-- Noņem HTML atzīmes -->
{$text|escape} <!-- Ekrēno HTML -->
{$multiline|nl2br} <!-- Pārvērš jaunas rindas uz <br> -->
{$html|br2nl} <!-- Pārvērš <br> atzīmes uz jaunām rindām -->
{$description|trim} <!-- Apgriež tukšumus -->
{$subject|title} <!-- Pārvērš uz virsraksta gadījumu -->
Mainīgo komandas
{$title|default=Default Title} <!-- Iestata noklusējuma vērtību -->
{$name|concat= (Admin)} <!-- Apvieno tekstu -->
Mainīgo komandas
{$content|striptag|trim|escape} <!-- Ķēžu vairākus filtrus -->
Komentāri
Veidnes komentāri tiek pilnībā noņemti no izvades un neparādīsies galīgajā HTML:
{* Tas ir vienrindas veidnes komentārs *}
{*
Tas ir vairākrindu
veidnes komentārs
kas aptver vairākas rindas
*}
<h1>{$title}</h1>
{* Debug komentārs: pārbauda, vai title mainīgais darbojas *}
<p>{$content}</p>
Piezīme: Veidnes komentāri {* ... *} atšķiras no HTML komentāriem <!-- ... -->. Veidnes komentāri tiek noņemti apstrādes laikā un nekad nenonāk pārlūkprogrammā.
Piemēra projekta struktūra
project/
├── source/
│ ├── layouts/
│ │ └── default.php
│ ├── components/
│ │ ├── header.php
│ │ └── footer.php
│ ├── css/
│ │ ├── bootstrap.min.css
│ │ └── custom.css
│ ├── js/
│ │ ├── app.js
│ │ └── bootstrap.min.js
│ └── homepage.php
├── public/
│ └── assets/ # Ģenerētie resursi
│ ├── css/
│ └── js/
└── vendor/Awesome-plugins/easy_query
EasyQuery
knifelemon/easy-query ir viegls, plūstošs SQL vaicājumu veidotājs, kas ģenerē SQL un parametrus sagatavotiem vaicājumiem. Darbojas ar SimplePdo.
Funkcijas
- 🔗 Plūstoša API - Ķēžu metodes lasāmu vaicājumu veidošanai
- 🛡️ SQL Injekciju Aizsardzība - Automātiska parametru saistīšana ar sagatavotiem vaicājumiem
- 🔧 Neapstrādāta SQL Atbalsts - Ievietojiet neapstrādātas SQL izteiksmes ar
raw() - 📝 Vairāki Vaicājumu Veidi - SELECT, INSERT, UPDATE, DELETE, COUNT
- 🔀 JOIN Atbalsts - Iekšējie, kreisās un labās savienojumi ar segvārdiem
- 🎯 Uzlaboti Nosacījumi - LIKE, IN, NOT IN, BETWEEN, salīdzinājuma operatori
- 🌐 Datu Bāzes Neatkarīgs - Atgriež SQL + parametrus, izmantojiet ar jebkuru DB savienojumu
- 🪶 Viegls - Minimāla pēda bez atkarībām
Instalēšana
composer require knifelemon/easy-query
Ātrais Sākums
use KnifeLemon\EasyQuery\Builder;
$q = Builder::table('users')
->select(['id', 'name', 'email'])
->where(['status' => 'active'])
->orderBy('created_at DESC')
->limit(10)
->build();
// Izmantojiet ar Flight's SimplePdo
$users = Flight::db()->fetchAll($q['sql'], $q['params']);
Saprašana build()
build() metode atgriež masīvu ar sql un params. Šī atdalīšana uztur jūsu datu bāzi drošu, izmantojot sagatavotus vaicājumus.
$q = Builder::table('users')
->where(['email' => 'user@example.com'])
->build();
// Atgriež:
// [
// 'sql' => 'SELECT * FROM users WHERE email = ?',
// 'params' => ['user@example.com']
// ]
Vaicājumu Veidi
SELECT
// Izvēlieties visas kolonnas
$q = Builder::table('users')->build();
// SELECT * FROM users
// Izvēlieties specifiskas kolonnas
$q = Builder::table('users')
->select(['id', 'name', 'email'])
->build();
// SELECT id, name, email FROM users
// Ar tabulas segvārdu
$q = Builder::table('users')
->alias('u')
->select(['u.id', 'u.name'])
->build();
// SELECT u.id, u.name FROM users AS u
INSERT
$q = Builder::table('users')
->insert([
'name' => 'John Doe',
'email' => 'john@example.com',
'status' => 'active'
])
->build();
// INSERT INTO users SET name = ?, email = ?, status = ?
Flight::db()->runQuery($q['sql'], $q['params']);
$userId = Flight::db()->lastInsertId();
UPDATE
$q = Builder::table('users')
->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')])
->where(['id' => 123])
->build();
// UPDATE users SET status = ?, updated_at = ? WHERE id = ?
Flight::db()->runQuery($q['sql'], $q['params']);
DELETE
$q = Builder::table('users')
->delete()
->where(['id' => 123])
->build();
// DELETE FROM users WHERE id = ?
Flight::db()->runQuery($q['sql'], $q['params']);
COUNT
$q = Builder::table('users')
->count()
->where(['status' => 'active'])
->build();
// SELECT COUNT(*) AS cnt FROM users WHERE status = ?
$count = Flight::db()->fetchField($q['sql'], $q['params']);
WHERE Nosacījumi
Vienkārša Vienlīdzība
$q = Builder::table('users')
->where(['id' => 123, 'status' => 'active'])
->build();
// WHERE id = ? AND status = ?
Salīdzinājuma Operatori
$q = Builder::table('users')
->where([
'age' => ['>=', 18],
'score' => ['<', 100],
'name' => ['!=', 'admin']
])
->build();
// WHERE age >= ? AND score < ? AND name != ?
LIKE
$q = Builder::table('users')
->where(['name' => ['LIKE', '%john%']])
->build();
// WHERE name LIKE ?
IN / NOT IN
// IN
$q = Builder::table('users')
->where(['id' => ['IN', [1, 2, 3, 4, 5]]])
->build();
// WHERE id IN (?, ?, ?, ?, ?)
// NOT IN
$q = Builder::table('users')
->where(['status' => ['NOT IN', ['banned', 'deleted']]])
->build();
// WHERE status NOT IN (?, ?)
BETWEEN
$q = Builder::table('products')
->where(['price' => ['BETWEEN', [100, 500]]])
->build();
// WHERE price BETWEEN ? AND ?
OR Nosacījumi
Izmantojiet orWhere(), lai pievienotu OR grupētus nosacījumus:
$q = Builder::table('users')
->where(['status' => 'active'])
->orWhere([
'role' => 'admin',
'permissions' => ['LIKE', '%manage%']
])
->build();
// WHERE status = ? AND (role = ? OR permissions LIKE ?)
JOIN
Iekšējais JOIN
$q = Builder::table('users')
->alias('u')
->select(['u.id', 'u.name', 'p.title'])
->innerJoin('posts', 'u.id = p.user_id', 'p')
->build();
// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id
Kreisais JOIN
$q = Builder::table('users')
->alias('u')
->select(['u.name', 'o.total'])
->leftJoin('orders', 'u.id = o.user_id', 'o')
->build();
// ... LEFT JOIN orders AS o ON u.id = o.user_id
Vairāki JOIN
$q = Builder::table('orders')
->alias('o')
->select(['o.id', 'u.name AS customer', 'p.title AS product'])
->innerJoin('users', 'o.user_id = u.id', 'u')
->leftJoin('order_items', 'o.id = oi.order_id', 'oi')
->leftJoin('products', 'oi.product_id = p.id', 'p')
->where(['o.status' => 'completed'])
->build();
Sakārtošana, Grupēšana un Ierobežojumi
ORDER BY
$q = Builder::table('users')
->orderBy('created_at DESC')
->build();
// ORDER BY created_at DESC
GROUP BY
$q = Builder::table('orders')
->select(['user_id', 'COUNT(*) as order_count'])
->groupBy('user_id')
->build();
// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id
LIMIT un OFFSET
$q = Builder::table('users')
->limit(10)
->build();
// LIMIT 10
$q = Builder::table('users')
->limit(10, 20) // limit, offset
->build();
// LIMIT 10 OFFSET 20
Neapstrādātas SQL Izteiksmes
Izmantojiet raw(), kad nepieciešamas SQL funkcijas vai izteiksmes, kas nedrīkst tikt apstrādātas kā saistīti parametri.
Pamata Neapstrādāts
$q = Builder::table('users')
->update([
'login_count' => Builder::raw('login_count + 1'),
'updated_at' => Builder::raw('NOW()')
])
->where(['id' => 123])
->build();
// SET login_count = login_count + 1, updated_at = NOW()
Neapstrādāts ar Saistītiem Parametriem
$q = Builder::table('orders')
->update([
'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10])
])
->where(['id' => 1])
->build();
// SET total = COALESCE(subtotal, ?) + ?
// params: [0, 10, 1]
Neapstrādāts WHERE (Apakšvaicājums)
$q = Builder::table('products')
->where([
'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')]
])
->build();
// WHERE price > (SELECT AVG(price) FROM products)
Droši Identifikatori Lietotāja Ievadei
Kad kolonnu nosaukumi nāk no lietotāja ievades, izmantojiet safeIdentifier(), lai novērstu SQL injekcijas:
$sortColumn = $_GET['sort']; // piem., 'created_at'
$safeColumn = Builder::safeIdentifier($sortColumn);
$q = Builder::table('users')
->orderBy($safeColumn . ' DESC')
->build();
// Ja lietotājs mēģina: "name; DROP TABLE users--"
// Izmet InvalidArgumentException
rawSafe Lietotāja Norādītiem Kolonnu Nosaukumiem
$userColumn = $_GET['aggregate_column'];
$q = Builder::table('orders')
->select([
Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total'
])
->build();
// Validē kolonnu nosaukumu, izmet izņēmumu, ja nederīgs
Brīdinājums: Nekad neiekļaujiet lietotāja ievadi tieši
raw(). Vienmēr izmantojiet saistītus parametrus vaisafeIdentifier().
Vaicājuma Veidotāja atkārtota Izmantošana
Notīrīšanas Metodes
Notīriet specifiskas daļas, lai atkārtoti izmantotu veidotāju:
$query = Builder::table('users')
->select(['id', 'name'])
->where(['status' => 'active'])
->orderBy('created_at DESC');
// Pirmais vaicājums
$q1 = $query->limit(10)->build();
// Notīriet un atkārtoti izmantojiet
$query->clearWhere()->clearLimit();
// Otrais vaicājums ar atšķirīgiem nosacījumiem
$q2 = $query
->where(['status' => 'pending'])
->limit(5)
->build();
Pieejamās Notīrīšanas Metodes
| Metode | Apraksts |
|---|---|
clearWhere() |
Notīra WHERE nosacījumus un parametrus |
clearSelect() |
Atstata SELECT kolonnas uz noklusējuma '*' |
clearJoin() |
Notīra visus JOIN pantus |
clearGroupBy() |
Notīra GROUP BY pantu |
clearOrderBy() |
Notīra ORDER BY pantu |
clearLimit() |
Notīra LIMIT un OFFSET |
clearAll() |
Atstata veidotāju uz sākotnējo stāvokli |
Piemērs ar Lapināšanu
$baseQuery = Builder::table('users')
->select(['id', 'name', 'email'])
->where(['status' => 'active'])
->orderBy('created_at DESC');
// Iegūstiet kopējo skaitu
$countQuery = clone $baseQuery;
$countResult = $countQuery->clearSelect()->count()->build();
$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']);
// Iegūstiet lapinātos rezultātus
$page = 1;
$perPage = 20;
$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build();
$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']);
Dinamiska Vaicājuma Veidošana
$query = Builder::table('products')->alias('p');
if (!empty($categoryId)) {
$query->where(['p.category_id' => $categoryId]);
}
if (!empty($minPrice)) {
$query->where(['p.price' => ['>=', $minPrice]]);
}
if (!empty($maxPrice)) {
$query->where(['p.price' => ['<=', $maxPrice]]);
}
if (!empty($searchTerm)) {
$query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]);
}
$result = $query->orderBy('p.created_at DESC')->limit(20)->build();
$products = Flight::db()->fetchAll($result['sql'], $result['params']);
Pilns FlightPHP Piemērs
use KnifeLemon\EasyQuery\Builder;
// Lietotāju saraksts ar lapināšanu
Flight::route('GET /users', function() {
$page = (int) (Flight::request()->query['page'] ?? 1);
$perPage = 20;
$q = Builder::table('users')
->select(['id', 'name', 'email', 'created_at'])
->where(['status' => 'active'])
->orderBy('created_at DESC')
->limit($perPage, ($page - 1) * $perPage)
->build();
$users = Flight::db()->fetchAll($q['sql'], $q['params']);
Flight::json(['users' => $users, 'page' => $page]);
});
// Lietotāja izveide
Flight::route('POST /users', function() {
$data = Flight::request()->data;
$q = Builder::table('users')
->insert([
'name' => $data->name,
'email' => $data->email,
'created_at' => Builder::raw('NOW()')
])
->build();
Flight::db()->runQuery($q['sql'], $q['params']);
Flight::json(['id' => Flight::db()->lastInsertId()]);
});
// Lietotāja atjaunināšana
Flight::route('PUT /users/@id', function($id) {
$data = Flight::request()->data;
$q = Builder::table('users')
->update([
'name' => $data->name,
'email' => $data->email,
'updated_at' => Builder::raw('NOW()')
])
->where(['id' => $id])
->build();
Flight::db()->runQuery($q['sql'], $q['params']);
Flight::json(['success' => true]);
});
// Lietotāja dzēšana
Flight::route('DELETE /users/@id', function($id) {
$q = Builder::table('users')
->delete()
->where(['id' => $id])
->build();
Flight::db()->runQuery($q['sql'], $q['params']);
Flight::json(['success' => true]);
});
API Atsauce
Statiskās Metodes
| Metode | Apraksts |
|---|---|
Builder::table(string $table) |
Izveido jaunu veidotāja instanci tabulai |
Builder::raw(string $sql, array $bindings = []) |
Izveido neapstrādātu SQL izteiksmi |
Builder::rawSafe(string $expr, array $identifiers, array $bindings = []) |
Neapstrādāta izteiksme ar drošu identifikatora aizstāšanu |
Builder::safeIdentifier(string $identifier) |
Validē un atgriež drošu kolonnas/tabula nosaukumu |
Instanču Metodes
| Metode | Apraksts |
|---|---|
alias(string $alias) |
Iestata tabulas segvārdu |
select(string\|array $columns) |
Iestata kolonnas izvēlei (noklusējums: '*') |
where(array $conditions) |
Pievieno WHERE nosacījumus (AND) |
orWhere(array $conditions) |
Pievieno OR WHERE nosacījumus |
join(string $table, string $condition, string $alias, string $type) |
Pievieno JOIN pantu |
innerJoin(string $table, string $condition, string $alias) |
Pievieno Iekšējo JOIN |
leftJoin(string $table, string $condition, string $alias) |
Pievieno Kreisais JOIN |
groupBy(string $groupBy) |
Pievieno GROUP BY pantu |
orderBy(string $orderBy) |
Pievieno ORDER BY pantu |
limit(int $limit, int $offset = 0) |
Pievieno LIMIT un OFFSET |
count(string $column = '*') |
Iestata vaicājumu uz COUNT |
insert(array $data) |
Iestata vaicājumu uz INSERT |
update(array $data) |
Iestata vaicājumu uz UPDATE |
delete() |
Iestata vaicājumu uz DELETE |
build() |
Veido un atgriež ['sql' => ..., 'params' => ...] |
get() |
Aliasam build() |
Tracy Debugger Integrācija
EasyQuery automātiski integrējas ar Tracy Debugger, ja instalēts. Nav nepieciešama iestatīšana!
composer require tracy/tracy
use Tracy\Debugger;
Debugger::enable();
// Visi vaicājumi automātiski tiek reģistrēti Tracy panelī
$q = Builder::table('users')->where(['status' => 'active'])->build();
Tracy panelis rāda:
- Kopējo vaicājumu skaitu un sadalījumu pēc veida
- Ģenerēto SQL (sinakses izcelts)
- Parametru masīvu
- Vaicājuma detaļas (tabula, where, joins utt.)
Pilnai dokumentācijai apmeklējiet GitHub repozitoriju.
Awesome-plugins/twig
Twig
Twig ir elastīgs, ātrs un drošs PHP veidņu dzinējs. Tā ir veidņu valoda, ko izmanto Symfony un daudzi citi projekti, kas nozīmē, ka mākslīgā intelekta kodēšanas rīki un lielākā daļa PHP izstrādātāju jau labi zina tās sintaksi. Twig kompilē veidnes uz optimizētu PHP, automātiski aizsargā izvadi pēc noklusējuma (lieliski XSS aizsardzībai) un ir viegli paplašināms ar filtriem, funkcijām un paplašinājumiem.
Instalācija
Instalējiet ar composer.
composer require twig/twig
Pamata konfigurācija
Ir dažas pamata konfigurācijas opcijas, lai sāktu darbu. Vairāk par tām var lasīt Twig dokumentācijā.
require 'vendor/autoload.php';
$app = Flight::app();
$app->map('render', function(string $template, array $data): void {
$loader = new \Twig\Loader\FilesystemLoader(Flight::get('flight.views.path'));
$twig = new \Twig\Environment($loader, [
// Kur Twig glabā kompilētās veidnes
'cache' => __DIR__ . '/../cache/twig',
// Pārkompilēt veidnes, kad mainās avots (ērti izstrādes laikā)
'auto_reload' => true,
]);
echo $twig->render($template, $data);
});
Twig reģistrēšana kā skata klasi
Ja vēlaties atkārtoti izmantot vienu Twig vidi (ieteicams ražošanai), reģistrējiet to un norādiet render uz to:
require 'vendor/autoload.php';
$app = Flight::app();
$app->register('view', \Twig\Environment::class, [
new \Twig\Loader\FilesystemLoader($app->get('flight.views.path')),
[
'cache' => __DIR__ . '/../cache/twig',
'auto_reload' => true,
],
]);
$app->map('render', function(string $template, array $data): void {
echo Flight::view()->render($template, $data);
});
Vienkāršs izkārtojuma piemērs
Šeit ir vienkāršs izkārtojuma faila piemērs. Šis ir fails, kas tiks izmantots, lai ietītu visas jūsu citas skatnes.
{# app/views/layout.twig #}
<!doctype html>
<html lang="en">
<head>
<title>{% if title %}{{ title }} - {% endif %}My App</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<nav>
{# jūsu navigācijas elementi šeit #}
</nav>
</header>
<div id="content">
{# Šeit ir burvība #}
{% block content %}{% endblock %}
</div>
<div id="footer">
© Copyright
</div>
</body>
</html>
Un tagad mums ir jūsu fails, kas tiks renderēts šajā satura blokā:
{# app/views/home.twig #}
{# Tas saka Twig, ka šis fails ir "iekšpusē" layout.twig failā #}
{% extends 'layout.twig' %}
{# Tas ir saturs, kas tiks renderēts izkārtojumā satura blokā #}
{% block content %}
<h1>Home Page</h1>
<p>Welcome to my app!</p>
{% endblock %}
Tad, kad renderējat to savā funkcijā vai kontrolierī, jūs darītu kaut ko līdzīgu šim:
// vienkāršs maršruts
Flight::route('/', function () {
Flight::render('home.twig', [
'title' => 'Home Page'
]);
});
// vai ja izmantojat kontrolieri
Flight::route('/', [HomeController::class, 'index']);
// HomeController.php
class HomeController
{
public function index()
{
Flight::render('home.twig', [
'title' => 'Home Page'
]);
}
}
Skatiet Twig dokumentāciju lai iegūtu vairāk informācijas par to, kā izmantot Twig pilnā potenciālā!
Atkļūdošana
Twig nāk ar Atkļūdošanas paplašinājumu, kas pievieno dump() funkciju, ko varat izmantot veidnēs. Iespējojiet to tikai izstrādes laikā:
$app->register('view', \Twig\Environment::class, [
new \Twig\Loader\FilesystemLoader($app->get('flight.views.path')),
[
'cache' => __DIR__ . '/../cache/twig',
'debug' => true, // nepieciešams dump() funkcijai
'auto_reload' => true,
],
], function (\Twig\Environment $twig): void {
$twig->addExtension(new \Twig\Extension\DebugExtension());
});
Tad veidnē:
{{ dump(user) }}
Jūs varat arī savienot Twig ar Tracy PHP līmeņa atkļūdošanai. Veidņu līmeņa metrikām (renderēšanas laiks, atmiņa, kuras veidnes/bloki darbināti), izmantojiet izvēles Twig paneli flightphp/tracy-extensions: nododiet Twig\Profiler\Profile kā twig_profile uz TracyExtensionLoader. Izvēles TwigTracyExtension atklāj {{ dump() }} / {{ bdump() }} / {{ dumpe() }} veidnēs, kad Tracy ir ieslēgts.
Drošības piezīme
Twig automātiski aizsargā izvadi pēc noklusējuma, kas palīdz aizsargāt pret XSS uzbrukumiem. Dodiet priekšroku {{ variable }} tekstam. Izmantojiet tikai |raw filtru, kad jūs apzināti uzticaties HTML saturam (piemēram, sanitizēts markdown, ko jūs jau apstrādājāt servera pusē).
Awesome-plugins/session
FlightPHP Sesija - Viegls failu balstīts sesijas pārvaldnieks
Tas ir viegls, failu balstīts sesijas pārvaldnieka spraudnis Flight PHP Framework. Tas nodrošina vienkāršu, bet spēcīgu risinājumu sesiju pārvaldībai, ar iespējām kā nesekojošas sesijas lasīšanas, izvēles šifrēšanu, automātisku apstiprināšanu un testēšanas režīmu attīstībai. Sesijas dati tiek glabāti failos, padarot to ideālu lietojumprogrammām, kurām nav nepieciešama datubāze.
Ja vēlaties izmantot datubāzi, pārbaudiet ghostff/session spraudni, kas satur daudzas no šīm pašām iespējām, bet ar datubāzes aizmuguri.
Apmeklējiet Github repozitoriju pilnam avota kodam un detaļām.
Instalēšana
Instalējiet spraudni caur Composer:
composer require flightphp/session
Pamata lietošana
Lūk, vienkāršs piemērs, kā izmantot flightphp/session spraudni jūsu Flight lietojumprogrammā:
require 'vendor/autoload.php';
use flight\Session;
$app = Flight::app();
// Reģistrē sesijas servisu
$app->register('session', Session::class);
// Piemērs maršrutam ar sesijas lietošanu
Flight::route('/login', function() {
$session = Flight::session();
$session->set('user_id', 123);
$session->set('username', 'johndoe');
$session->set('is_admin', false);
echo $session->get('username'); // Izvada: johndoe
echo $session->get('preferences', 'default_theme'); // Izvada: default_theme
if ($session->get('user_id')) {
Flight::json(['message' => 'Lietotājs ir pieteicies!', 'user_id' => $session->get('user_id')]);
}
});
Flight::route('/logout', function() {
$session = Flight::session();
$session->clear(); // Notīra visas sesijas datus
Flight::json(['message' => 'Izlogojies veiksmīgi']);
});
Flight::start();
Galvenie punkti
- Nesekojošas: Pēc noklusējuma izmanto
read_and_closesesijas sākšanai, novēršot sesijas bloķēšanas problēmas. - Automātiska apstiprināšana: Ieslēgta pēc noklusējuma, tāpēc izmaiņas tiek saglabātas automātiski izslēgšanās brīdī, ja vien nav atslēgta.
- Failu glabāšana: Sesijas tiek glabātas sistēmas pagaidu direktorijā zem
/flight_sessionspēc noklusējuma.
Konfigurācija
Jūs varat pielāgot sesijas pārvaldnieku, nododot masīvu ar opcijām reģistrējot:
// Jā, tas ir dubults masīvs :)
$app->register('session', Session::class, [ [
'save_path' => '/custom/path/to/sessions', // Direktorija sesijas failiem
'prefix' => 'myapp_', // Priekša sesijas failiem
'encryption_key' => 'a-secure-32-byte-key-here', // Ieslēgt šifrēšanu (32 baiti ieteikti AES-256-CBC)
'auto_commit' => false, // Atslēgt automātisko apstiprināšanu manuālai kontrolei
'start_session' => true, // Sākt sesiju automātiski (pēc noklusējuma: true)
'test_mode' => false, // Ieslēgt testēšanas režīmu attīstībai
'serialization' => 'json', // Serializācijas metode: 'json' (pēc noklusējuma) vai 'php' (legacy)
] ]);
Konfigurācijas opcijas
| Opcija | Apraksts | Noklusētā vērtība |
|---|---|---|
save_path |
Direktorija, kur glabājas sesijas faili | sys_get_temp_dir() . '/flight_sessions' |
prefix |
Priekša saglabātajam sesijas failam | sess_ |
encryption_key |
Atslēga AES-256-CBC šifrēšanai (izvēles) | null (bez šifrēšanas) |
auto_commit |
Automātiski saglabāt sesijas datus izslēgšanās brīdī | true |
start_session |
Sākt sesiju automātiski | true |
test_mode |
Darboties testēšanas režīmā bez ietekmēšanas uz PHP sesijām | false |
test_session_id |
Pielāgota sesijas ID testēšanas režīmam (izvēles) | Nejauši ģenerēta, ja nav iestatīta |
serialization |
Serializācijas metode: 'json' (pēc noklusējuma, droša) vai 'php' (legacy, atļauj objektus) | 'json' |
Serializācijas režīmi
Pēc noklusējuma šī bibliotēka izmanto JSON serializāciju sesijas datiem, kas ir droša un novērš PHP objektu iesūkšanās ievainojamības. Ja jums ir nepieciešams glabāt PHP objektus sesijā (nav ieteicams lielākumam app), jūs varat izvēlēties legacy PHP serializāciju:
'serialization' => 'json'(pēc noklusējuma):- Tiek atļautas tikai masīvi un primitīvi dati sesijas datos.
- Drošāka: imūna pret PHP objektu iesūkšanos.
- Faili tiek priekšēji ar
J(vienkāršs JSON) vaiF(šifrēts JSON).
'serialization' => 'php':- Atļauj glabāt PHP objektus (lietojiet ar uzmanību).
- Faili tiek priekšēji ar
P(vienkārša PHP serializācija) vaiE(šifrēta PHP serializācija).
Piezīme: Ja izmantojat JSON serializāciju, mēģinot glabāt objektu, tiks izraisīta izņēmuma kļūda.
Paplašināta lietošana
Manuāla apstiprināšana
Ja atslēdzat automātisko apstiprināšanu, jums ir manuāli jāapstiprina izmaiņas:
$app->register('session', Session::class, ['auto_commit' => false]);
Flight::route('/update', function() {
$session = Flight::session();
$session->set('key', 'value');
$session->commit(); // Skaidri saglabā izmaiņas
});
Sesijas drošība ar šifrēšanu
Ieslēdziet šifrēšanu sensitīviem datiem:
$app->register('session', Session::class, [
'encryption_key' => 'your-32-byte-secret-key-here'
]);
Flight::route('/secure', function() {
$session = Flight::session();
$session->set('credit_card', '4111-1111-1111-1111'); // Šifrēts automātiski
echo $session->get('credit_card'); // Dekodēts pie saņemšanas
});
Sesijas atjaunošana
Atjaunojiet sesijas ID drošībai (piemēram, pēc pieteikšanās):
Flight::route('/post-login', function() {
$session = Flight::session();
$session->regenerate(); // Jauns ID, saglabā datus
// VAI
$session->regenerate(true); // Jauns ID, dzēš vecos datus
});
Middleware piemērs
Aizsargājiet maršrutus ar sesijas balstītu autentifikāciju:
Flight::route('/admin', function() {
Flight::json(['message' => 'Laipni lūgts admin panelī']);
})->addMiddleware(function() {
$session = Flight::session();
if (!$session->get('is_admin')) {
Flight::halt(403, 'Piekļuve liegta');
}
});
Tas ir tikai vienkāršs piemērs, kā to izmantot middleware. Vairāk detalizētam piemēram, skatiet middleware dokumentāciju.
Metodes
Session klase nodrošina šādas metodes:
set(string $key, $value): Glabā vērtību sesijā.get(string $key, $default = null): Iegūst vērtību, ar izvēles noklusējumu, ja atslēga neeksistē.delete(string $key): Noņem specifisku atslēgu no sesijas.clear(): Dzēš visus sesijas datus, bet saglabā to pašu faila nosaukumu sesijai.commit(): Saglabā pašreizējos sesijas datus failu sistēmā.id(): Atgriež pašreizējo sesijas ID.regenerate(bool $deleteOldFile = false): Atjauno sesijas ID, ieskaitot jauna sesijas faila izveidošanu, saglabājot visus vecos datus un vecais fails paliek sistēmā. Ja$deleteOldFileirtrue, vecais sesijas fails tiek dzēsts.destroy(string $id): Iznīcina sesiju pēc ID un dzēš sesijas failu no sistēmas. Tas ir daļa noSessionHandlerInterfaceun$idir nepieciešams. Tipiska lietošana būtu$session->destroy($session->id()).getAll(): Atgriež visus datus no pašreizējās sesijas.
Visas metodes izņemot get() un id() atgriež Session instanci ķēdes izveidošanai.
Kāpēc izmantot šo spraudni?
- Viegls: Nav ārēju atkarību — tikai faili.
- Nesekojošas: Izvairās no sesijas bloķēšanas ar
read_and_closepēc noklusējuma. - Drošs: Atbalsta AES-256-CBC šifrēšanu sensitīviem datiem.
- Fleksibls: Automātiska apstiprināšana, testēšanas režīms un manuālas kontroles opcijas.
- Flight-Native: Izveidots specifiski Flight framework.
Tehniskās detaļas
- Glabāšanas formāts: Sesijas faili tiek priekšēji ar
sess_un glabāti konfigurētajāsave_path. Faila satura priekši:J: Vienkāršs JSON (pēc noklusējuma, bez šifrēšanas)F: Šifrēts JSON (pēc noklusējuma ar šifrēšanu)P: Vienkārša PHP serializācija (legacy, bez šifrēšanas)E: Šifrēta PHP serializācija (legacy ar šifrēšanu)
- Šifrēšana: Izmanto AES-256-CBC ar nejaušu IV katrai sesijas rakstīšanai, kad tiek norādīta
encryption_key. Šifrēšana darbojas gan JSON, gan PHP serializācijas režīmos. - Serializācija: JSON ir pēc noklusējuma un drošākā metode. PHP serializācija pieejama legacy/uzlabotai lietošanai, bet ir mazāk droša.
- Atkritumu savākšana: Ietver PHP
SessionHandlerInterface::gc()veco sesiju tīrīšanai.
Dalība
Ieteikumi ir laipni gaidīti! Forkojiet repozitoriju, veiciet izmaiņas un iesniedziet pull request. Ziņojiet par kļūdām vai ieteikumiām caur Github issue tracker.
Licence
Šis spraudnis ir licencēts zem MIT Licence. Skatiet Github repozitoriju detaļām.
Awesome-plugins/runway
Runway
Runway ir CLI lietotne, kas palīdz pārvaldīt jūsu Flight lietotnes. Tā var ģenerēt kontrolierus, parādīt visas maršrutus, palaist AI iestatīšanas palīgus, migrācijas (skeletonā) un vēl vairāk. Tā ir balstīta uz izcilo adhocore/php-cli bibliotēku.
Klikšķiniet šeit, lai skatītu kodu.
Scaffolding komandas ir apzināti saskaņotas ar oficiālo skeleton, lai AI kodēšanas rīki un cilvēki katru reizi iegūtu vienādus ceļus, vārdu telpas un konstruktora injekcijas stilu.
Instalācija
Instalējiet ar composer.
composer require flightphp/runway
Skeleton jau atkarīgs no Runway; izmantojiet php runway no projekta saknes.
Pamata konfigurācija
Pirmo reizi palaižot Runway, tas mēģinās atrast runway konfigurāciju app/config/config.php caur 'runway' atslēgu.
<?php
// app/config/config.php
return [
'runway' => [
'app_root' => 'app/',
'public_root' => 'public/',
// neobligāti; skeleton arī izmanto index_root publiskajai ieejai
'index_root' => 'public/index.php',
],
];
PIEZĪME - Sākot ar v1.2.0,
.runway-config.jsonir novecojis par labuapp/config/config.php. Migrējiet arphp runway config:migrate, kad atjaunināt vecākus projektus. Skeleton joprojām var izveidot nelielu.runway-config.jsoncreate-project laikā saderībai; turpmāk dodiet priekšrokurunwayatslēgaiconfig.php.
Projekta saknes noteikšana
Runway ir pietiekami gudrs, lai noteiktu jūsu projekta sakni, pat ja to palaižat no apakšdirektorijas. Tas meklē indikatorus, piemēram, composer.json, .git vai app/config/config.php, lai noteiktu, kur atrodas projekta sakne. Tas nozīmē, ka Runway komandas varat palaist no jebkuras vietas savā projektā!
Lietošana
Runway ir vairākas komandas, kuras varat izmantot Flight lietotnes pārvaldīšanai. Ir divi vienkārši veidi, kā izmantot Runway.
- Ja izmantojat skeleton projektu, varat palaist
php runway [komanda]no sava projekta saknes. - Ja izmantojat Runway kā composer instalētu pakotni, varat palaist
vendor/bin/runway [komanda]no sava projekta saknes.
Komandu saraksts
Visu pieejamo komandu sarakstu varat apskatīt, palaižot php runway komandu.
php runway
Paļaujieties tikai uz komandām, kas faktiski parādās šajā sarakstā jūsu instalācijā (pamata Runway komandas pret projektu specifiskām, piemēram, skeleton migrate).
Komandas palīdzība
Jebkurai komandai varat nodot --help karodziņu, lai iegūtu vairāk informācijas par to, kā izmantot komandu.
php runway routes --help
php runway make:controller --help
Šeit ir daži piemēri:
Kontroliera ģenerēšana
make:controller veido kontroliera skeletu, kas atbilst oficiālajam skeleton izkārtojumam:
| Ceļš | app/Controller/{Nosaukums}.php |
| Vārdu telpa | App\Controller |
| Stils | flight\Engine konstruktora injekcija (bez Flight:: klases ķermenī) |
php runway make:controller MyController
# → app/Controller/MyController.php
# namespace App\Controller;
Paredzamās formas piemērs (vienkāršots):
<?php
declare(strict_types=1);
namespace App\Controller;
use flight\Engine;
class MyController
{
protected Engine $app;
public function __construct(Engine $app)
{
$this->app = $app;
}
public function index(): void
{
// piem. $this->app->render('…', […]);
}
}
Reģistrējiet to ar klases izsaucamajam, lai Dice varētu izveidot kontrolieri:
// app/config/routes.php
use App\Controller\MyController;
$router->get('/mine', [MyController::class, 'index']);
Kāpēc šis izkārtojums? Mapes reģistram jāatbilst vārdu telpai (Controller nevis controllers) Composer PSR-4 Linux sistēmām — skatiet Autoloadēšanu. Tas pats ceļš ir tas, ko root un scoped AGENTS.md faili saka AI rīkiem izmantot, lai ģenerētie un rokām rakstītie kontrolieri paliktu identiski.
Vecākā dokumentācijā un kopienas projektos dažreiz tika izmantots
app/controllers/unapp\controllers. Tas joprojām ir derīgs, ja jūsu kokā joprojām tiek izmantotas mazie burti mapēm. Jauni skeleton projekti un pašreizējāmake:controllerizvade izmantoapp/Controller/+App\Controller.
Active Record modeļa ģenerēšana
Vispirms pārliecinieties, ka esat instalējis Active Record spraudni.
php runway make:record users
Oficiālajā skeleton modeļi atrodas app/Model/ ar vārdu telpu App\Model, un DB savienojums ir SimplePdo (injicējiet to vai nododiet ActiveRecord konstruktoram). Ģenerētie failu nosaukumi/vārdu telpas seko Runway pašreizējiem noklusējumiem un jūsu runway konfigurācijai — dodiet priekšroku jaunu modeļu saskaņošanai ar App\Model, lai tie atbilstu autoloadēšanai un AGENTS.md.
Oficiālā skeleton posts demonstrācijas modelim atbilstošs piemērs:
<?php
declare(strict_types=1);
namespace App\Model;
use flight\ActiveRecord;
/**
* @property int $id
* @property string $title
* // …
*/
class Post extends ActiveRecord
{
protected array $relations = [];
public function __construct($databaseConnection)
{
parent::__construct($databaseConnection, 'posts');
}
}
Ja vecāks ģenerators joprojām izvada app/records / app\records, varat saglabāt šo konvenciju mantojuma lietotnēs vai pārvietot failus uz app/Model/ un atjaunināt vārdu telpu, lai atbilstu mapes reģistram.
Migrācijas (skeleton)
Oficiālais skeleton nodrošina projekta komandu (atklātu no app/commands/), piemēram:
php runway migrate
Migrācijas ir SQL faili zem migrations/ (piemēram, YYYYMMDDHHMMSS_apraksts.sql SQLite un …_apraksts.mysql.sql MySQL), izvēlēti no jūsu datu bāzes draivera konfigurācijas / vides. Precīzi karodziņi un uzvedība ir noteikta šajā projekta komandā — palaidiet php runway migrate --help savā lietotnē.
AI palīgi
Runway atklāj AI orientētas komandas, kas tiek izmantotas ar AI un izstrādātāja pieredzi:
php runway ai:init
php runway ai:generate-instructions
Tās saglabā LLM akreditācijas datus un ģenerē projekta instrukcijas (galvenokārt AGENTS.md). Skeletonā uzskatiet AGENTS.md (un scoped kopijas zem app/) plus SECURITY.md par patiesības avotu aģentiem.
Visu maršrutu parādīšana
Tas parādīs visus maršrutus, kas pašlaik ir reģistrēti ar Flight.
php runway routes
Ja vēlaties skatīt tikai specifiskus maršrutus, varat nodot karodziņu maršrutu filtrēšanai.
# Parādīt tikai GET maršrutus
php runway routes --get
# Parādīt tikai POST maršrutus
php runway routes --post
# utt.
Pielāgotu komandu pievienošana Runway
Ja veidojat pakotni Flight vai vēlaties pievienot savas pielāgotās komandas savam projektam, varat to izdarīt, izveidojot src/commands/, flight/commands/, app/commands/ vai commands/ direktoriju savam projektam/pakotnei. Ja nepieciešama turpmāka pielāgošana, skatiet zemāk esošo sadaļu par konfigurāciju.
Skeletonā projekta komandas atrodas app/commands/ ar vārdu telpu App\Command. Runway tās atklāj pēc ceļa; saglabājiet šo mapi sinhronizētu ar Composer classmap/PSR-4, kā jūsu projekts jau dara.
Lai izveidotu komandu, vienkārši paplašiniet AbstractBaseCommand klasi un īstenojiet vismaz __construct metodi un execute metodi.
<?php
declare(strict_types=1);
namespace App\Command;
use flight\commands\AbstractBaseCommand;
class ExampleCommand extends AbstractBaseCommand
{
/**
* Konstruktor
*
* @param array<string,mixed> $config Konfigurācija no app/config/config.php
*/
public function __construct(array $config)
{
parent::__construct('make:example', 'Izveidot piemēru dokumentācijai', $config);
$this->argument('<funny-gif>', 'Smieklīgā gif nosaukums');
}
/**
* Izpilda funkciju
*
* @return void
*/
public function execute()
{
$io = $this->app()->io();
$io->info('Veido piemēru...');
// Dariet kaut ko šeit
$io->ok('Piemērs izveidots!');
}
}
Skatiet adhocore/php-cli dokumentāciju, lai iegūtu vairāk informācijas par to, kā izveidot savas pielāgotās komandas Flight lietotnē!
Konfigurācijas pārvaldība
Tā kā konfigurācija ir pārvietota uz app/config/config.php sākot ar v1.2.0, ir dažas palīgfunkcijas konfigurācijas pārvaldīšanai.
Skeleton padoms: Saglabājiet
config.phpkā burtiskas PHP vērtības. Noslēpumi pieder.env. Izvairieties no$_ENV[...]izteiksmēmconfig.phpiekšpusē —config:setpārraksta šo failu kā statiskus datus un varētu iebāzt noslēpumus failā. Skatiet Konfigurāciju.
Vecās konfigurācijas migrēšana
Ja jums ir vecs .runway-config.json fails, varat viegli migrēt to uz app/config/config.php ar šādu komandu:
php runway config:migrate
Konfigurācijas vērtības iestatīšana
Varat iestatīt konfigurācijas vērtību, izmantojot config:set komandu. Tas ir noderīgi, ja vēlaties atjaunināt konfigurācijas vērtību, neatverot failu.
php runway config:set app_root "app/"
Konfigurācijas vērtības iegūšana
Varat iegūt konfigurācijas vērtību, izmantojot config:get komandu.
php runway config:get app_root
Visas Runway konfigurācijas
Ja nepieciešams pielāgot Runway konfigurāciju, varat iestatīt šīs vērtības app/config/config.php. Zemāk ir dažas papildu konfigurācijas, kuras varat iestatīt:
<?php
// app/config/config.php
return [
// ... citi konfigurācijas vērtības ...
'runway' => [
// Šeit atrodas jūsu lietotnes direktorija
'app_root' => 'app/',
// Šis ir direktorijs, kur atrodas jūsu root index fails
'index_root' => 'public/',
// Tie ir ceļi uz citu projektu saknēm
'root_paths' => [
'/home/user/different-project',
'/var/www/another-project'
],
// Bāzes ceļi visticamāk nav jākonfigurē, bet tas ir šeit, ja vēlaties
'base_paths' => [
'/includes/libs/vendor', // ja jums ir patiešām unikāls ceļš jūsu vendor direktorijai vai kaut kam citam
],
// Galīgie ceļi ir atrašanās vietas projektā, kur meklēt komandu failus
'final_paths' => [
'src/diff-path/commands',
'app/module/admin/commands',
],
// Ja vēlaties vienkārši pievienot pilnu ceļu, dariet to (absolūts vai relatīvs pret projekta sakni)
'paths' => [
'/home/user/different-project/src/diff-path/commands',
'/var/www/another-project/app/module/admin/commands',
'app/my-unique-commands'
]
]
];
Konfigurācijas piekļuve
Ja nepieciešams efektīvi piekļūt konfigurācijas vērtībām, varat tām piekļūt caur __construct metodi vai app() metodi. Ir arī svarīgi atzīmēt, ka ja jums ir app/config/services.php fails, šie pakalpojumi arī būs pieejami jūsu komandai.
public function execute()
{
$io = $this->app()->io();
// Piekļūt konfigurācijai
$app_root = $this->config['runway']['app_root'];
// Piekļūt pakalpojumiem, piemēram, varbūt datu bāzes savienojumam
$database = $this->config['database']
// ...
}
AI palīgu ietvari
Runway ir daži palīgu ietvari, kas atvieglo AI komandu ģenerēšanu. Varat izmantot addOption un addArgument veidā, kas jutās līdzīgi Symfony Console. Tas ir noderīgi, ja izmantojat AI rīkus savu komandu ģenerēšanai.
public function __construct(array $config)
{
parent::__construct('make:example', 'Izveidot piemēru dokumentācijai', $config);
// Mode arguments ir nullable un noklusēti kā pilnībā neobligāti
$this->addOption('name', 'Piemēra nosaukums', null);
}
Skatiet arī
- Instalācija - Skeleton koks un create-project noklusējumi
- Autoloadēšana -
App\un mapes reģistrs - Atkarību injekcija - Dice + Engine injekcija ģenerētajiem kontrolieriem
- AI un izstrādātāja pieredze -
ai:init,ai:generate-instructions,AGENTS.md - Active Record - Modeļi, kas izmantoti ar
make:record/ skeletonApp\Model - SimplePdo - DB savienojums, ko izmanto skeleton migrācijas un modeļi
Awesome-plugins/tracy_extensions
Tracy Flight Panel Paplašinājumi
Šis ir paplašinājumu komplekts, lai padarītu darbu ar Flight nedaudz bagātāku.
- Flight - Analizēt visas Flight mainīgās vērtības.
- Database - Analizēt visus vaicājumus, kas izpildīti lapā (ja pareizi inicializē datu bāzes savienojumu)
- Request - Analizēt visus
$_SERVERmainīgos un pārbaudīt visus globālos datus ($_GET,$_POST,$_FILES) - Session - Analizēt visus
$_SESSIONmainīgos, ja sesijas ir aktīvas. - Twig (neobligāti) - Analizēt Twig veidnes renderēšanas laiku, atmiņu un to, kuras veidnes/bloki/makro tika izpildīti (nepieciešams
twig/twiguntwig_profilekonfigurācija)
Tas ir īpaši noderīgi ar oficiālo skeletu, kurš pēc noklusējuma izmanto Twig: tas pats izkārtojums AI rīki seko arī skaidri parādās Tracy joslā.
Šis ir Panelis

Un katrs panelis attēlo ļoti noderīgu informāciju par jūsu aplikāciju!

Klikšķiniet šeit lai skatītu kodu.
Instalācija
Izpildiet composer require flightphp/tracy-extensions --dev un jūs esat ceļā!
Twig nav stingra šī pakotnes atkarība. Instalējiet twig/twig tikai tad, ja vēlaties Twig paneli (skelets to jau dara skatiem).
Konfigurācija
Ir ļoti maz konfigurācijas, kas jums jāveic, lai to sāktu. Jums būs jāinicializē Tracy atkļūdotājs pirms šī lietošanas https://tracy.nette.org/en/guide:
<?php
use Tracy\Debugger;
use flight\debug\tracy\TracyExtensionLoader;
// bootstrap kods
require __DIR__ . '/vendor/autoload.php';
Debugger::enable();
// Jums var būt nepieciešams norādīt savu vidi ar Debugger::enable(Debugger::DEVELOPMENT)
// ja savā app izmantojat datu bāzes savienojumus, ir
// nepieciešams PDO wrapper, ko izmantot TIKAI IZSTRĀDES laikā (nevis ražošanā!)
// Tam ir tie paši parametri kā parastam PDO savienojumam
$pdo = new PdoQueryCapture('sqlite:test.db', 'user', 'pass');
// vai ja pievienojat to Flight framework
Flight::register('db', PdoQueryCapture::class, ['sqlite:test.db', 'user', 'pass']);
// tagad, kad veicat vaicājumu, tas uztvers laiku, vaicājumu un parametrus
// Tas savieno punktus
if(Debugger::$showBar === true) {
// Tam jābūt false vai Tracy nevar pat renderēt :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
// vairāk koda
Flight::start();
Papildu Konfigurācija
Sesijas Dati
Ja jums ir pielāgots sesiju apstrādātājs (piemēram, ghostff/session), varat nodot jebkuru sesiju datu masīvu Tracy, un tas automātiski to izvadīs jums. Jūs to nododat ar session_data atslēgu otrajā parametrā TracyExtensionLoader konstruktorā.
use Ghostff\Session\Session;
// vai izmantot flight\Session;
require 'vendor/autoload.php';
$app = Flight::app();
$app->register('session', Session::class);
if(Debugger::$showBar === true) {
// Tam jābūt false vai Tracy nevar pat renderēt :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
// maršruti un citas lietas...
Flight::start();
Twig panelis (neobligāts)
Ja jūsu app izmanto Twig (ieskaitot oficiālo skeletu), varat parādīt veidnes metrikas Tracy joslā. Izveidojiet Twig Profile, pievienojiet ProfilerExtension savai videi, pēc tam nododiet šo profilu ielādētājam zem twig_profile atslēgas. Pievienojiet profilēšanu tikai izstrādes laikā.
<?php
use flight\debug\tracy\TracyExtensionLoader;
use flight\debug\tracy\TwigTracyExtension;
use Tracy\Debugger;
use Twig\Environment;
use Twig\Extension\ProfilerExtension;
use Twig\Loader\FilesystemLoader;
use Twig\Profiler\Profile;
$loader = new FilesystemLoader(__DIR__ . '/views');
$twig = new Environment($loader, [
'debug' => true,
'cache' => false,
]);
// Neobligāti: atklāt Tracy dump palīgfunkcijas veidnēs
// {{ dump(var) }}, {{ bdump(var) }}, {{ dumpe(var) }}
$twig->addExtension(new TwigTracyExtension());
$tracyConfig = [];
if (Debugger::$showBar === true) {
$profile = new Profile();
$twig->addExtension(new ProfilerExtension($profile));
$tracyConfig['twig_profile'] = $profile;
}
if (Debugger::$showBar === true) {
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), $tracyConfig);
}
// Kartēt Flight::render() uz Twig (piemērs)
Flight::map('render', function (string $template, array $data = []) use ($twig) {
if (substr($template, -5) !== '.twig') {
$template .= '.twig';
}
echo $twig->render($template, $data);
});
Ko panelis parāda
- Kopējais Twig renderēšanas laiks un atmiņa
- Veidnes / bloka / makro izsaukumu skaits
- Katra veidne, kas tika renderēta, ar savu laiku un atmiņu
Twig cilne ir paslēpta, kad vaicājumam netika renderētas veidnes, vai kad izlaižat twig_profile (vai jums nav Twig instalēts) — citi Flight paneļi turpina darboties.
Skeletveida services.php, izveidojiet to pašu $profile / ProfilerExtension, kad atkļūdošana ir ieslēgta, nododiet twig_profile uz TracyExtensionLoader, un turpiniet izmantot savu kopīgo Twig vidi priekš $app->render().
Latte
PHP 8.1+ ir nepieciešams šai sadaļai.
Ja jums ir Latte instalēts savā projektā, Tracy ir vietējā integrācija ar Latte, lai analizētu jūsu veidnes. Jūs vienkārši reģistrējat paplašinājumu ar savu Latte instanci (šī ir Latte paša Tracy tilts, nevis Twig panelis augšā).
require 'vendor/autoload.php';
$app = Flight::app();
$app->map('render', function($template, $data, $block = null) {
$latte = new Latte\Engine;
// citas konfigurācijas...
// pievienot paplašinājumu tikai tad, ja Tracy Debug josla ir ieslēgta
if(Debugger::$showBar === true) {
// šeit jūs pievienojat Latte Panel Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
}
$latte->render($template, $data, $block);
});
Skatīt Arī
- Tracy - Tracy bāzes iestatījums Flight
- Twig - Veidņošana, ko izmanto skelets un Twig panelis
- Templates - Kā Flight kartē
renderuz Twig/Latte - Installation - Skelets ietver tracy-extensions izstrādes laikā
Awesome-plugins/apm
FlightPHP APM Dokumentācija
Laipni lūdzam FlightPHP APM — jūsu lietotnes personīgais veiktspējas treneris! Šī rokasgrāmata ir jūsu ceļvedis, kā iestatīt, izmantot un apgūt Lietotnes veiktspējas uzraudzību (APM) ar FlightPHP. Neatkarīgi no tā, vai meklējat lēnus pieprasījumus vai vēlaties iedziļināties latentuma diagrammās, mēs esam jums palīdzējuši. Padarīsim jūsu lietotni ātrāku, lietotājus laimīgākus un atkļūdošanas sesijas vieglākas!
Skatīt demo Flight Docs vietnes informācijas paneli.

Kāpēc APM ir svarīgs
Iedomājieties: jūsu lietotne ir aizņemta restorāna. Bez veida, kā izsekot, cik ilgi pasūtījumi aizņem vai kur virtuve kavējas, jūs minat, kāpēc klienti aiziet neapmierināti. APM ir jūsu sous-chef — tas vēro katru soli, no ienākošajiem pieprasījumiem līdz datubāzes vaicājumiem, un atzīmē visu, kas jūs palēnina. Lēnas lapas zaudē lietotājus (pētījumi saka, ka 53% atstāj, ja vietne aizņem vairāk nekā 3 sekundes, lai ielādētu!), un APM palīdz jums noķert šīs problēmas pirms tās sāp. Tas ir proaktīvs miera prāts — mazāk “kāpēc tas ir salauzts?” brīžu, vairāk “skatieties, cik gludi tas darbojas!” uzvaru.
Uzstādīšana
Sāciet darbu ar Composer:
composer require flightphp/apm
Jums būs nepieciešams:
- PHP 7.4+: Saglabā mūs saderīgus ar LTS Linux distro, vienlaikus atbalstot modernu PHP.
- FlightPHP Core v3.15+: Vieglais ietvars, ko mēs uzlabojam.
Atbalstītās datubāzes
FlightPHP APM pašlaik atbalsta šādas datubāzes metrikas glabāšanai:
- SQLite3: Vienkārša, failu bāzēta un lieliska vietējai izstrādei vai mazām lietotnēm. Noklusējuma opcija lielākajā daļā iestatījumu.
- MySQL/MariaDB: Ideāla lielākiem projektiem vai ražošanas vidēm, kur nepieciešama stabila, mērogojama glabāšana.
Jūs varat izvēlēties savu datubāzes tipu konfigurācijas solī (skatīt zemāk). Pārliecinieties, ka jūsu PHP vidē ir instalēti nepieciešamie paplašinājumi (piem., pdo_sqlite vai pdo_mysql).
Darba sākšana
Šeit ir jūsu soli pa solim ceļvedis APM izcilībai:
1. Reģistrējiet APM
Ievietojiet šo savā index.php vai services.php failā, lai sāktu izsekošanu:
use flight\apm\logger\LoggerFactory;
use flight\database\SimplePdo;
use flight\Apm;
$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
$Apm = new Apm($ApmLogger);
$Apm->bindEventsToFlightInstance($app);
// If you're adding a database connection
// Prefer SimplePdo (or PdoQueryCapture from Tracy Extensions in dev).
// Enable APM query tracking via the options array (5th argument).
$pdo = new SimplePdo('mysql:host=localhost;dbname=example', 'user', 'pass', null, [
'trackApmQueries' => true, // required to capture queries for the APM
]);
$Apm->addPdoConnection($pdo);
Kas šeit notiek?
LoggerFactory::create()paņem jūsu konfigurāciju (vairāk par to drīz) un iestata žurnālu — SQLite pēc noklusējuma.Apmir zvaigzne — tas klausās Flight notikumus (pieprasījumi, maršruti, kļūdas utt.) un apkopo metrikas.bindEventsToFlightInstance($app)piesaista to visu jūsu Flight lietotnei.
Pro padoms: Paraugu ņemšana Ja jūsu lietotne ir aizņemta, katra pieprasījuma reģistrēšana var pārslodzi sistēmu. Izmantojiet parauga ātrumu (0.0 līdz 1.0):
$Apm = new Apm($ApmLogger, 0.1); // Logs 10% of requests
Tas saglabā veiktspēju ātru, vienlaikus nodrošinot jums stabilus datus.
2. Konfigurējiet to
Palaidiet šo, lai izveidotu savu .runway-config.json:
php vendor/bin/runway apm:init
Ko tas dara?
- Palaiž vedni, kas jautā, no kurienes nāk neapstrādātās metrikas (avots) un kur nonāk apstrādātie dati (galamērķis).
- Noklusējums ir SQLite — piemēram,
sqlite:/tmp/apm_metrics.sqliteavotam, cits galamērķim. - Jūs beigsiet ar konfigurāciju, piemēram:
{ "apm": { "source_type": "sqlite", "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", "storage_type": "sqlite", "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" } }
Šis process arī jautās, vai vēlaties palaist migrācijas šim iestatījumam. Ja iestatāt to pirmo reizi, atbilde ir jā.
Kāpēc divas atrašanās vietas? Neapstrādātās metrikas ātri uzkrājas (domājiet par nefiltrētiem žurnāliem). Strādnieks tās apstrādā strukturētā galamērķī informācijas panelim. Saglabā lietas sakārtotas!
3. Apstrādājiet metrikas ar strādnieku
Strādnieks pārvērš neapstrādātās metrikas informācijas panelim gatavos datos. Palaidiet to vienreiz:
php vendor/bin/runway apm:worker
Ko tas dara?
- Lasa no jūsu avota (piem.,
apm_metrics.sqlite). - Apstrādā līdz 100 metrikām (noklusējuma partijas izmērs) jūsu galamērķī.
- Apstājas, kad pabeigts vai ja nav palikušas metrikas.
Saglabājiet to darboties Dzīvām lietotnēm jums būs nepieciešama nepārtraukta apstrāde. Šeit ir jūsu opcijas:
-
Dēmona režīms:
php vendor/bin/runway apm:worker --daemonDarbojas mūžīgi, apstrādājot metrikas, kad tās nāk. Lieliski izstrādei vai maziem iestatījumiem.
-
Crontab: Pievienojiet šo savam crontab (
crontab -e):* * * * * php /path/to/project/vendor/bin/runway apm:workerIzpildās katru minūti — ideāli ražošanai.
-
Tmux/Screen: Sāciet atvienojamu sesiju:
tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon # Ctrl+B, then D to detach; `tmux attach -t apm-worker` to reconnectSaglabā to darboties pat tad, ja izrakstāties.
-
Pielāgotas izmaiņas:
php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300--batch_size 50: Apstrādāt 50 metrikas vienlaikus.--max_messages 1000: Apstāties pēc 1000 metrikām.--timeout 300: Beigt pēc 5 minūtēm.
Kāpēc apgrūtināties? Bez strādnieka jūsu informācijas panelis ir tukšs. Tas ir tilts starp neapstrādātiem žurnāliem un darbības ieskatiem.
4. Palaidiet informācijas paneli
Skatiet savas lietotnes vitālos rādītājus:
php vendor/bin/runway apm:dashboard
Ko tas dara?
- Palaida PHP serveri
http://localhost:8001/apm/dashboard. - Rāda pieprasījumu žurnālus, lēnus maršrutus, kļūdu līmeņus un vairāk.
Pielāgojiet to:
php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php
--host 0.0.0.0: Pieejams no jebkura IP (noderīgi attālinātai skatīšanai).--port 8080: Izmantojiet citu portu, ja 8001 ir aizņemts.--php-path: Norādiet uz PHP, ja tas nav jūsu PATH.
Atveriet URL savā pārlūkprogrammā un izpētiet!
Ražošanas režīms
Ražošanai jums var nākties izmēģināt dažas metodes, lai palaistu informācijas paneli, jo tur droši vien ir ugunsmūri un citi drošības pasākumi. Šeit ir dažas opcijas:
- Izmantojiet reverso proxy: Iestatiet Nginx vai Apache, lai pārsūtītu pieprasījumus uz informācijas paneli.
- SSH tunelis: Ja varat SSH pieslēgties serverim, izmantojiet
ssh -L 8080:localhost:8001 youruser@yourserverlai tunelētu informācijas paneli uz savu lokālo mašīnu. - VPN: Ja jūsu serveris ir aiz VPN, pieslēdzieties tam un piekļūstiet informācijas panelim tieši.
- Konfigurējiet ugunsmūri: Atveriet portu 8001 savam IP vai servera tīklam. (vai jebkuru portu, ko iestatījāt).
- Konfigurējiet Apache/Nginx: Ja jums ir tīmekļa serveris jūsu lietotnes priekšā, varat to konfigurēt uz domēnu vai apakšdomēnu. Ja to darāt, iestatiet dokumentu sakni uz
/path/to/your/project/vendor/flightphp/apm/dashboard
Vēlaties citu informācijas paneli?
Jūs varat izveidot savu informācijas paneli, ja vēlaties! Skatieties vendor/flightphp/apm/src/apm/presenter direktoriju idejām, kā prezentēt datus savam informācijas panelim!
Informācijas paneļa funkcijas
Informācijas panelis ir jūsu APM HQ — šeit ir tas, ko redzēsiet:
- Pieprasījumu žurnāls: Katrs pieprasījums ar laika zīmogu, URL, atbildes kodu un kopējo laiku. Noklikšķiniet uz “Detaļas” middleware, vaicājumiem un kļūdām.
- Lēnākie pieprasījumi: Top 5 pieprasījumi, kas aizņem laiku (piem., “/api/heavy” ar 2.5s).
- Lēnākie maršruti: Top 5 maršruti pēc vidējā laika — lieliski modeļu noteikšanai.
- Kļūdu līmenis: Procentuāli pieprasījumi, kas neizdodas (piem., 2.3% 500s).
- Latentuma procentiles: 95. (p95) un 99. (p99) atbildes laiki — ziniet savus sliktākos scenārijus.
- Atbildes koda diagramma: Vizualizējiet 200s, 404s, 500s laika gaitā.
- Garie vaicājumi/middleware: Top 5 lēnie datubāzes zvani un middleware slāņi.
- Kešatmiņas trāpījums/neveiksme: Cik bieži jūsu kešatmiņa glābj dienu.
Papildu:
- Filtrēt pēc “Pēdējā stunda,” “Pēdējā diena,” vai “Pēdējā nedēļa.”
- Pārslēgt tumšo režīmu tām vēlu nakts sesijām.
Piemērs:
Pieprasījums uz /users var parādīt:
- Kopējais laiks: 150ms
- Middleware:
AuthMiddleware->handle(50ms) - Vaicājums:
SELECT * FROM users(80ms) - Kešatmiņa: Trāpījums
user_list(5ms)
Pielāgotu notikumu pievienošana
Izsekot jebko — kā API zvanu vai maksājuma procesu:
use flight\apm\CustomEvent;
$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [
'endpoint' => 'https://api.example.com/users',
'response_time' => 0.25,
'status' => 200
]));
Kur tas parādās? Informācijas paneļa pieprasījuma detaļās zem “Pielāgotie notikumi” — izvēršams ar skaistu JSON formatējumu.
Lietošanas gadījums:
$start = microtime(true);
$apiResponse = file_get_contents('https://api.example.com/data');
$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [
'url' => 'https://api.example.com/data',
'time' => microtime(true) - $start,
'success' => $apiResponse !== false
]));
Tagad redzēsiet, vai šis API velk jūsu lietotni uz leju!
Datubāzes uzraudzība
Izsekot PDO vaicājumus šādi:
use flight\database\SimplePdo;
$pdo = new SimplePdo('sqlite:/path/to/db.sqlite', null, null, null, [
'trackApmQueries' => true, // required to capture queries for the APM
]);
$Apm->addPdoConnection($pdo);
Ko jūs saņemat:
- Vaicājuma teksts (piem.,
SELECT * FROM users WHERE id = ?) - Izpildes laiks (piem., 0.015s)
- Rindu skaits (piem., 42)
Uzmanību:
- Neobligāti: Izlaidiet šo, ja jums nav nepieciešama DB izsekošana.
- SimplePdo (ieteicams): Izmantojiet
SimplePdoartrackApmQueries => true. NovecojušaisPdoWrapperjoprojām darbojas (5. konstruktora argumentstrue). Neapstrādāts core PDO vēl nav saistīts — sekojiet līdzi! - Veiktspējas brīdinājums: Katra vaicājuma reģistrēšana DB smagā vietnē var palēnināt lietas. Izmantojiet paraugu ņemšanu (
$Apm = new Apm($ApmLogger, 0.1)) lai samazinātu slodzi.
Piemēra izvade:
- Vaicājums:
SELECT name FROM products WHERE price > 100 - Laiks: 0.023s
- Rindas: 15
Strādnieka opcijas
Pielāgojiet strādnieku pēc savas patikas:
--timeout 300: Apstājas pēc 5 minūtēm — labs testēšanai.--max_messages 500: Ierobežo līdz 500 metrikām — saglabā to galīgu.--batch_size 200: Apstrādā 200 vienlaikus — līdzsvaro ātrumu un atmiņu.--daemon: Darbojas nepārtraukti — ideāli dzīvoai uzraudzībai.
Piemērs:
php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600
Darbojas stundu, apstrādājot 100 metrikas vienlaikus.
Pieprasījuma ID lietotnē
Katram pieprasījumam ir unikāls pieprasījuma ID izsekošanai. Jūs varat izmantot šo ID savā lietotnē, lai korelētu žurnālus un metrikas. Piemēram, jūs varat pievienot pieprasījuma ID kļūdas lapai:
Flight::map('error', function($message) {
// Get the request ID from the response header X-Flight-Request-Id
$requestId = Flight::response()->getHeader('X-Flight-Request-Id');
// Additionally you could fetch it from the Flight variable
// This method won't work well in swoole or other async platforms.
// $requestId = Flight::get('apm.request_id');
echo "Error: $message (Request ID: $requestId)";
});
Jaunināšana
Ja jaunināt uz jaunāku APM versiju, pastāv iespēja, ka ir nepieciešamas datubāzes migrācijas. Jūs varat to izdarīt, palaižot šādu komandu:
php vendor/bin/runway apm:migrate
Tas palaidīs visas migrācijas, kas nepieciešamas, lai atjauninātu datubāzes shēmu uz jaunāko versiju.
Piezīme: Ja jūsu APM datubāze ir liela izmēra, šīs migrācijas var aizņemt kādu laiku. Jūs varat vēlēties palaist šo komandu ārpus maksimālās slodzes stundām.
Jaunināšana no 0.4.3 -> 0.5.0
Ja jaunināt no 0.4.3 uz 0.5.0, jums būs jāpalaiž šāda komanda:
php vendor/bin/runway apm:config-migrate
Tas migrēs jūsu konfigurāciju no vecā formāta, izmantojot .runway-config.json failu, uz jauno formātu, kas glabā atslēgu/vērtību config.php failā.
Veco datu tīrīšana
Lai saglabātu savu datubāzi sakārtotu, jūs varat iztīrīt vecos datus. Tas ir īpaši noderīgi, ja vadāt aizņemtu lietotni un vēlaties saglabāt datubāzes izmēru pārvaldāmu. Jūs varat to izdarīt, palaižot šādu komandu:
php vendor/bin/runway apm:purge
Tas noņems visus datus, kas vecāki par 30 dienām no datubāzes. Jūs varat pielāgot dienu skaitu, nododot citu vērtību --days opcijai:
php vendor/bin/runway apm:purge --days 7
Tas noņems visus datus, kas vecāki par 7 dienām no datubāzes.
Problēmu novēršana
Iestrēguši? Izmēģiniet šos:
-
Nav informācijas paneļa datu?
- Vai strādnieks darbojas? Pārbaudiet
ps aux | grep apm:worker. - Vai konfigurācijas ceļi sakrīt? Pārbaudiet, vai
.runway-config.jsonDSN norāda uz reāliem failiem. - Palaidiet
php vendor/bin/runway apm:workermanuāli, lai apstrādātu gaidošās metrikas.
- Vai strādnieks darbojas? Pārbaudiet
-
Strādnieka kļūdas?
- Ieskaitieties savos SQLite failos (piem.,
sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"). - Pārbaudiet PHP žurnālus stack traces.
- Ieskaitieties savos SQLite failos (piem.,
-
Informācijas panelis nesāksies?
- Vai ports 8001 ir aizņemts? Izmantojiet
--port 8080. - Vai PHP nav atrasts? Izmantojiet
--php-path /usr/bin/php. - Vai ugunsmūris bloķē? Atveriet portu vai izmantojiet
--host localhost.
- Vai ports 8001 ir aizņemts? Izmantojiet
-
Pārāk lēni?
- Samaziniet parauga ātrumu:
$Apm = new Apm($ApmLogger, 0.05)(5%). - Samaziniet partijas izmēru:
--batch_size 20.
- Samaziniet parauga ātrumu:
-
Neizseko izņēmumus/kļūdas?
- Ja jums ir Tracy ieslēgts jūsu projektam, tas pārrakstīs Flight kļūdu apstrādi. Jums būs jāatspējo Tracy un pēc tam jāpārliecinās, ka
Flight::set('flight.handle_errors', true);ir iestatīts.
- Ja jums ir Tracy ieslēgts jūsu projektam, tas pārrakstīs Flight kļūdu apstrādi. Jums būs jāatspējo Tracy un pēc tam jāpārliecinās, ka
-
Neizseko datubāzes vaicājumus?
- Dodiet priekšroku
SimplePdoar['trackApmQueries' => true]kā 5. konstruktora argumentu (opciju masīvs). - Ja joprojām izmantojat novecojušo
PdoWrapper, nododiettruekā 5. argumentu. - Izsauciet
$Apm->addPdoConnection($pdo)pēc savienojuma izveides.
- Dodiet priekšroku
Awesome-plugins/tracy
Tracy
Tracy ir brīnišķīgs kļūdu apstrādātājs, ko var izmantot kopā ar Flight. Tam ir vairāki paneļi, kas var palīdzēt atkļūdot jūsu lietojumprogrammu. Tas ir arī ļoti viegli paplašināms un pievienot savus paneļus. Flight komanda ir izveidojusi dažus paneļus īpaši Flight projektiem ar flightphp/tracy-extensions spraudni (Flight mainīgie, DB vaicājumi, pieprasījums, sesija un izvēles Twig panelis, kad nododat profilētāja profilu — skatiet Tracy Extensions).
Instalācija
Instalējiet ar composer. Un jūs patiešām vēlēsieties to instalēt bez izstrādes versijas, jo Tracy nāk ar ražošanas kļūdu apstrādes komponenti.
composer require tracy/tracy
Pamata konfigurācija
Ir dažas pamata konfigurācijas iespējas, lai sāktu darbu. Vairāk par tām varat lasīt Tracy dokumentācijā.
require 'vendor/autoload.php';
use Tracy\Debugger;
// Iespējot Tracy
Debugger::enable();
// Debugger::enable(Debugger::DEVELOPMENT) // dažreiz jums ir jābūt precīzam (arī Debugger::PRODUCTION)
// Debugger::enable('23.75.345.200'); // jūs varat arī norādīt IP adrešu masīvu
// Šeit tiks reģistrētas kļūdas un izņēmumi. Pārliecinieties, ka šis direktorijs eksistē un ir rakstāms.
Debugger::$logDirectory = __DIR__ . '/../log/';
Debugger::$strictMode = true; // rādīt visas kļūdas
// Debugger::$strictMode = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED; // visas kļūdas izņemot novecojušus paziņojumus
if (Debugger::$showBar) {
$app->set('flight.content_length', false); // ja Debugger josla ir redzama, tad content-length nevar iestatīt ar Flight
// Tas ir specifiski Tracy Extension for Flight, ja esat to iekļāvis
// pretējā gadījumā komentējiet to.
new TracyExtensionLoader($app);
}
Noderīgi padomi
Kad atkļūdojat savu kodu, ir dažas ļoti noderīgas funkcijas datu izvadīšanai.
bdump($var)- Tas izvadīs mainīgo Tracy joslā atsevišķā panelī.dumpe($var)- Tas izvadīs mainīgo un pēc tam nekavējoties beigs darbu.
Awesome-plugins/active_record
Flight Active Record
Aktīvs ieraksts ir datubāzes entītijas kartēšana uz PHP objektu. Vienkārši izteikts, ja jums ir lietotāju tabula datubāzē, jūs varat "tulkot" rindas šajā tabulā uz User klasi un $user objektu jūsu koda bāzē. Skatiet pamatinstanci.
Noklikšķiniet šeit, lai iegūtu repozitoriju GitHub.
Pamatinstance
Pieņemsim, ka jums ir šāda tabula:
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
password TEXT
);
Tagad jūs varat izveidot jaunu klasi, lai attēlotu šo tabulu:
/**
* ActiveRecord klase parasti ir vienskaitlī
*
* Ļoti ieteicams pievienot tabulas īpašības kā komentārus šeit
*
* @property int $id
* @property string $name
* @property string $password
*/
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
// jūs varat iestatīt to šādi
parent::__construct($database_connection, 'users');
// vai šādi
parent::__construct($database_connection, null, [ 'table' => 'users']);
}
}
Tagad vērojiet, kā notiek burvība!
// sqlite gadījumā
$database_connection = new PDO('sqlite:test.db'); // tas ir tikai piemēram, jūs droši vien izmantosiet īstu datubāzes savienojumu
// mysql gadījumā
$database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password');
// vai mysqli
$database_connection = new mysqli('localhost', 'username', 'password', 'test_db');
// vai mysqli ar neobjekta bāzētu izveidi
$database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db');
$user = new User($database_connection);
$user->name = 'Bobby Tables';
$user->password = password_hash('some cool password');
$user->insert();
// vai $user->save();
echo $user->id; // 1
$user->name = 'Joseph Mamma';
$user->password = password_hash('some cool password again!!!');
$user->insert();
// šeit nevar izmantot $user->save(), pretējā gadījumā tas domās, ka tas ir atjauninājums!
echo $user->id; // 2
Un tik viegli bija pievienot jaunu lietotāju! Tagad, kad datubāzē ir lietotāja rinda, kā jūs to izvilksiet?
$user->find(1); // atrast id = 1 datubāzē un atgriezt to.
echo $user->name; // 'Bobby Tables'
Un kas, ja jūs vēlaties atrast visus lietotājus?
$users = $user->findAll();
Ko darīt ar noteiktu nosacījumu?
$users = $user->like('name', '%mamma%')->findAll();
Redziet, cik jautri tas ir? Instalēsim to un sāksim!
Instalēšana
Vienkārši instalējiet ar Composer
composer require flightphp/active-record
Lietošana
To var izmantot kā neatkarīgu bibliotēku vai ar Flight PHP Framework. Pilnībā atkarīgs no jums.
Neatkarīgi
Vienkārši pārliecinieties, ka konstruktoram nododat PDO savienojumu.
$pdo_connection = new PDO('sqlite:test.db'); // tas ir tikai piemēram, jūs droši vien izmantosiet īstu datubāzes savienojumu
$User = new User($pdo_connection);
Vai nevēlaties vienmēr iestatīt datubāzes savienojumu konstruktorā? Skatiet Datubāzes savienojuma pārvaldību citiem variantiem!
Reģistrēšana kā metode Flight
Ja izmantojat Flight PHP Framework, jūs varat reģistrēt ActiveRecord klasi kā servisu, bet patiesībā nav obligāti.
Flight::register('user', 'User', [ $pdo_connection ]);
// tad jūs varat izmantot to šādi kontrolierī, funkcijā utt.
Flight::user()->find(1);
runway Metodes
runway ir CLI rīks Flight, kas ir ar pielāgotu komandu šai bibliotēkai.
# Lietošana
php runway make:record database_table_name [class_name]
# Piemērs
php runway make:record users
Tas izveidos jaunu klasi app/records/ direktorijā kā UserRecord.php ar šādu saturu:
<?php
declare(strict_types=1);
namespace app\records;
/**
* ActiveRecord klase lietotāju tabulai.
* @link https://docs.flightphp.com/awesome-plugins/active-record
*
* @property int $id
* @property string $username
* @property string $email
* @property string $password_hash
* @property string $created_dt
*/
class UserRecord extends \flight\ActiveRecord
{
/**
* @var array $relations Iestatīt modeļa attiecības
* https://docs.flightphp.com/awesome-plugins/active-record#relationships
*/
protected array $relations = [
// 'relation_name' => [ self::HAS_MANY, 'RelatedClass', 'foreign_key' ],
];
/**
* Konstruktors
* @param mixed $databaseConnection Savienojums ar datubāzi
*/
public function __construct($databaseConnection)
{
parent::__construct($databaseConnection, 'users');
}
}
CRUD funkcijas
find($id = null) : boolean|ActiveRecord
Atrast vienu ierakstu un piešķirt to pašreizējam objektam. Ja nododat kādu $id, tas veiks meklēšanu primārajā atslēgā ar šo vērtību. Ja nekas netiek nodots, tas atradīs pirmo ierakstu tabulā.
Turklāt jūs varat nodot citas palīgmēģenes, lai vaicātu tabulu.
// atrast ierakstu ar dažiem nosacījumiem iepriekš
$user->notNull('password')->orderBy('id DESC')->find();
// atrast ierakstu pēc specifiska id
$id = 123;
$user->find($id);
findAll(): array<int,ActiveRecord>
Atrast visus ierakstus tabulā, ko jūs norādāt.
$user->findAll();
isHydrated(): boolean (v0.4.0)
Atgriež true, ja pašreizējais ieraksts ir hidratēts (iegūts no datubāzes).
$user->find(1);
// ja ieraksts ir atrasts ar datiem...
$user->isHydrated(); // true
insert(): boolean|ActiveRecord
Ievieto pašreizējo ierakstu datubāzē.
$user = new User($pdo_connection);
$user->name = 'demo';
$user->password = md5('demo');
$user->insert();
Teksta bāzētas primārās atslēgas
Ja jums ir teksta bāzēta primārā atslēga (piemēram, UUID), jūs varat iestatīt primārās atslēgas vērtību pirms ievietošanas divos veidos.
$user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]);
$user->uuid = 'some-uuid';
$user->name = 'demo';
$user->password = md5('demo');
$user->insert(); // vai $user->save();
vai jūs varat ļaut primārajai atslēgai automātiski ģenerēties caur notikumiem.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]);
// jūs varat iestatīt primaryKey arī šādi, nevis ar masīvu iepriekš.
$this->primaryKey = 'uuid';
}
protected function beforeInsert(self $self) {
$self->uuid = uniqid(); // vai kā jūs ģenerējat savas unikālās id
}
}
Ja jūs neiestatāt primāro atslēgu pirms ievietošanas, tā tiks iestatīta uz rowid un datubāze to ģenerēs jums, bet tā nepastāvēs, jo tas lauks var nepastāvēt jūsu tabulā. Tāpēc ieteicams izmantot notikumu, lai automātiski apstrādātu to.
update(): boolean|ActiveRecord
Atjaunina pašreizējo ierakstu datubāzē.
$user->greaterThan('id', 0)->orderBy('id desc')->find();
$user->email = 'test@example.com';
$user->update();
save(): boolean|ActiveRecord
Ievieto vai atjaunina pašreizējo ierakstu datubāzē. Ja ierakstam ir id, tas atjauninās, citādi ievietos.
$user = new User($pdo_connection);
$user->name = 'demo';
$user->password = md5('demo');
$user->save();
Piezīme: Ja jums ir definētas attiecības klasē, tas rekursīvi saglabās tās attiecības, ja tās ir definētas, instance un ir netīri dati atjaunināšanai. (v0.4.0 un augstāk)
delete(): boolean
Dzēš pašreizējo ierakstu no datubāzes.
$user->gt('id', 0)->orderBy('id desc')->find();
$user->delete();
Jūs varat arī dzēst vairākus ierakstus, izpildot meklēšanu iepriekš.
$user->like('name', 'Bob%')->delete();
dirty(array $dirty = []): ActiveRecord
Netīri dati attiecas uz datiem, kas ir mainīti ierakstā.
$user->greaterThan('id', 0)->orderBy('id desc')->find();
// līdz šim nekas nav "netīrs".
$user->email = 'test@example.com'; // tagad email tiek uzskatīts par "netīru", jo tas ir mainīts.
$user->update();
// tagad nav datu, kas ir netīri, jo tie ir atjaunināti un saglabāti datubāzē
$user->password = password_hash()'newpassword'); // tagad tas ir netīrs
$user->dirty(); // neko nepadojot, tas notīrīs visus netīros ierakstus.
$user->update(); // nekas netiks atjaunināts, jo nekas netika uztverts kā netīrs.
$user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]);
$user->update(); // gan name, gan password tiks atjaunināti.
copyFrom(array $data): ActiveRecord (v0.4.0)
Tas ir alias dirty() metodei. Tas ir nedaudz skaidrāks, ko jūs darāt.
$user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]);
$user->update(); // gan name, gan password tiks atjaunināti.
isDirty(): boolean (v0.4.0)
Atgriež true, ja pašreizējais ieraksts ir mainīts.
$user->greaterThan('id', 0)->orderBy('id desc')->find();
$user->email = 'test@email.com';
$user->isDirty(); // true
reset(bool $include_query_data = true): ActiveRecord
Atiestata pašreizējo ierakstu uz tā sākotnējo stāvokli. Tas ir patiešām labs lietošanai cilpas veida uzvedībās. Ja padojat true, tas arī atiestatīs vaicājuma datus, kas tika izmantoti, lai atrastu pašreizējo objektu (noklusējuma uzvedība).
$users = $user->greaterThan('id', 0)->orderBy('id desc')->find();
$user_company = new UserCompany($pdo_connection);
foreach($users as $user) {
$user_company->reset(); // sākt ar tīru lapu
$user_company->user_id = $user->id;
$user_company->company_id = $some_company_id;
$user_company->insert();
}
getBuiltSql(): string (v0.4.1)
Pēc tam, kad izpildāt find(), findAll(), insert(), update() vai save() metodi, jūs varat iegūt SQL, kas tika izveidots, un izmantot to atkļūdošanas nolūkos.
SQL vaicājuma metodes
select(string $field1 [, string $field2 ... ])
Jūs varat atlasīt tikai dažas kolonnas tabulā, ja vēlaties (tas ir efektīvāks patiešām plašās tabulās ar daudzām kolonnām)
$user->select('id', 'name')->find();
from(string $table)
Jūs tehniski varat izvēlēties arī citu tabulu! Kāpēc gan ne?!
$user->select('id', 'name')->from('user')->find();
join(string $table_name, string $join_condition)
Jūs pat varat pievienoties citai tabulai datubāzē.
$user->join('contacts', 'contacts.user_id = users.id')->find();
where(string $where_conditions)
Jūs varat iestatīt dažus pielāgotus where argumentus (jūs nevarat iestatīt parametrus šajā where paziņojumā)
$user->where('id=1 AND name="demo"')->find();
Drošības piezīme - Jūs varētu būt kārdināts darīt kaut ko līdzīgu $user->where("id = '{$id}' AND name = '{$name}'")->find();. Lūdzu, NEDARIET TO!!! Tas ir pakļauts tam, ko sauc par SQL injekcijas uzbrukumiem. Ir daudz rakstu tiešsaistē, lūdzu, meklējiet Google "sql injection attacks php" un atradīsit daudz rakstu par šo tēmu. Pareizais veids, kā apstrādāt to ar šo bibliotēku, ir, nevis izmantot šo where() metodi, bet gan kaut ko līdzīgu $user->eq('id', $id)->eq('name', $name)->find(); Ja jums absolūti jāto dara, PDO bibliotēkai ir $pdo->quote($var), lai aizbēgtu to jums. Tikai pēc quote() izmantošanas jūs varat izmantot to where() paziņojumā.
group(string $group_by_statement)/groupBy(string $group_by_statement)
Grupēt jūsu rezultātus pēc noteikta nosacījuma.
$user->select('COUNT(*) as count')->groupBy('name')->findAll();
order(string $order_by_statement)/orderBy(string $order_by_statement)
Kārtot atgriezto vaicājumu noteiktā veidā.
$user->orderBy('name DESC')->find();
limit(string $limit)/limit(int $offset, int $limit)
Ierobežot atgriezto ierakstu skaitu. Ja dots otrais int, tas būs nobīde, ierobežojums tieši kā SQL.
$user->orderby('name DESC')->limit(0, 10)->findAll();
WHERE nosacījumi
equal(string $field, mixed $value) / eq(string $field, mixed $value)
Kur field = $value
$user->eq('id', 1)->find();
notEqual(string $field, mixed $value) / ne(string $field, mixed $value)
Kur field <> $value
$user->ne('id', 1)->find();
isNull(string $field)
Kur field IS NULL
$user->isNull('id')->find();
isNotNull(string $field) / notNull(string $field)
Kur field IS NOT NULL
$user->isNotNull('id')->find();
greaterThan(string $field, mixed $value) / gt(string $field, mixed $value)
Kur field > $value
$user->gt('id', 1)->find();
lessThan(string $field, mixed $value) / lt(string $field, mixed $value)
Kur field < $value
$user->lt('id', 1)->find();
greaterThanOrEqual(string $field, mixed $value) / ge(string $field, mixed $value) / gte(string $field, mixed $value)
Kur field >= $value
$user->ge('id', 1)->find();
lessThanOrEqual(string $field, mixed $value) / le(string $field, mixed $value) / lte(string $field, mixed $value)
Kur field <= $value
$user->le('id', 1)->find();
like(string $field, mixed $value) / notLike(string $field, mixed $value)
Kur field LIKE $value vai field NOT LIKE $value
$user->like('name', 'de')->find();
in(string $field, array $values) / notIn(string $field, array $values)
Kur field IN($value) vai field NOT IN($value)
$user->in('id', [1, 2])->find();
between(string $field, array $values)
Kur field BETWEEN $value AND $value1
$user->between('id', [1, 2])->find();
OR nosacījumi
Ir iespējams apvijināt jūsu nosacījumus OR paziņojumā. Tas tiek darīts ar startWrap() un endWrap() metodi vai aizpildot 3. parametru nosacījumā pēc lauka un vērtības.
// Metode 1
$user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find();
// Tas tiks novērtēts kā `id = 1 AND (name = 'demo' OR name = 'test')`
// Metode 2
$user->eq('id', 1)->eq('name', 'demo', 'OR')->find();
// Tas tiks novērtēts kā `id = 1 OR name = 'demo'`
Attiecības
Jūs varat iestatīt vairākas attiecību veidus, izmantojot šo bibliotēku. Jūs varat iestatīt one->many un one->one attiecības starp tabulām. Tas prasa nedaudz papildu iestatījumu klasē iepriekš.
Iestatot $relations masīvu nav grūti, bet pareizās sintakses minēšana var būt mulsinoša.
protected array $relations = [
// jūs varat nosaukt atslēgu jebkā vēlaties. ActiveRecord nosaukums droši vien ir labs. Piem: user, contact, client
'user' => [
// obligāti
// self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO
self::HAS_ONE, // tas ir attiecību veids
// obligāti
'Some_Class', // tas ir "cits" ActiveRecord klase, uz kuru tas atsaucas
// obligāti
// atkarībā no attiecību veida
// self::HAS_ONE = ārējā atslēga, kas atsaucas uz savienojumu
// self::HAS_MANY = ārējā atslēga, kas atsaucas uz savienojumu
// self::BELONGS_TO = lokālā atslēga, kas atsaucas uz savienojumu
'local_or_foreign_key',
// tikai FYI, tas arī pievienojas tikai uz "citas" modeļa primāro atslēgu
// izvēles
[ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // papildu nosacījumi, ko vēlaties, pievienojoties attiecībai
// $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5))
// izvēles
'back_reference_name' // tas ir, ja vēlaties atpakaļatsauce uz šo attiecību atpakaļ uz sevi Piem: $user->contact->user;
];
]
class User extends ActiveRecord{
protected array $relations = [
'contacts' => [ self::HAS_MANY, Contact::class, 'user_id' ],
'contact' => [ self::HAS_ONE, Contact::class, 'user_id' ],
];
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
}
class Contact extends ActiveRecord{
protected array $relations = [
'user' => [ self::BELONGS_TO, User::class, 'user_id' ],
'user_with_backref' => [ self::BELONGS_TO, User::class, 'user_id', [], 'contact' ],
];
public function __construct($database_connection)
{
parent::__construct($database_connection, 'contacts');
}
}
Tagad mums ir atsauces iestatītas, lai mēs varētu izmantot tās ļoti viegli!
$user = new User($pdo_connection);
// atrast jaunāko lietotāju.
$user->notNull('id')->orderBy('id desc')->find();
// iegūt kontaktus, izmantojot attiecību:
foreach($user->contacts as $contact) {
echo $contact->id;
}
// vai mēs varam iet otru ceļu.
$contact = new Contact();
// atrast vienu kontaktu
$contact->find();
// iegūt lietotāju, izmantojot attiecību:
echo $contact->user->name; // tas ir lietotāja vārds
Diezgan forši, vai ne?
Eager Loading
Pārskats
Eager loading atrisina N+1 vaicājuma problēmu, iepriekš ielādējot attiecības. Tā vietā, lai izpildītu atsevišķu vaicājumu katrai ieraksta attiecībai, eager loading iegūst visus saistītos datus tikai vienā papildu vaicājumā uz attiecību.
Piezīme: Eager loading ir pieejams tikai v0.7.0 un augstāk.
Pamatlietošana
Izmantojiet with() metodi, lai norādītu, kuras attiecības eager ielādēt:
// Ielādēt lietotājus ar viņu kontaktiem 2 vaicājumos, nevis N+1
$users = $user->with('contacts')->findAll();
foreach ($users as $u) {
foreach ($u->contacts as $contact) {
echo $contact->email; // Nav papildu vaicājuma!
}
}
Vairākas attiecības
Ielādēt vairākas attiecības uzreiz:
$users = $user->with(['contacts', 'profile', 'settings'])->findAll();
Attiecību veidi
HAS_MANY
// Eager ielādēt visus kontaktus katram lietotājam
$users = $user->with('contacts')->findAll();
foreach ($users as $u) {
// $u->contacts jau ir ielādēts kā masīvs
foreach ($u->contacts as $contact) {
echo $contact->email;
}
}
HAS_ONE
// Eager ielādēt vienu kontaktu katram lietotājam
$users = $user->with('contact')->findAll();
foreach ($users as $u) {
// $u->contact jau ir ielādēts kā objekts
echo $u->contact->email;
}
BELONGS_TO
// Eager ielādēt vecāku lietotājus visiem kontaktiem
$contacts = $contact->with('user')->findAll();
foreach ($contacts as $c) {
// $c->user jau ir ielādēts
echo $c->user->name;
}
Ar find()
Eager loading darbojas ar findAll() un find() :
$user = $user->with('contacts')->find(1);
// Lietotājs un visi viņu kontakti ielādēti 2 vaicājumos
Veiktspējas priekšrocības
Bez eager loading (N+1 problēma):
$users = $user->findAll(); // 1 vaicājums
foreach ($users as $u) {
$contacts = $u->contacts; // N vaicājumi (viens uz lietotāju!)
}
// Kopā: 1 + N vaicājumi
Ar eager loading:
$users = $user->with('contacts')->findAll(); // 2 vaicājumi kopā
foreach ($users as $u) {
$contacts = $u->contacts; // 0 papildu vaicājumi!
}
// Kopā: 2 vaicājumi (1 lietotājiem + 1 visiem kontaktiem)
10 lietotājiem tas samazina vaicājumus no 11 līdz 2 - 82% samazinājums!
Svarīgas piezīmes
- Eager loading ir pilnīgi izvēles - lazy loading joprojām darbojas kā iepriekš
- Jau ielādētās attiecības automātiski tiek izlaistas
- Atpakaļatsauces darbojas ar eager loading
- Attiecību atsauces tiek ievērotas eager loading laikā
Ierobežojumi
- Ieslēgtas eager loading (piem., with(['contacts.addresses']) ) pašlaik netiek atbalstīts
- Eager load ierobežojumi caur aizvērumiem nav atbalstīti šajā versijā
Pielāgota datu iestatīšana
Dažreiz jums var būt nepieciešams pievienot kaut ko unikālu jūsu ActiveRecord, piemēram, pielāgotu aprēķinu, kas varētu būt vieglāk pievienot objektam, kas tad tiks nodots, teiksim, šablonam.
setCustomData(string $field, mixed $value)
Jūs pievienojat pielāgoto datu ar setCustomData() metodi.
$user->setCustomData('page_view_count', $page_view_count);
Un tad jūs vienkārši atsaucaties uz to kā uz normālu objekta īpašību.
echo $user->page_view_count;
Notikumi
Viens vairāk super lielisks elements par šo bibliotēku ir par notikumiem. Notikumi tiek izraisīti noteiktos laikos, balstoties uz noteiktām metodēm, ko jūs saucat. Tie ir ļoti noderīgi, lai automātiski iestatītu datus jums.
onConstruct(ActiveRecord $ActiveRecord, array &config)
Tas ir patiešām noderīgi, ja jums ir nepieciešams iestatīt noklusējuma savienojumu vai kaut ko tādu.
// index.php vai bootstrap.php
Flight::register('db', 'PDO', [ 'sqlite:test.db' ]);
//
//
//
// User.php
class User extends flight\ActiveRecord {
protected function onConstruct(self $self, array &$config) { // neaizmirstiet & atsauci
// jūs varētu to darīt, lai automātiski iestatītu savienojumu
$config['connection'] = Flight::db();
// vai to
$self->transformAndPersistConnection(Flight::db());
// Jūs varat arī iestatīt tabulas nosaukumu šādi.
$config['table'] = 'users';
}
}
beforeFind(ActiveRecord $ActiveRecord)
Tas, visticamāk, ir noderīgi tikai tad, ja jums ir nepieciešama vaicājuma manipulācija katru reizi.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeFind(self $self) {
// vienmēr palaidiet id >= 0, ja tas ir jūsu stils
$self->gte('id', 0);
}
}
afterFind(ActiveRecord $ActiveRecord)
Šis, visticamāk, ir noderīgāks, ja jums vienmēr ir jāpalaid kaut kāda loģika katru reizi, kad šis ieraksts tiek iegūts. Vai jums ir jāšifrē kaut kas? Vai jums ir jāpalaid pielāgots skaita vaicājums katru reizi (nav efektīvi, bet nu labi)?
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterFind(self $self) {
// šifrēšana kaut kā
$self->secret = yourDecryptFunction($self->secret, $some_key);
// varbūt saglabājot kaut ko pielāgotu kā vaicājumu???
$self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count'];
}
}
beforeFindAll(ActiveRecord $ActiveRecord)
Tas, visticamāk, ir noderīgi tikai tad, ja jums ir nepieciešama vaicājuma manipulācija katru reizi.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeFindAll(self $self) {
// vienmēr palaidiet id >= 0, ja tas ir jūsu stils
$self->gte('id', 0);
}
}
afterFindAll(array<int,ActiveRecord> $results)
Līdzīgs afterFind(), bet jūs varat to darīt visiem ierakstiem!
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterFindAll(array $results) {
foreach($results as $self) {
// dariet kaut ko foršu kā afterFind()
}
}
}
beforeInsert(ActiveRecord $ActiveRecord)
Patiešām noderīgi, ja jums ir nepieciešams iestatīt noklusējuma vērtības katru reizi.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeInsert(self $self) {
// iestatīt dažus labus noklusējumus
if(!$self->created_date) {
$self->created_date = gmdate('Y-m-d');
}
if(!$self->password) {
$self->password = password_hash((string) microtime(true));
}
}
}
afterInsert(ActiveRecord $ActiveRecord)
Varbūt jums ir gadījums, kad mainīt datus pēc ievietošanas?
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterInsert(self $self) {
// dariet, ko vēlaties
Flight::cache()->set('most_recent_insert_id', $self->id);
// vai ko citu....
}
}
beforeUpdate(ActiveRecord $ActiveRecord)
Patiešām noderīgi, ja jums ir nepieciešams iestatīt noklusējuma vērtības katru reizi atjauninājumā.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeInsert(self $self) {
// iestatīt dažus labus noklusējumus
if(!$self->updated_date) {
$self->updated_date = gmdate('Y-m-d');
}
}
}
afterUpdate(ActiveRecord $ActiveRecord)
Varbūt jums ir gadījums, kad mainīt datus pēc atjaunināšanas?
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterInsert(self $self) {
// dariet, ko vēlaties
Flight::cache()->set('most_recently_updated_user_id', $self->id);
// vai ko citu....
}
}
beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)
Tas ir noderīgi, ja vēlaties, lai notikumi notiktu gan ievietošanas, gan atjauninājuma laikā. Es jūs saīsināšu no gara skaidrojuma, bet esmu pārliecināts, ka jūs varat uzminēt, kas tas ir.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeSave(self $self) {
$self->last_updated = gmdate('Y-m-d H:i:s');
}
}
beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)
Neesmu pārliecināts, ko jūs vēlētos darīt šeit, bet bez tiesājumiem! Dodieties!
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeDelete(self $self) {
echo 'Viņš bija drosmīgs karavīrs... :cry-face:';
}
}
Datubāzes savienojuma pārvaldība
Izmantojot šo bibliotēku, jūs varat iestatīt datubāzes savienojumu dažādos veidos. Jūs varat iestatīt savienojumu konstruktorā, varat iestatīt to caur konfigurācijas mainīgo $config['connection'] vai varat iestatīt to caur setDatabaseConnection() (v0.4.1).
$pdo_connection = new PDO('sqlite:test.db'); // piemēram
$user = new User($pdo_connection);
// vai
$user = new User(null, [ 'connection' => $pdo_connection ]);
// vai
$user = new User();
$user->setDatabaseConnection($pdo_connection);
Ja vēlaties izvairīties no $database_connection iestatīšanas katru reizi, kad saucat active record, ir veidi ap to!
// index.php vai bootstrap.php
// Iestatīt to kā reģistrētu klasi Flight
Flight::register('db', 'PDO', [ 'sqlite:test.db' ]);
// User.php
class User extends flight\ActiveRecord {
public function __construct(array $config = [])
{
$database_connection = $config['connection'] ?? Flight::db();
parent::__construct($database_connection, 'users', $config);
}
}
// Un tagad nav nepieciešami argumenti!
$user = new User();
Piezīme: Ja plānojat veikt unit testēšanu, darot to šādi, tas var pievienot dažus izaicinājumus unit testēšanai, bet kopumā, jo jūs varat injicēt savu savienojumu ar
setDatabaseConnection()vai$config['connection'], tas nav pārāk slikti.
Ja jums ir jāatjauno datubāzes savienojums, piemēram, ja palaižat ilgu CLI skriptu un ir jāatjauno savienojums ik pa laikam, jūs varat atkārtoti iestatīt savienojumu ar $your_record->setDatabaseConnection($pdo_connection).
Iesaiste
Lūdzu, dariet. :D
Iestatīšana
Kad jūs iesaistāties, pārliecinieties, ka palaižat composer test-coverage, lai uzturētu 100% testa pārklājumu (tas nav īsts unit testa pārklājums, vairāk kā integrācijas testēšana).
Arī pārliecinieties, ka palaižat composer beautify un composer phpcs, lai labotu jebkādas linting kļūdas.
Licence
MIT
Awesome-plugins/latte
Latte
Latte ir pilnvērtīgs veidņu dz motor, kas ir ļoti viegli lietojams un jūtas tuvāk PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas.
Instalācija
Instalējiet ar composer.
composer require latte/latte
Pamata konfigurācija
Ir dažas pamata konfigurācijas opcijas, lai sāktu. Jūs varat lasīt vairāk par tām Latte dokumentācijā.
require 'vendor/autoload.php';
$app = Flight::app();
$app->map('render', function(string $template, array $data, ?string $block): void {
$latte = new Latte\Engine;
// Kur latte specifiski glabā savu kešu
$latte->setTempDirectory(__DIR__ . '/../cache/');
$finalPath = Flight::get('flight.views.path') . $template;
$latte->render($finalPath, $data, $block);
});
Vienkāršs izkārtojuma piemērs
Šeit ir vienkāršs izkārtojuma faila piemērs. Šis ir fails, kas tiks izmantots, lai aptvertu visas jūsu citas skatus.
<!-- app/views/layout.latte -->
<!doctype html>
<html lang="en">
<head>
<title>{$title ? $title . ' - '}My App</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<nav>
<!-- jūsu navigācijas elementi šeit -->
</nav>
</header>
<div id="content">
<!-- Šī ir maģija šeit -->
{block content}{/block}
</div>
<div id="footer">
© Copyright
</div>
</body>
</html>
Un tagad mums ir jūsu fails, kas tiks renderēts tajā satura blokā:
<!-- app/views/home.latte -->
<!-- Tas pasaka Latte, ka šis fails ir "iekšā" layout.latte failā -->
{extends layout.latte}
<!-- Šis ir saturs, kas tiks renderēts izkārtojumā satura blokā -->
{block content}
<h1>Sākumlapa</h1>
<p>Sveiki manā lietotnē!</p>
{/block}
Pēc tam, kad jūs dodaties renderēt to savā funkcijā vai kontrolierī, jūs darītu kaut ko šādu:
// vienkāršs maršruts
Flight::route('/', function () {
Flight::render('home.latte', [
'title' => 'Sākumlapa'
]);
});
// vai ja jūs izmantojat kontrollieri
Flight::route('/', [HomeController::class, 'index']);
// HomeController.php
class HomeController
{
public function index()
{
Flight::render('home.latte', [
'title' => 'Sākumlapa'
]);
}
}
Skatiet Latte dokumentāciju, lai iegūtu vairāk informācijas par to, kā izmantot Latte pilnā potenciālā!
Kļūdu labošana ar Tracy
PHP 8.1+ ir nepieciešams šai sadaļai.
Jūs varat izmantot arī Tracy, lai palīdzētu ar jūsu Latte veidņu failu kļūdu labošanu tieši no kastes! Ja jums jau ir instalēts Tracy, jums jāpievieno Latte paplašinājums Tracy.
// services.php
use Tracy\Debugger;
$app->map('render', function(string $template, array $data, ?string $block): void {
$latte = new Latte\Engine;
// Kur latte specifiski glabā savu kešu
$latte->setTempDirectory(__DIR__ . '/../cache/');
$finalPath = Flight::get('flight.views.path') . $template;
// Tas pievienos paplašinājumu tikai tad, ja ir iespējota Tracy atkļūdošanas josla
if (Debugger::$showBar === true) {
// šeit jūs pievienojat Latte paneli Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
}
$latte->render($finalPath, $data, $block);
});Awesome-plugins/awesome_plugins
Brīnišķīgi spraudņi
Flight ir neticami paplašināms. Ir pieejami vairāki spraudņi, kurus var izmantot, lai pievienotu funkcionalitāti Flight lietotnei. Daži no tiem ir oficiāli atbalstīti Flight komandas, bet citi ir mikro/viegli risinājumi, kas palīdz sākt darbu.
MI rīki
Flight var padarīt vēl foršāku ar MI darbināmiem spraudņiem.
- Flight MCP - Spraudnis MCP (Model Control Protocol) integrēšanai ar Flight, nodrošinot vienmērīgu MI darbināmu funkcionalitāti. Galvenokārt vērsts uz dokumentācijas lapām, tas palīdz samazināt token izmaksas, nodrošinot aktuālāko informāciju par Flight projektiem.
API dokumentācija
API dokumentācija ir būtiska jebkurai API. Tas palīdz izstrādātājiem saprast, kā mijiedarboties ar API un ko sagaidīt pretī. Ir pieejami daži rīki, kas palīdz ģenerēt API dokumentāciju Flight projektiem.
- FlightPHP OpenAPI Generator - Daniel Schreiber bloga ieraksts par to, kā izmantot OpenAPI Spec ar FlightPHP, lai izveidotu API, izmantojot API pirmo pieeju.
- SwaggerUI - Swagger UI ir lielisks rīks, kas palīdz ģenerēt API dokumentāciju Flight projektiem. Tas ir ļoti viegli lietojams un var tikt pielāgots jūsu vajadzībām. Šī ir PHP bibliotēka, kas palīdz ģenerēt Swagger dokumentāciju.
Lietotnes veiktspējas uzraudzība (APM)
Lietotnes veiktspējas uzraudzība (APM) ir būtiska jebkurai lietotnei. Tas palīdz izprast, kā darbojas lietotne un kur ir sastrēgumi. Ir pieejami vairāki APM rīki, kurus var izmantot ar Flight.
- official flightphp/apm - Flight APM ir vienkārša APM bibliotēka, ko var izmantot Flight lietotņu uzraudzībai. To var izmantot, lai uzraudzītu lietotnes veiktspēju un palīdzētu identificēt sastrēgumus.
Asinhronā apstrāde
Flight jau ir ātrs ietvars, bet turbodzinēja pievienošana padara visu vēl aizraujošāku (un izaicināmāku)!
- flightphp/async - Oficiālā Flight Async bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot asinhronu apstrādi lietotnei. Tā izmanto Swoole/Openswoole dziļākā līmenī, lai nodrošinātu vienkāršu un efektīvu veidu asinhronu uzdevumu izpildei.
Autorizācija/Pieejas tiesības
Autorizācija un pieejas tiesības ir būtiskas jebkurai lietotnei, kurai nepieciešamas kontroles, lai noteiktu, kurš var piekļūt kam.
- official flightphp/permissions - Oficiālā Flight Permissions bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot lietotāju un lietotnes līmeņa pieejas tiesības lietotnei.
Autentifikācija
Autentifikācija ir būtiska lietotnēm, kurām nepieciešams verificēt lietotāja identitāti un nodrošināt API galapunktus.
- firebase/php-jwt - JSON Web Token (JWT) bibliotēka PHP. Vienkāršs un drošs veids, kā ieviest token balstītu autentifikāciju Flight lietotnēs. Ideāli piemērots bezstāvokļa API autentifikācijai, maršrutu aizsardzībai ar starpprogrammatūru un OAuth stila autorizācijas plūsmu ieviešanai.
Kešatmiņa
Kešatmiņa ir lielisks veids, kā paātrināt lietotni. Ir pieejamas vairākas kešatmiņas bibliotēkas, kuras var izmantot ar Flight.
- official flightphp/cache - Vieglā, vienkāršā un patstāvīgā PHP failu kešatmiņas klase
CLI
CLI lietotnes ir lielisks veids, kā mijiedarboties ar lietotni. Jūs varat tās izmantot, lai ģenerētu kontrolierus, parādītu visus maršrutus un vairāk.
- official flightphp/runway - Runway ir CLI lietotne, kas palīdz pārvaldīt Flight lietotnes.
Sīkdatnes
Sīkdatnes ir lielisks veids, kā saglabāt nelielus datu fragmentus klienta pusē. Tās var izmantot, lai saglabātu lietotāja preferences, lietotnes iestatījumus un vairāk.
- overclokk/cookie - PHP Cookie ir PHP bibliotēka, kas nodrošina vienkāršu un efektīvu veidu, kā pārvaldīt sīkdatnes.
Atkļūdošana
Atkļūdošana ir būtiska, kad izstrādājat lokālajā vidē. Ir daži spraudņi, kas var uzlabot jūsu atkļūdošanas pieredzi.
- tracy/tracy - Šis ir pilnībā aprīkots kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas palīdz atkļūdot lietotni. Tas ir arī ļoti viegli paplašināms un var pievienot savus paneļus.
- official flightphp/tracy-extensions - Izmantojot Tracy kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar atkļūdošanu specifiski Flight projektiem.
Datubāzes
Datubāzes ir lielākās daļas lietotņu kodols. Tā ir vieta, kur saglabāt un iegūt datus. Dažas datubāzes bibliotēkas ir vienkārši aploki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM sistēmas.
- official flightphp/core SimplePdo - Oficiālais Flight PDO palīgs, kas ir daļa no kodola. Tas ir moderns aploks ar ērtām palīgmetodēm, piemēram,
insert(),update(),delete()untransaction(), lai vienkāršotu datubāzes operācijas. Visi rezultāti tiek atgriezti kā Collections, lai nodrošinātu elastīgu masīva/objekta piekļuvi. Nav ORM, tikai labāks veids, kā strādāt ar PDO. - deprecated flightphp/core PdoWrapper - Oficiālais Flight PDO aploks, kas ir daļa no kodola (novecojis kopš v3.18.0). Izmantojiet SimplePdo vietā.
- official flightphp/active-record - Oficiālais Flight ActiveRecord ORM/Mapper. Lieliska maza bibliotēka, lai viegli iegūtu un saglabātu datus datubāzē.
- byjg/php-migration - Spraudnis, lai sekotu līdzi visām datubāzes izmaiņām projektā.
- knifelemon/easy-query - Viegls, plūstošs SQL vaicājumu veidotājs, kas ģenerē SQL un parametrus sagatavotajiem vaicājumiem. Lieliski darbojas ar SimplePdo.
Šifrēšana
Šifrēšana ir būtiska jebkurai lietotnei, kas saglabā sensitīvus datus. Datus šifrēt un atšifrēt nav īpaši grūti, bet pareizi glabāt šifrēšanas atslēgu var būt sarežģīti. Vissvarīgākais ir nekad neglabāt šifrēšanas atslēgu publiskajā direktorijā vai to commit'ot kodā.
- defuse/php-encryption - Šī ir bibliotēka, ko var izmantot, lai šifrētu un atšifrētu datus. Darba sākšana ir diezgan vienkārša, lai sāktu šifrēt un atšifrēt datus.
Darbu rinda
Darbu rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas var būt e-pasta sūtīšana, attēlu apstrāde vai jebkas, kas nav jādara reālā laikā.
- n0nag0n/simple-job-queue - Simple Job Queue ir bibliotēka, ko var izmantot, lai asinhroni apstrādātu darbus. To var izmantot ar beanstalkd, MySQL/MariaDB, SQLite un PostgreSQL.
Sesija
Sesijas īsti nav noderīgas API, bet tīmekļa lietotnes izveidei sesijas var būt būtiskas stāvokļa un pieteikšanās informācijas uzturēšanai.
- official flightphp/session - Oficiālā Flight Session bibliotēka. Šī ir vienkārša sesijas bibliotēka, ko var izmantot, lai saglabātu un iegūtu sesijas datus. Tā izmanto PHP iebūvēto sesiju apstrādi.
- Ghostff/Session - PHP Session Manager (nebloķējošs, flash, segment, sesijas šifrēšana). Izmanto PHP open_ssl sesijas datu papildu šifrēšanai/atšifrēšanai.
Veidnes
Veidnes ir jebkuras tīmekļa lietotnes ar lietotāja saskarni kodols. Ir pieejami vairāki veidņu dzinēji, kurus var izmantot ar Flight.
- deprecated flightphp/core View - Šis ir ļoti vienkāršs veidņu dzinējs, kas ir daļa no kodola. Tas nav ieteicams izmantot, ja projektā ir vairāk nekā pāris lapas.
- latte/latte - Latte ir pilnībā aprīkots veidņu dzinējs, kas ir ļoti viegli lietojams un jūtās tuvāks PHP sintaksei nekā Twig vai Smarty. Tas ir arī ļoti viegli paplašināms un var pievienot savus filtrus un funkcijas.
- twig/twig - Twig ir elastīgs, ātrs un drošs veidņu dzinējs (tāds pats, kādu izmanto Symfony). MI rīki un daudzi PHP izstrādātāji to labi zina, tas automātiski aizsargā izvadi pēc noklusējuma un tam ir milzīga paplašinājumu ekosistēma.
- knifelemon/comment-template - CommentTemplate ir spēcīgs PHP veidņu dzinējs ar aktīvu kompilāciju, veidņu mantošanu un mainīgo apstrādi. Ietver automātisku CSS/JS minimizāciju, kešatmiņu, Base64 kodēšanu un papildu Flight PHP ietvara integrāciju.
WordPress integrācija
Vai vēlaties izmantot Flight WordPress projektā? Tam ir ērts spraudnis!
- n0nag0n/wordpress-integration-for-flight-framework - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāli piemērots, lai pievienotu pielāgotas API, mikropakalpojumus vai pat pilnas lietotnes WordPress vietnei, izmantojot Flight ietvaru. Īpaši noderīgi, ja vēlaties labāko no abām pasaulēm!
Ieguldījums
Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet pull request, lai to pievienotu sarakstam!
Media
Media
Mēs esam mēģinājuši izsekot dažādu veidu medijiem internetā par Flight. Skatiet zemāk dažādus resursus, kurus varat izmantot, lai uzzinātu vairāk par Flight.
Raksti un apraksti
- Unit Testing and SOLID Principles by Brian Fenton (2015?)
- PHP Web Framework Flight by ojambo (2025)
- Define, Generate, and Implement: An API-First Approach with OpenAPI Generator and FlightPHP by Daniel Schreiber (2025)
- Best PHP Micro Frameworks for 2024 by n0nag0n (2024)
- Creating a RESTful API with Flight Framework by n0nag0n (2024)
- Building a Simple Blog with Flight Part 2 by n0nag0n (2024)
- Building a Simple Blog with Flight Part 1 by n0nag0n (2024)
- 🚀 Build a Simple CRUD API in PHP with the Flight Framework by soheil-khaledabadi (2024)
- Building a PHP Web Application with the Flight Micro-framework by Arthur C. Codex (2023)
- Best PHP Frameworks for Web Development in 2024 by Ravikiran A S (2023)
- Top 12 PHP Frameworks: A Comprehensive Guide for 2023 by marketing kbk (2023)
- 5 PHP Frameworks You've (Probably) Never Heard of by n0nag0n (2022)
- 12 top PHP frameworks for web developers to consider in 2023 by Anna Monus (2022)
- The Best PHP Microframeworks on a Cloud Server by Shahzeb Ahmed (2021)
- PHP framework: Top 15 powerful ones for your web development by AHT Tech (2020)
- Easy PHP Routing with FlightPHP by Lucas Conceição (2019)
- Trying Out New PHP Framework (Flight) by Leon (2017)
- Setting up FlightPHP to work with Backbonejs by Timothy Tocci (2015)
Video un pamācības
- Build a Flight PHP App with MVC & MariaDB in 10 Minutes! (Beginner Friendly) by ojamboshop (2025)
- Create a REST API for IoT Devices Using PHP & FlightPHP - ESP32 API by IoT Craft Hub (2024)
- PHP Flight Framework Simple Introductory Video by n0nag0n (2024)
- Set header HTTP code in Flightphp (3 Solutions!!) by Roel Van de Paar (2024)
- PHP Flight Framework Tutorial. Super easy API Project! by n0nag0n (2022)
- Aplicación web CRUD con php y mysql y bootstrap usando flight by Devlopteca - Oscar Uh (2021)
- DevOps & SysAdmins: Lighttpd rewrite rule for Flight PHP microframework by Roel Van de Paar (2021)
- Tutorial REST API Flight PHP #PART2 INSERT TABLE Info #Code (Tagalog) by Info Singkat Official (2020)
- Tutorial REST API Flight PHP #PART1 Info #Code (Tagalog) by Info Singkat Official (2020)
- How To Create JSON REST API IN PHP - Part 2 by Codewife (2018)
- How To Create JSON REST API IN PHP - Part 1 by Codewife (2018)
- Teste Micro Frameworks PHP - Flight PHP, Lumen, Slim 3 e Laravel by Codemarket (2016)
- Tutorial 1 Flight PHP - Instalación by absagg (2014)
- Tutorial 2 Flight PHP - Route parte 1 by absagg (2014)
Trūkst kaut kas?
Vai mums trūkst kaut kas, ko jūs esat uzrakstījis vai ierakstījis? Informējiet mūs ar problēmas ziņojumu vai pull request!
Examples
Vai ātri sākt?
Jums ir divas opcijas, lai sāktu darbu ar jaunu Flight projektu:
- Pilns Skelets Boilerplate: Pilnīgāks piemērs ar kontrolieriem un skatiem.
- Vienkāršs Fails Skelets Boilerplate: Viens fails, kas ietver visu, kas nepieciešams, lai palaistu jūsu lietojumprogrammu vienā vienkāršā failā.
Kopienas sniegtie piemēri:
- flightravel: FlightPHP ar Laravel direktorijām, ar PHP rīkiem + GH Actions
- fleact - FlightPHP starter komplekts ar ReactJS integrāciju.
- flastro - FlightPHP starter komplekts ar Astro integrāciju.
- velt - Velt ir ātrs un viegls Svelte starter veidne ar FlightPHP backend.
- vite-flightphp - FlightPHP ar mūsdienu front-end (Vite + Tailwind CSS) un karstās atjaunināšanas funkciju.
Vai vajag iedvesmu?
Lai gan šie nav oficiāli atbalstīti no Flight komandas puses, tie var dot jums idejas, kā strukturēt savus pašu projektus, kas izveidoti ar Flight!
- ASC REST API Pareizrakstības pārbaudītājs - Viegls REST API arabu valodas pareizrakstības pārbaudei, izveidots ar FlightPHP un ArPHP bibliotēku. Šis API nodrošina arabu teksta pareizrakstības pārbaudes iespējas, tostarp nepareizi uzrakstītu vārdu atklāšanu un labošanas ieteikumus.
- Eventify - Eventify ir vienas lapas lietojumprogramma, kas savieno pasākumu organizētājus ar dalībniekiem. Izveidots ar PHP (FlightPHP), JavaScript un MySQL, tas ietver JWT autentifikāciju, pasākumu pārvaldību un RESTful API dokumentāciju, izmantojot OpenAPI.
- Ivox Auto Noma - Ivox Auto Noma ir vienas lapas, mobilajām ierīcēm draudzīga auto nomas tīmekļa lietojumprogramma, izveidota ar PHP (FlightPHP), JavaScript un MySQL. Tā atbalsta lietotāju reģistrāciju, pārlūkošanu un auto rezervēšanu, savukārt administratori var pārvaldīt auto, lietotājus un rezervācijas. Lietojumprogrammā ir REST API, JWT autentifikācija un atsaucīgs dizains modernai nomas pieredzei.
- Decay - Flight v3 ar HTMX un SleekDB, viss par zombijiem! (Demo)
- Flight Piemērs Blogs - Flight v3 ar vidutājprogrammu, kontrolieriem, Active Record un Latte.
- Flight CRUD RESTful API - Vienkāršs CRUD API projekts, izmantojot Flight ietvaru, kas nodrošina pamata struktūru jauniem lietotājiem, lai ātri iestatītu PHP lietojumprogrammu ar CRUD operācijām un datubāzes savienojumu. Projekts demonstrē, kā izmantot Flight RESTful API izstrādei, padarot to par ideālu mācību rīku iesācējiem un noderīgu starter komplektu pieredzējušākiem izstrādātājiem.
- Flight Skolas Pārvaldības Sistēma - Flight v3
- Paste Bin ar Komentāriem - Flight v3
- Pamata Skelets Lietojumprogramma
- Piemērs Viki
- The IT-Innovator PHP Framework Lietojumprogramma
- LittleEducationalCMS (Spāņu)
- Itāļu Dzelteno Lappušu API
- Vispārīga Satura Pārvaldības Sistēma (ar....ļoti maz dokumentācijas)
- Mazs php ietvars balstīts uz Flight un medoo.
- Piemērs MVC Lietojumprogramma
- Ražošanai gatavs Flight Boilerplate - Ražošanai gatavs autentifikācijas ietvars, kas ietaupa nedēļām ilgu izstrādi. Ietver uzņēmuma līmeņa drošību: 2FA/TOTP, LDAP integrācija, Azure SSO, inteliģenta ātruma ierobežošana, sesijas pirkstu nospiedumu, aizsardzība pret brutālu spēku, drošības analītikas panelis, visaptveroša auditēšanas žurnālošana un granulēta loma balstīta piekļuves kontrole.
Vai vēlaties Dalīties ar Savu Piemēru?
Ja jums ir projekts, kuru vēlaties dalīt, lūdzu, iesniedziet pull request, lai to pievienotu šim sarakstam!
Install/install
Instalēšanas instrukcijas
Pirms varat instalēt Flight, ir daži pamata priekšnosacījumi. Proti, jums būs nepieciešams:
- Instalēt PHP savā sistēmā
- Instalēt Composer, lai iegūtu vislabāko izstrādātāja pieredzi.
Pamata instalācija
Ja izmantojat Composer, varat izpildīt šo komandu:
composer require flightphp/core
Tas jūsu sistēmā ievietos tikai Flight kodola failus. Jums būs jādefinē projekta struktūra, izkārtojums, atkarības, konfigurācijas, automātiskā ielāde utt. Šī metode nodrošina, ka netiek instalētas citas atkarības, izņemot Flight.
Varat arī lejupielādēt failus tieši un izvilkt tos savā tīmekļa direktorijā.
Pamata instalācija ir lieliski piemērota mācībām, mikro API un kopēšanas-ielīmēšanas eksperimentiem. Lai iegūtu pilnu lietotnes izkārtojumu, kam cilvēki un AI kodēšanas rīki var sekot vienādi, izmantojiet zemāk ieteikto skeletu.
Ieteicamā instalācija
Ļoti ieteicams sākt ar flightphp/skeleton lietotni jebkuram jaunam projektam. Instalācija ir vienkārša.
composer create-project flightphp/skeleton my-project/
cd my-project/
composer start
# neobligāta parauga DB + ierakstu demonstrācija
php runway migrate
Šis solis izveido projekta struktūru, Composer PSR-4 automātisko ielādi, konfigurāciju un rīkus, piemēram, Tracy, Tracy paplašinājumus un Runway. Tas ietver arī saknes AGENTS.md failu (un ierobežotas kopijas zem app/), lai AI asistenti dalītos ar jums vienā izkārtojumā — skatiet AI un izstrādātāja pieredze.
Ko sniedz skeleton lietotne
project-root/
├── AGENTS.md # AI / aģentu patiesības avots
├── SECURITY.md # Drošības gaidības
├── .env.example # Noslēpumi / izvietošanas pārklājumi (kopēts uz .env)
├── public/index.php # Tikai tīmekļa ieejas punkts
├── app/
│ ├── config/ # bootstrap, maršruti, pakalpojumi, config_sample.php
│ ├── Controller/ # App\Controller\* (PascalCase mape!)
│ ├── Middleware/ # App\Middleware\*
│ ├── Model/ # App\Model\* (ActiveRecord)
│ ├── Utils/ # Config, Env, DatabaseFactory
│ ├── commands/ # Runway CLI komandas
│ ├── views/ # Twig veidnes (*.twig)
│ ├── cache/
│ └── log/
├── migrations/ # SQL migrācijas (.sql / .mysql.sql)
└── tests/ # PHPUnit
Nosaukumvietas seko mapes reģistram. Composer kartē "App\\": "app/", tāpēc:
| Ceļš uz diska | Nosaukumvieta |
|---|---|
app/Controller/HomeController.php |
App\Controller\HomeController |
app/Middleware/… |
App\Middleware\… |
app/Model/… |
App\Model\… |
app/Utils/… |
App\Utils\… |
Operētājsistēmā Linux app/controller/ nav tas pats, kas app/Controller/. Automātiskā ielāde ir reģistrjutīga — atbilst skeleton PascalCase mapēm. Detalizēti: Automātiskā ielāde.
Noklusējuma kopums (jauni projekti): Twig skati, SimplePdo + ActiveRecord, Dice ar Engine ievadīšanu (vēlams izvairīties no Flight:: lietotnes klasēs), neobligāta SQLite pēc php runway migrate.
create-project parasti kopē app/config/config_sample.php → config.php un .env.example → .env, ja tādi ir. Maršruti atrodas app/config/routes.php; pakalpojumi un DI atrodas app/config/services.php.
Dokumentācija ↔ skeleton: Šie dokumenti māca Flight API (bieži ar īsiem
Flight::piemēriem). Skeleton nosaka lietotnes struktūru. Pievienojot kodu zemapp/, sekojiet skeleton kokam; izmantojiet dokumentus metožu nosaukumiem, opcijām un spraudņiem.
Konfigurējiet savu tīmekļa serveri
Iebūvētais PHP izstrādes serveris
Šis ir visvienkāršākais veids, kā sākt darbu. Varat izmantot iebūvēto serveri, lai palaistu savu lietotni, un pat izmantot SQLite kā datubāzi (ja vien sqlite3 ir instalēts jūsu sistēmā), un nekas daudz nav nepieciešams! Vienkārši izpildiet šo komandu pēc PHP instalēšanas:
php -S localhost:8000
# vai ar skeleton lietotni
composer start
Pēc tam atveriet pārlūkprogrammu un dodieties uz http://localhost:8000.
Ja vēlaties, lai jūsu projekta dokumentu sakne būtu cita direktorija (piem., jūsu projekts ir ~/myproject, bet dokumentu sakne ir ~/myproject/public/), varat izpildīt šo komandu, kad esat ~/myproject direktorijā:
php -S localhost:8000 -t public/
# ar skeleton lietotni tas jau ir konfigurēts
composer start
Pēc tam atveriet pārlūkprogrammu un dodieties uz http://localhost:8000.
Apache
Pārliecinieties, ka Apache ir instalēts jūsu sistēmā. Ja nav, meklējiet internetā, kā instalēt Apache savā sistēmā.
Apache gadījumā rediģējiet savu .htaccess failu ar šādu saturu:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
Piezīme: Ja jums jāizmanto Flight apakšdirektorijā, pievienojiet rindu
RewriteBase /subdir/tūlīt pēcRewriteEngine On.
Piezīme: Ja vēlaties aizsargāt visus servera failus, piemēram, db vai env failu. Ievietojiet to savā
.htaccessfailā:
RewriteEngine On
RewriteRule ^(.*)$ index.php
Nginx
Pārliecinieties, ka Nginx ir instalēts jūsu sistēmā. Ja nav, meklējiet internetā, kā instalēt Nginx savā sistēmā.
Nginx gadījumā pievienojiet savai servera deklarācijai šādu konfigurāciju:
server {
location / {
try_files $uri $uri/ /index.php;
}
}
Izveidojiet savu index.php failu
Ja veicat pamata instalāciju, jums būs nepieciešams kods, lai sāktu darbu.
<?php
// Ja izmantojat Composer, iekļaujiet autoloader.
require 'vendor/autoload.php';
// ja neizmantojat Composer, ielādējiet ietvaru tieši
// require 'flight/Flight.php';
// Pēc tam definējiet maršrutu un piešķiriet funkciju pieprasījuma apstrādei.
Flight::route('/', function () {
echo 'hello world!';
});
// Visbeidzot, palaidiet ietvaru.
Flight::start();
Skeleton lietotnē publiskais ieejas punkts tikai palaiž lietotni. Maršruti tiek reģistrēti app/config/routes.php (parasti [App\Controller\…::class, 'method'], lai Dice varētu ievadīt atkarības). Pakalpojumi, Twig, SimplePdo un konteiners ir savienoti app/config/services.php. Šī struktūra ir apzināta, lai AI rīki un cilvēki katru reizi rediģētu tās pašas vietas.
PHP instalēšana
Ja jūsu sistēmā jau ir instalēts php, izlaidiet šīs instrukcijas un pārejiet uz lejupielādes sadaļu
macOS
PHP instalēšana, izmantojot Homebrew
-
Instalējiet Homebrew (ja vēl nav instalēts):
- Atveriet termināli un izpildiet:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- Atveriet termināli un izpildiet:
-
Instalējiet PHP:
- Instalējiet jaunāko versiju:
brew install php - Lai instalētu konkrētu versiju, piemēram, PHP 8.1:
brew tap shivammathur/php brew install shivammathur/php/php@8.1
- Instalējiet jaunāko versiju:
-
Pārslēgties starp PHP versijām:
- Atsaistiet pašreizējo versiju un saistiet vēlamo versiju:
brew unlink php brew link --overwrite --force php@8.1 - Pārbaudiet instalēto versiju:
php -v
- Atsaistiet pašreizējo versiju un saistiet vēlamo versiju:
Windows 10/11
PHP manuāla instalēšana
-
Lejupielādējiet PHP:
- Apmeklējiet PHP for Windows un lejupielādējiet jaunāko vai konkrētu versiju (piem., 7.4, 8.0) kā ne-thread-safe zip failu.
-
Izvelciet PHP:
- Izvelciet lejupielādēto zip failu uz
C:\php.
- Izvelciet lejupielādēto zip failu uz
-
Pievienojiet PHP sistēmas PATH:
- Dodieties uz Sistēmas rekvizīti > Vides mainīgie.
- Sadaļā Sistēmas mainīgie atrodiet Path un noklikšķiniet Rediģēt.
- Pievienojiet ceļu
C:\php(vai kur vien izvilkāt PHP). - Noklikšķiniet OK, lai aizvērtu visus logus.
-
Konfigurējiet PHP:
- Kopējiet
php.ini-developmentuzphp.ini. - Rediģējiet
php.ini, lai konfigurētu PHP pēc vajadzības (piem., iestatotextension_dir, iespējojot paplašinājumus).
- Kopējiet
-
Pārbaudiet PHP instalāciju:
- Atveriet komandu uzvedni un izpildiet:
php -v
- Atveriet komandu uzvedni un izpildiet:
Vairāku PHP versiju instalēšana
-
Atkārtojiet iepriekš minētās darbības katrai versijai, ievietojot katru atsevišķā direktorijā (piem.,
C:\php7,C:\php8). -
Pārslēdzieties starp versijām, pielāgojot sistēmas PATH mainīgo, lai tas norādītu uz vēlamo versijas direktoriju.
Ubuntu (20.04, 22.04 utt.)
PHP instalēšana, izmantojot apt
-
Atjauniniet pakotņu sarakstus:
- Atveriet termināli un izpildiet:
sudo apt update
- Atveriet termināli un izpildiet:
-
Instalējiet PHP:
- Instalējiet jaunāko PHP versiju:
sudo apt install php - Lai instalētu konkrētu versiju, piemēram, PHP 8.1:
sudo apt install php8.1
- Instalējiet jaunāko PHP versiju:
-
Instalējiet papildu moduļus (neobligāti):
- Piemēram, lai instalētu MySQL atbalstu:
sudo apt install php8.1-mysql
- Piemēram, lai instalētu MySQL atbalstu:
-
Pārslēgties starp PHP versijām:
- Izmantojiet
update-alternatives:sudo update-alternatives --set php /usr/bin/php8.1
- Izmantojiet
-
Pārbaudiet instalēto versiju:
- Izpildiet:
php -v
- Izpildiet:
Rocky Linux
PHP instalēšana, izmantojot yum/dnf
-
Iespējojiet EPEL krātuvi:
- Atveriet termināli un izpildiet:
sudo dnf install epel-release
- Atveriet termināli un izpildiet:
-
Instalējiet Remi krātuvi:
- Izpildiet:
sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm sudo dnf module reset php
- Izpildiet:
-
Instalējiet PHP:
- Lai instalētu noklusējuma versiju:
sudo dnf install php - Lai instalētu konkrētu versiju, piemēram, PHP 7.4:
sudo dnf module install php:remi-7.4
- Lai instalētu noklusējuma versiju:
-
Pārslēgties starp PHP versijām:
- Izmantojiet
dnfmoduļa komandu:sudo dnf module reset php sudo dnf module enable php:remi-8.0 sudo dnf install php
- Izmantojiet
-
Pārbaudiet instalēto versiju:
- Izpildiet:
php -v
- Izpildiet:
Vispārīgas piezīmes
- Izstrādes vidēs ir svarīgi konfigurēt PHP iestatījumus atbilstoši jūsu projekta prasībām.
- Pārslēdzot PHP versijas, pārliecinieties, ka visi attiecīgie PHP paplašinājumi ir instalēti konkrētajai versijai, kuru plānojat izmantot.
- Restartējiet savu tīmekļa serveri (Apache, Nginx utt.) pēc PHP versiju maiņas vai konfigurāciju atjaunināšanas, lai izmaiņas stātos spēkā.
Guides
Ceļveži
Flight PHP ir izstrādāts, lai būtu vienkāršs, bet spēcīgs, un mūsu ceļveži palīdzēs jums izveidot reālas pasaules aplikācijas solis pa solim. Šie praktiskie pamācību materiāli vada jūs cauri pilnīgiem projektiem, lai demonstrētu, kā Flight var tikt izmantots efektīvi.
Oficiālie ceļveži
Būvējot emu blogu
Uzziniet, kā izveidot funkcionējošu bloga aplikāciju ar Flight PHP. Šis ceļvedis vada jūs cauri:
- Projekta struktūras izveidošanai
- Darbam ar veidnēm, izmantojot Latte
- Maršrutu ieviešanai ierakstiem
- Datu glabāšanai un izgūšanai
- Formu iesniegumu apstrādei
- Pamata kļūdu apstrādei
Šī pamācība ir ideāla iesācējiem, kuri vēlas redzēt, kā visi elementi sader kopā reālā aplikācijā.
Vienības testēšana un SOLID principi
Šis ceļvedis aptver vienības testēšanas pamatus Flight PHP aplikācijās. Tajā ietilpst:
- PHPUnit iestatīšana
- Testējama koda rakstīšana, izmantojot SOLID principus
- Atkarību mockošana
- Biežās kļūdas, kuras izvairīties
- Testu mērogošana, kad jūsu aplikācija aug Šī pamācība ir ideāla izstrādātājiem, kuri vēlas uzlabot koda kvalitāti un uzturējamību.
Neoficiālie ceļveži
Kaut arī šie ceļveži netiek oficiāli uzturēti Flight komandas, tie ir vērtīgi resursi, kurus izveidojusi kopiena. Tie aptver dažādas tēmas un lietošanas gadījumus, sniedzot papildu ieskatus Flight PHP izmantošanā.
Creating a RESTful API with Flight Framework
Šis ceļvedis vada jūs cauri RESTful API izveidošanai, izmantojot Flight PHP framework. Tajā tiek apskatīti API iestatīšanas pamati, maršrutu definēšana un JSON atbilžu atgriešana.
Building a Simple Blog
Šis ceļvedis vada jūs cauri vienkārša bloga izveidošanai, izmantojot Flight PHP framework. Tajā faktiski ir 2 daļas: viena, lai aptvertu pamatus, un otra, lai apskatītu vairāk uzlabotus tēmus un uzlabojumus ražošanas gatavam blogam.
- Building a Simple Blog with Flight - Part 1 - Sākt ar vienkāršu blogu.
- Building a Simple Blog with Flight - Part 2 - Bloga uzlabošana ražošanai.
Building a Pokémon API in PHP: A Beginner's Guide
Šis aizraujošais ceļvedis vada jūs cauri vienkārša Pokémon API izveidošanai, izmantojot Flight PHP. Tajā tiek apskatīti API iestatīšanas pamati, maršrutu definēšana un JSON atbilžu atgriešana.
Iesaistīšanās
Vai jums ir ideja par ceļvedi? Atrasts kļūda? Mēs priecājamies par ieguldījumiem! Mūsu ceļveži tiek uzturēti FlightPHP dokumentācijas repozitorijā.
Ja jūs esat izveidojis kaut ko interesantu ar Flight un vēlaties to dalīties kā ceļvedi, lūdzu, iesniedziet pull request. Daloties ar savām zināšanām, jūs palīdzat Flight kopienai augt.
Meklējat API dokumentāciju?
Ja jūs meklējat specifisku informāciju par Flight galvenajām funkcijām un metodēm, apskatiet Learn sadaļu mūsu dokumentācijā.