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 framework aspektus, lai tie atbilstu jūsu lietojumprogrammas vajadzībām. Daži ir iestatīti pēc noklusējuma, bet jūs varat tos pārrakstīt pēc vajadzības. Jūs varat arī iestatīt savas mainīgās vērtības, lai tās izmantotu visā jūsu lietojumprogrammā.
Saprašana
Jūs varat pielāgot noteiktus Flight uzvedības aspektus, iestatot konfigurācijas vērtības
izmantojot set
metodi.
Flight::set('flight.log_errors', true);
app/config/config.php
failā jūs varat redzēt visas noklusējuma konfigurācijas mainīgās vērtības, kas ir pieejamas jums.
Pamata izmantošana
Flight konfigurācijas opcijas
Turpmāk ir visu pieejamo konfigurācijas iestatījumu saraksts:
- flight.base_url
?string
- Pārrakstīt pieprasījuma bāzes URL, ja Flight darbojas apakšdirektorijā. (noklusējums: null) - flight.case_sensitive
bool
- URL reģistra jutīga atbilstība. (noklusējums: false) - flight.handle_errors
bool
- Ļaut Flight apstrādāt visas kļūdas iekšēji. (noklusējums: true) - flight.log_errors
bool
- Reģistrēt 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 balstoties uz Tracy konfigurācijām, nevis šo konfigurāciju.
- flight.views.path
string
- Direktorija, kas satur skata veidnes failus. (noklusējums: ./views) - flight.views.extension
string
- Skata veidnes faila paplašinājums. (noklusējums: .php) - flight.content_length
bool
- IestatītContent-Length
galveni. (noklusējums: true)- Ja jūs izmantojat Tracy, tas jāiestata uz false, lai Tracy varētu pareizi renderēt.
- flight.v2.output_buffering
bool
- Izmantot mantojamu izvades buferizāciju. Skatīt migrēšanu uz v3. (noklusējums: false)
Loader konfigurācija
Ir papildu konfigurācijas iestatījums loader. Tas ļaus jums
automatiski ielādēt klases ar _
klases nosaukumā.
// Iespējot klases ielādi ar apakšsvītrām
// Noklusējums ir true
Loader::$v2ClassLoading = false;
Mainīgās vērtības
Flight ļauj jums saglabāt mainīgās vērtības, lai tās varētu izmantot jebkur jūsu lietojumprogrammā.
// Saglabāt jūsu mainīgo
Flight::set('id', 123);
// Citur jūsu lietojumprogrammā
$id = Flight::get('id');
Lai pārbaudītu, vai mainīgais ir iestatīts, jūs varat izdarīt:
if (Flight::has('id')) {
// Izpildīt kaut ko
}
Jūs varat notīrīt mainīgo šādi:
// Notīra id mainīgo
Flight::clear('id');
// Notīra visas mainīgās vērtības
Flight::clear();
Piezīme: Tas, ka jūs varat iestatīt mainīgo, nenozīmē, ka jums tas jādarītu. Izmantojiet šo funkciju saudzīgi. Iemesls ir tas, ka jebkas, kas uzglabāts šeit, kļūst par globālu mainīgo. Globālās mainīgās vērtības ir sliktas, jo tās var mainīt no jebkuras vietas jūsu lietojumprogrammā, padarot grūti izsekot kļūdas. Turklāt tas var sarežģīt lietas, piemēram, vienības testēšanu.
Kļūdas un izņēmumi
Visas kļūdas un izņēmumi tiek uztverti 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 dažām kļūdas informācijām.
Jūs 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ī. Jūs varat to iespējot, mainot konfigurāciju:
Flight::set('flight.log_errors', true);
404 Nav atrasts
Kad 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.
Jūs varat pārrakstīt šo uzvedību savām vajadzībām:
Flight::map('notFound', function () {
// Apstrādāt nav atrasts
});
Skatīt arī
- Paplašināšana Flight - Kā paplašināt un pielāgot Flight kodola funkcionalitāti.
- Vienības testēšana - Kā rakstīt vienības testus jūsu Flight lietojumprogrammai.
- Tracy - Spraudnis uzlabotai kļūdu apstrādei un atkļūdošanai.
- Tracy paplašinājumi - Paplašinājumi Tracy integrācijai ar Flight.
- APM - Spraudnis lietojumprogrammas veiktspējas uzraudzībai un kļūdu izsekošanai.
Traucējummeklēšana
- Ja jums ir problēmas, lai noskaidrotu visas jūsu konfigurācijas vērtības, jūs varat izdarīt
var_dump(Flight::get());
Izmaiņu žurnāls
- v3.5.0 - Pievienota konfigurācija
flight.v2.output_buffering
, lai atbalstītu mantojamu izvades buferizācijas uzvedību. - v2.0 - Pievienotas kodola konfigurācijas.
Learn/ai
AI un izstrādātāju pieredze ar Flight
Pārskats
Flight padara viegli uzlabot jūsu PHP projektus ar AI vadītiem rīkiem un mūsdienīgiem izstrādātāju darba plūsmu. Ar iebūvētiem komandām savienojumiem ar LLM (Large Language Model) sniedzējiem un ģenerēšanu projektu specifiskām AI kodēšanas instrukcijām, Flight palīdz jums un jūsu komandai iegūt maksimālo labumu no AI asistentiem, piemēram, GitHub Copilot, Cursor un Windsurf.
Izpratne
AI kodēšanas asistenti ir visnoderīgākie, kad viņi saprot jūsu projekta kontekstu, konvencijas un mērķus. Flight AI palīgi ļauj jums:
- Savienot savu projektu ar populāriem LLM sniedzējiem (OpenAI, Grok, Claude utt.)
- Ģenerēt un atjaunināt projektu specifiskas instrukcijas AI rīkiem, lai visi saņemtu konsekventu, atbilstošu palīdzību
- Turēt jūsu komandu saskaņotu un produktīvu, ar mazāku laiku, kas pavadīts konteksta skaidrošanā
Šīs funkcijas ir iebūvētas Flight kodolā CLI un oficiālajā flightphp/skeleton starter projektā.
Pamata lietošana
LLM akreditīvu iestatīšana
ai:init
komanda ved jūs cauri jūsu projekta savienojumam ar LLM sniedzēju.
php runway ai:init
Jums tiks uzdots:
- Izvēlēties savu sniedzēju (OpenAI, Grok, Claude utt.)
- Ievadīt savu API atslēgu
- Iestatīt bāzes URL un modeļa nosaukumu
Tas izveido .runway-creds.json
failu jūsu projekta saknē (un nodrošina, ka tas ir jūsu .gitignore
).
Piemērs:
Welcome to AI Init!
Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1
Enter the base URL for the LLM API [https://api.openai.com]:
Enter your API key for openai: sk-...
Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]:
Credentials saved to .runway-creds.json
Ģenerēšana projektu specifiskām AI instrukcijām
ai:generate-instructions
komanda palīdz jums izveidot vai atjaunināt instrukcijas AI kodēšanas asistentiem, pielāgotas jūsu projektam.
php runway ai:generate-instructions
Jūs atbildēsiet uz dažiem jautājumiem par jūsu projektu (apraksts, datubāze, veidnes, drošība, komandas lielums utt.). Flight izmanto jūsu LLM sniedzēju, lai ģenerētu instrukcijas, tad ieraksta tās:
.github/copilot-instructions.md
(for GitHub Copilot).cursor/rules/project-overview.mdc
(for Cursor).windsurfrules
(for Windsurf)
Piemērs:
Please describe what your project is for? My awesome API
What database are you planning on using? MySQL
What HTML templating engine will you plan on using (if any)? latte
Is security an important element of this project? (y/n) y
...
AI instructions updated successfully.
Tagad jūsu AI rīki sniegs gudrākus, atbilstošākus ieteikumus, balstītus uz jūsu projekta reālajām vajadzībām.
Padziļinātā lietošana
- Jūs varat pielāgot jūsu akreditīvu vai instrukciju failu atrašanās vietu, izmantojot komandas opcijas (skatiet
--help
katrai komandai). - AI palīgi ir paredzēti darbam ar jebkuru LLM sniedzēju, kas atbalsta OpenAI saderīgās API.
- Ja vēlaties atjaunināt jūsu instrukcijas, kad jūsu projekts attīstās, tikai palaidiet atkārtoti
ai:generate-instructions
un atbildiet uz uzvednēm vēlreiz.
Skatīt arī
- Flight Skeleton – Oficiālais starter ar AI integrāciju
- Runway CLI – Vairāk par CLI rīku, kas nodrošina šīs komandas
Traucējummeklēšana
- Ja jūs redzat "Missing .runway-creds.json", palaidiet
php runway ai:init
vispirms. - Pārliecinieties, ka jūsu API atslēga ir derīga un tai ir piekļuve izvēlētajam modelim.
- Ja instrukcijas neatjaunojas, pārbaudiet failu atļaujas jūsu projektu direktorijā.
Izmaiņu žurnāls
- v3.16.0 – Pievienotas
ai:init
unai:generate-instructions
CLI 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 svarīga lieta, kad runa ir 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 nodrošina vairākas funkcijas, lai palīdzētu jums nodrošināt jūsu tīmekļa lietojumprogrammu drošību.
Izpratne
Ir vairākas izplatītas drošības draudi, par kuriem jums jāzina, būvējot tīmekļa lietojumprogrammas. Daži no visizplatītākajiem draudiem ietver:
- Cross Site Request Forgery (CSRF)
- Cross Site Scripting (XSS)
- SQL Injection
- Cross Origin Resource Sharing (CORS)
Templates palīdz ar XSS, automātiski aizbēgot izvadi pēc noklusējuma, tāpēc jums nav jāatceras to darīt. Sessions var palīdzēt ar CSRF, uzglabājot CSRF žetonu lietotāja sesijā, kā aprakstīts zemāk. Izmantojot sagatavotus paziņojumus ar PDO, var palīdzēt novērst SQL injekcijas uzbrukumus (vai izmantojot ērtas metodes PdoWrapper klasē). CORS var apstrādāt ar vienkāršu āķi pirms Flight::start()
tiek izsaukts.
Visas šīs metodes darbojas kopā, lai palīdzētu saglabāt jūsu tīmekļa lietojumprogrammu drošību. Jums vienmēr jādomā par labākajām drošības praksēm, lai mācītos un saprastu tās.
Pamata Izmantošana
Virsraksti
HTTP virsraksti ir viens no vieglākajiem veidiem, kā nodrošināt jūsu tīmekļa lietojumprogrammu drošību. Jūs varat izmantot virsrakstus, lai novērstu clickjacking, XSS un citus uzbrukumus. Ir vairākas veidi, kā jūs varat pievienot šos virsrakstus savai lietojumprogrammai.
Divas lieliskas vietnes, kur pārbaudīt jūsu virsrakstu drošību, ir securityheaders.com un observatory.mozilla.org. Pēc tam, kad iestatīsiet zemāk esošo kodu, jūs viegli varēsiet pārbaudīt, vai jūsu virsraksti darbojas, izmantojot šīs divas vietnes.
Pievienot Manuāli
Jūs varat manuāli pievienot šos virsrakstus, izmantojot header
metodi uz Flight\Response
objekta.
// Iestatīt X-Frame-Options virsrakstu, lai novērstu clickjacking
Flight::response()->header('X-Frame-Options', 'SAMEORIGIN');
// Iestatīt Content-Security-Policy virsrakstu, lai novērstu XSS
// Piezīme: šis virsraksts var kļūt ļoti sarežģīts, tāpēc jums būs jāmeklē
// piemēri internetā savai lietojumprogrammai
Flight::response()->header("Content-Security-Policy", "default-src 'self'");
// Iestatīt X-XSS-Protection virsrakstu, lai novērstu XSS
Flight::response()->header('X-XSS-Protection', '1; mode=block');
// Iestatīt X-Content-Type-Options virsrakstu, lai novērstu MIME sniffing
Flight::response()->header('X-Content-Type-Options', 'nosniff');
// Iestatīt Referrer-Policy virsrakstu, lai kontrolētu, cik daudz referrer informācijas tiek nosūtīta
Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade');
// Iestatīt Strict-Transport-Security virsrakstu, lai piespiestu HTTPS
Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
// Iestatīt Permissions-Policy virsrakstu, lai kontrolētu, kuras funkcijas un API var izmantot
Flight::response()->header('Permissions-Policy', 'geolocation=()');
Šos var pievienot jūsu routes.php
vai index.php
failu augšdaļā.
Pievienot kā Filtru
Jūs varat tos arī pievienot filtrā/āķī, kā sekojošā:
// Pievienot virsrakstus 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=()');
});
Pievienot kā Vidutāju
Jūs varat tos arī pievienot kā vidutāja klasi, kas nodrošina lielāko elastību, kurām maršrutiem to piemērot. Vispārīgi, šie virsraksti jāpiemēro visām HTML un API atbildēm.
// app/middlewares/SecurityHeadersMiddleware.php
namespace app\middlewares;
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();
$response->header('X-Frame-Options', 'SAMEORIGIN');
$response->header("Content-Security-Policy", "default-src 'self'");
$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=()');
}
}
// index.php vai kur jums ir jūsu maršruti
// FYI, šī tukšā virkne darbojas kā globāls vidutājs visiem
// maršrutiem. Protams, jūs varētu izdarīt to pašu un pievienot
// to tikai specifiskiem maršrutiem.
Flight::group('', function(Router $router) {
$router->get('/users', [ 'UserController', 'getUsers' ]);
// vairāk maršrutu
}, [ SecurityHeadersMiddleware::class ]);
Cross Site Request Forgery (CSRF)
Cross Site Request Forgery (CSRF) ir uzbrukuma veids, kur ļaunprātīga vietne var likt lietotāja pārlūkprogrammai nosūtīt pieprasījumu uz jūsu vietni. To var izmantot, lai veiktu darbības jūsu vietnē bez lietotāja zināšanām. Flight nenodrošina iebūvētu CSRF aizsardzības mehānismu, bet jūs varat viegli ieviest savu, izmantojot vidutāju.
Iestatīšana
Vispirms jums jāģenerē CSRF žetons un jāglabā tas lietotāja sesijā. Tad jūs varat izmantot šo žetonu savās formās un pārbaudīt to, kad forma tiek iesniegta. Mēs izmantosim flightphp/session spraudni, lai pārvaldītu sesijas.
// Ģenerēt CSRF žetonu un glabāt to lietotāja sesijā
// (pieņemot, ka jūs esat izveidojis sesijas objektu un pievienojis to Flight)
// skatiet sesijas dokumentāciju vairāk informācijai
Flight::register('session', flight\Session::class);
// Jums jāģenerē tikai viens žetons uz sesiju (tā tas darbojas
// visās vairākās cilnēs un pieprasījumos 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
<!-- Izmantot CSRF žetonu savā formā -->
<form method="post">
<input type="hidden" name="csrf_token" value="<?= Flight::session()->get('csrf_token') ?>">
<!-- citas formas lauki -->
</form>
Izmantojot Latte
Jūs varat arī iestatīt pielāgotu funkciju, lai izvadītu CSRF žetonu savos Latte veidņos.
Flight::map('render', function(string $template, array $data, ?string $block): void {
$latte = new Latte\Engine;
// citas konfigurācijas...
// Iestatīt pielāgotu funkciju, lai izvadītu CSRF žetonu
$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 savos Latte veidņos jūs varat izmantot csrf()
funkciju, lai izvadītu CSRF žetonu.
<form method="post">
{csrf()}
<!-- citas formas lauki -->
</form>
Pārbaudīt CSRF Žetonu
Jūs varat pārbaudīt CSRF žetonu, izmantojot vairākas metodes.
Vidutājs
// app/middlewares/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');
}
}
}
}
// index.php vai kur jums ir jūsu maršruti
use app\middlewares\CsrfMiddleware;
Flight::group('', function(Router $router) {
$router->get('/users', [ 'UserController', 'getUsers' ]);
// vairāk maršrutu
}, [ CsrfMiddleware::class ]);
Notikuma Filtri
// Šis vidutājs pārbauda, vai pieprasījums ir POST pieprasījums un, ja ir, tas pārbauda, vai CSRF žetons ir derīgs
Flight::before('start', function() {
if(Flight::request()->method == 'POST') {
// uztvert csrf žetonu no formas 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);
}
}
});
Cross Site Scripting (XSS)
Cross Site Scripting (XSS) ir uzbrukuma veids, kur ļaunprātīga formas ievade var injicēt kodu jūsu vietnē. Lielākā daļa no šīm iespējām nāk no formas vērtībām, kuras jūsu gala lietotāji aizpildīs. Jums nekad nevajadzētu uzticēties izvadai no jūsu lietotājiem! Vienmēr pieņemiet, ka visi no viņiem ir labākie hakeri pasaulē. Viņi var injicēt ļaunprātīgu JavaScript vai HTML jūsu lapā. Šo kodu var izmantot, lai nozagt informāciju no jūsu lietotājiem vai veiktu darbības jūsu vietnē. Izmantojot Flight skata klasi vai citu veidņu dzinēju, piemēram, Latte, jūs varat viegli aizbēgt izvadi, lai novērstu XSS uzbrukumus.
// Pieņemsim, ka lietotājs ir gudrs un mēģina izmantot šo kā savu vārdu
$name = '<script>alert("XSS")</script>';
// Tas aizbēgs izvadi
Flight::view()->set('name', $name);
// Tas izvadīs: <script>alert("XSS")</script>
// Ja jūs izmantojat kaut ko tādu kā Latte, kas reģistrēts kā jūsu skata klase, tas arī automātiski aizbēgs šo.
Flight::view()->render('template', ['name' => $name]);
SQL Injection
SQL Injection ir uzbrukuma veids, kur ļaunprātīgs lietotājs var injicēt SQL kodu jūsu datubāzē. To var izmantot, lai nozagt informāciju
no jūsu datubāzes vai veiktu darbības jūsu datubāzē. Atkal jums nekad nevajadzētu uzticēties ievadei no jūsu lietotājiem! Vienmēr pieņemiet, ka viņi ir
izslāpuši pēc asinīm. Jūs varat izmantot sagatavotus paziņojumus jūsu PDO
objektos, kas novērsīs SQL injekciju.
// Pieņemot, ka jums ir Flight::db() reģistrēts kā jūsu PDO objekts
$statement = Flight::db()->prepare('SELECT * FROM users WHERE username = :username');
$statement->execute([':username' => $username]);
$users = $statement->fetchAll();
// Ja jūs izmantojat PdoWrapper klasi, to var viegli izdarīt vienā rindā
$users = Flight::db()->fetchAll('SELECT * FROM users WHERE username = :username', [ 'username' => $username ]);
// Jūs varat izdarīt to pašu ar PDO objektu ar ? aizstājējiem
$statement = Flight::db()->fetchAll('SELECT * FROM users WHERE username = ?', [ $username ]);
Nedroša Piemēra
Zemāk ir iemesls, kāpēc mēs izmantojam SQL sagatavotus paziņojumus, lai aizsargātu no nevainīgiem piemēriem, piemēram, zemāk:
// gala lietotājs aizpilda tīmekļa formu.
// formas vērtībai hakeris ievada kaut ko šādu:
$username = "' OR 1=1; -- ";
$sql = "SELECT * FROM users WHERE username = '$username' LIMIT 5";
$users = Flight::db()->fetchAll($sql);
// Pēc vaicājuma būvēšanas 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 lietotājus datubāzē, nevis tikai to vienu lietotājvārdu
CORS
Cross-Origin Resource Sharing (CORS) ir mehānisms, kas ļauj daudziem resursiem (piem., fonti, JavaScript utt.) tīmekļa lapā tikt
pieprasītiem no cita domēna ārpus domēna, no kura resurss radies. Flight nav iebūvētas funkcionalitātes,
bet to var viegli apstrādāt ar āķi, kas darbojas pirms Flight::start()
metodes izsaukšanas.
// app/utils/CorsUtil.php
namespace app\utils;
class CorsUtil
{
public function set(array $params): void
{
$request = Flight::request();
$response = Flight::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 jūsu atļautās saimnieces šeit.
$allowed = [
'capacitor://localhost',
'ionic://localhost',
'http://localhost',
'http://localhost:4200',
'http://localhost:8080',
'http://localhost:8100',
];
$request = Flight::request();
if (in_array($request->getVar('HTTP_ORIGIN'), $allowed, true) === true) {
$response = Flight::response();
$response->header("Access-Control-Allow-Origin", $request->getVar('HTTP_ORIGIN'));
}
}
}
// index.php vai kur jums ir jūsu maršruti
$CorsUtil = new CorsUtil();
// Tam jādarbojas pirms start darbojas.
Flight::before('start', [ $CorsUtil, 'setupCors' ]);
Kļūdu Apstrāde
Slēpjiet sensitīvas kļūdu detaļas produkcijā, lai izvairītos no informācijas noplūdes uzbrucējiem. Produkcijā reģistrējiet kļūdas, nevis rādiet tās ar display_errors
iestatītu uz 0
.
// Jūsu bootstrap.php vai index.php
// pievienojiet šo jūsu app/config/config.php
$environment = ENVIRONMENT;
if ($environment === 'production') {
ini_set('display_errors', 0); // Izslēgt kļūdu rādīšanu
ini_set('log_errors', 1); // Reģistrēt kļūdas
ini_set('error_log', '/path/to/error.log');
}
// Jūsu maršrutos vai kontroļeros
// Izmantojiet Flight::halt() kontrolētai 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.
// Pieņemsim POST pieprasījumu ar $_POST['input'] un $_POST['email']
// Sanitizēt virkni ievadi
$clean_input = filter_var(Flight::request()->data->input, FILTER_SANITIZE_STRING);
// Sanitizēt e-pastu
$clean_email = filter_var(Flight::request()->data->email, FILTER_SANITIZE_EMAIL);
Paroles Hāšošana
Glabājiet paroles droši un pārbaudiet tās droši, izmantojot PHP iebūvētās funkcijas, piemēram, password_hash un password_verify. Paroles nekad nevajadzētu glabāt vienkāršā tekstā, nedrīkst tās šifrēt ar atgriezeniskām metodēm. Hāšošana nodrošina, ka pat ja jūsu datubāze ir kompromitēta, faktiskās paroles paliek aizsargātas.
$password = Flight::request()->data->password;
// Hāšot paroli, kad glabājat (piem., reģistrācijas laikā)
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Pārbaudīt paroli (piem., pieteikšanās laikā)
if (password_verify($password, $stored_hash)) {
// Parole sakrīt
}
Ātruma Ierobežošana
Aizsargājiet pret brute force uzbrukumiem vai servisa atteikuma uzbrukumiem, ierobežojot pieprasījumu ātrumu ar kešu.
// Pieņemot, ka jums ir uzstādīts un reģistrēts flightphp/cache
// 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); // Atjaunot pēc 60 sekundēm
});
Skatīt Arī
- Sessions - Kā droši pārvaldīt lietotāja sesijas.
- Templates - Izmantojot veidnes, lai automātiski aizbēgtu izvadi un novērstu XSS.
- PDO Wrapper - Vienkāršotas datubāzes mijiedarbības ar sagatavotiem paziņojumiem.
- Middleware - Kā izmantot vidutājus, lai vienkāršotu drošības virsrakstu pievienošanas procesu.
- Responses - Kā pielāgot HTTP atbildes ar drošiem virsrakstiem.
- Requests - Kā apstrādāt un sanitizēt lietotāja ievadi.
- filter_var - PHP funkcija ievades sanitizācijai.
- password_hash - PHP funkcija drošai paroles hāšošanai.
- password_verify - PHP funkcija hāšoto parolu pārbaudei.
Traucējummeklēšana
- Atsauce uz "Skatīt Arī" sadaļu iepriekš, lai iegūtu traucējummeklēšanas informāciju, kas saistīta ar problēmām Flight Framework komponentos.
Izmaiņu Žurnāls
- v3.1.0 - Pievienotas sadaļas par CORS, Kļūdu Apstrādi, Ievades Sanitizāciju, Paroles Hāšošanu un Ātruma Ierobežošanu.
- v2.0 - Pievienota aizbēgšana noklusējuma skatiem, lai novērstu XSS.
Learn/routing
Maršrutizācija
Pārskats
Maršrutizācija Flight PHP kartē URL raksturlietas ar atgriezeniskajām funkcijām vai klases metodēm, ļaujot ātri un vienkārši apstrādāt pieprasījumus. Tā ir paredzēta minimālam overhead, iesācējam draudzīgai lietošanai un paplašināmībai bez ārējām atkarībām.
Saprašana
Maršrutizācija ir kodola 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žādas URL izraisa specifisku kodu, vai nu caur funkcijām, klases metodēm vai kontroliera darbībām. Flight maršrutizācijas sistēma ir elastīga, atbalsta pamatraksturlietas, nosauktos parametrus, regulārās izteiksmes un papildu funkcijas, piemēram, atkarību injekciju un resursu maršrutizāciju. Šī pieeja uztur jūsu kodu organizētu un viegli uzturamu, vienlaikus paliekot ātra un vienkārša iesācējiem un paplašināma pieredzējušiem lietotājiem.
Piezīme: Vēlaties saprast vairāk par maršrutizāciju? Apskatiet "kāpēc ietvars?" lapu plašākam skaidrojumam.
Pamata Lietošana
Vienkārša Maršruta Definēšana
Pamata maršrutizācija Flight tiek veikta, saskaņojot URL raksturlietu ar atgriezenisko funkciju vai klases un metodes masīvu.
Flight::route('/', function(){
echo 'sveiks pasaule!';
});
Maršruti tiek saskaņoti tajā secībā, kādā tie ir definēti. Pirmais maršruts, kas saskan ar pieprasījumu, tiks izsaukts.
Funkciju Lietošana kā Atgriezeniskajām Funkcijām
Atgriezeniskā funkcija var būt jebkurš callable objekts. Tātad jūs varat izmantot parasto funkciju:
function hello() {
echo 'sveiks pasaule!';
}
Flight::route('/', 'hello');
Klases un Metodes Lietošana kā Kontrolieris
Jūs varat izmantot klases metodi (statisku vai nē) kā:
class GreetingController {
public function hello() {
echo 'sveiks pasaule!';
}
}
Flight::route('/', [ 'GreetingController','hello' ]);
// or
Flight::route('/', [ GreetingController::class, 'hello' ]); // preferred method
// or
Flight::route('/', [ 'GreetingController::hello' ]);
// or
Flight::route('/', [ 'GreetingController->hello' ]);
Vai arī izveidojot objektu pirms tam 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 "Sveiks, {$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 ietvarā, flight\Engine klase vienmēr tiek injicēta, ja vien jūs neprecizējat caur atkarību injekcijas konteineru
Metodes Specifiska Maršrutizācija
Pēc noklusējuma maršruta raksturlietas tiek saskaņotas pret visām pieprasījuma metodēm. Jūs varat atbildēt uz specifiskām metodēm, novietojot identifikatoru pirms URL.
Flight::route('GET /', function () {
echo 'Es saņēmu GET pieprasījumu.';
});
Flight::route('POST /', function () {
echo 'Es saņēmu POST pieprasījumu.';
});
// You cannot use Flight::get() for routes as that is a method
// to get variables, not create a route.
Flight::post('/', function() { /* code */ });
Flight::patch('/', function() { /* code */ });
Flight::put('/', function() { /* code */ });
Flight::delete('/', function() { /* code */ });
Jūs varat arī kartēt vairākas metodes uz vienu atgriezenisko funkciju, izmantojot |
atdalītāju:
Flight::route('GET|POST /', function () {
echo 'Es saņēmu vai nu GET, vai POST pieprasījumu.';
});
Ī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 tieši kā GET pieprasījumi, bet Flight automātiski noņem atbildes ķermeni pirms tā nosūtīšanas klientam.
- Tas nozīmē, ka jūs varat definēt maršrutu GET, un HEAD pieprasījumi uz to pašu URL atgriezīs tikai galvenes (bez satura), kā paredzēts HTTP standartos.
Flight::route('GET /info', function() {
echo 'Šī ir kāda informācija!';
});
// A HEAD request to /info will return the same headers, but no body.
OPTIONS Pieprasījumi
OPTIONS pieprasījumi tiek automātiski apstrādāti Flight jebkuram definētam maršrutam.
- Kad saņemts OPTIONS pieprasījums, Flight atbild ar
204 No Content
statusu unAllow
galveni, kas uzskaita visas atbalstītās HTTP metodes tam maršrutam. - Jums nav jādefinē atsevišķs maršruts OPTIONS.
// For a route defined as:
Flight::route('GET|POST /users', function() { /* ... */ });
// An OPTIONS request to /users will respond with:
//
// Status: 204 No Content
// Allow: GET, POST, HEAD, OPTIONS
Maršrutētāja Objekta Lietošana
Papildus jūs varat iegūt Maršrutētāja objektu, kuram ir daži palīgapstrādes metodes jūsu lietošanai:
$router = Flight::router();
// maps all methods just like Flight::route()
$router->map('/', function() {
echo 'sveiks pasaule!';
});
// GET request
$router->get('/users', function() {
echo 'lietotāji';
});
$router->post('/users', function() { /* code */});
$router->put('/users/update/@id', function() { /* code */});
$router->delete('/users/@id', function() { /* code */});
$router->patch('/users/@id', function() { /* code */});
Regulārās Izteiksmes (Regex)
Jūs varat izmantot regulārās izteiksmes savos maršrutos:
Flight::route('/user/[0-9]+', function () {
// This will match /user/1234
});
Lai gan šī metode ir pieejama, ieteicams izmantot nosauktos parametrus vai nosauktos parametrus ar regulārajām izteiksmēm, jo tie ir lasāmāki un vieglāk uzturami.
Nosauktie Parametri
Jūs varat norādīt nosauktos parametrus savos maršrutos, kas tiks nodoti jūsu atgriezeniskajai funkcijai. Tas ir vairāk maršruta lasāmībai nekā jebkas cits. Lūdzu, skatiet sadaļu zemāk par svarīgu brīdinājumu.
Flight::route('/@name/@id', function (string $name, string $id) {
echo "sveiks, $name ($id)!";
});
Jūs varat arī iekļaut regulārās izteiksmes ar saviem nosauktajiem parametriem, izmantojot :
atdalītāju:
Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) {
// This will match /bob/123
// But will not match /bob/12345
});
Piezīme: Saskaņošanas regex grupas
()
ar pozicionālajiem parametriem nav atbalstītas. Piem::'\(
Svarīgs Brīdinājums
Lai gan iepriekšējā piemērā šķiet, ka @name
ir tieši saistīts ar mainīgo $name
, tas nav. Parametru secība atgriezeniskajā funkcijā nosaka, kas tam tiek nodots. Ja jūs mainītu parametru secību atgriezeniskajā funkcijā, mainīgie tiktu mainīti arī. Šeit ir piemērs:
Flight::route('/@name/@id', function (string $id, string $name) {
echo "sveiks, $name ($id)!";
});
Un ja jūs apmeklētu šādu URL: /bob/123
, izvade būtu sveiks, 123 (bob)!
.
Lūdzu, esiet uzmanīgi, kad iestatāt savus maršrutus un atgriezeniskās funkcijas!
Neobligātie Parametri
Jūs varat norādīt nosauktos parametrus, kas ir neobligāti saskaņošanai, ietverot segmentus iekavās.
Flight::route(
'/blog(/@year(/@month(/@day)))',
function(?string $year, ?string $month, ?string $day) {
// This will match the following URLS:
// /blog/2012/12/10
// /blog/2012/12
// /blog/2012
// /blog
}
);
Jei kuri neobligātie parametri netiek saskaņoti, tie tiks nodoti kā NULL
.
Wildcard Maršrutizācija
Saskaņošana tiek veikta tikai uz atsevišķiem URL segmentiem. Ja vēlaties saskaņot vairākus segmentus, varat izmantot *
wildcard.
Flight::route('/blog/*', function () {
// This will match /blog/2000/02/01
});
Lai maršrutētu visus pieprasījumus uz vienu atgriezenisko funkciju, varat darīt:
Flight::route('*', function () {
// Do something
});
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 vienkārša.
Ja vēlaties pielāgotu 404 atbildi, varat kartēt savu notFound
metodi:
Flight::map('notFound', function() {
$url = Flight::request()->url;
// You could also use Flight::render() with a custom template.
$output = <<<HTML
<h1>Mans Pielāgots 404 Nav Atrasts</h1>
<h3>Lapa, kuru jūs pieprasījāt {$url}, netika atrasta.</h3>
HTML;
$this->response()
->clearBody()
->status(404)
->write($output)
->send();
});
Metodes Nav Atrasts Apstrādātājs
Pēc noklusējuma, ja URL ir atrasts, bet metode nav atļauta, Flight nosūtīs HTTP 405 Method Not Allowed
atbildi, kas ir ļoti vienkārša un vienkārša (Piem: Method Not Allowed. Allowed Methods are: GET, POST). Tā arī iekļaus Allow
galveni ar atļautajām metodēm tam URL.
Ja vēlaties pielāgotu 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);
// You could also use Flight::render() with a custom template.
$output = <<<HTML
<h1>Mans Pielāgots 405 Metode Nav Atļauta</h1>
<h3>Metode, kuru jūs 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 Injekcija Maršrutos
Ja vēlaties izmantot atkarību injekciju caur konteineru (PSR-11, PHP-DI, Dice utt.), vienīgais maršrutu veids, kur tas ir pieejams, ir vai nu tieši izveidojot objektu pats un izmantojot konteineru, lai izveidotu jūsu objektu, vai arī varat izmantot virknes, lai definētu klasi un metodi, ko izsaukt. Jūs varat apmeklēt Atkarību Injekcijas lapu vairāk informācijas.
Šeit ir ātrs piemērs:
use flight\database\PdoWrapper;
// Greeting.php
class Greeting
{
protected PdoWrapper $pdoWrapper;
public function __construct(PdoWrapper $pdoWrapper) {
$this->pdoWrapper = $pdoWrapper;
}
public function hello(int $id) {
// do something with $this->pdoWrapper
$name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]);
echo "Sveiks, pasaule! Mans vārds ir {$name}!";
}
}
// index.php
// Setup the container with whatever params you need
// See the Dependency Injection page for more information on PSR-11
$dice = new \Dice\Dice();
// Don't forget to reassign the variable with '$dice = '!!!!!
$dice = $dice->addRule('flight\database\PdoWrapper', [
'shared' => true,
'constructParams' => [
'mysql:host=localhost;dbname=test',
'root',
'password'
]
]);
// Register the container handler
Flight::registerContainerHandler(function($class, $params) use ($dice) {
return $dice->create($class, $params);
});
// Routes like normal
Flight::route('/hello/@id', [ 'Greeting', 'hello' ]);
// or
Flight::route('/hello/@id', 'Greeting->hello');
// or
Flight::route('/hello/@id', 'Greeting::hello');
Flight::start();
Izpildes Nodošana Nākamajam Maršrutam
Deprecated
Jūs varat nodot izpildi nākamajam saskanīgajam maršrutam, atgriežot true
no jūsu atgriezeniskās funkcijas.
Flight::route('/user/@name', function (string $name) {
// Check some condition
if ($name !== "Bob") {
// Continue to next route
return true;
}
});
Flight::route('/user/*', function () {
// This will get called
});
Tagad ieteicams izmantot middleware, lai apstrādātu sarežģītus gadījumus kā šis.
Maršruta Aliasēšana
Piešķirot aliasu maršrutam, jūs varat vēlāk dinamiski izsaukt šo aliasu savā lietojumprogrammā, lai tas tiktu ģenerēts vēlāk jūsu kodā (piem: saite HTML veidnē vai ģenerējot pāradresācijas URL).
Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view');
// or
Flight::route('/users/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view');
// later in code somewhere
class UserController {
public function update() {
// code to save user...
$id = $user['id']; // 5 for example
$redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // will return '/users/5'
Flight::redirect($redirectUrl);
}
}
Tas ir īpaši noderīgi, ja jūsu URL mainās. Iepriekšējā piemērā, pieņemsim, ka lietotāji tika pārvietoti uz /admin/users/@id
vietā.
Ar aliasēšanu vietā maršrutam, jums vairs nav jāmeklē visi vecie URL jūsu kodā un jāmaina tie, jo alias tagad atgriezīs /admin/users/5
, kā piemērā iepriekš.
Maršruta aliasēšana joprojām darbojas grupās:
Flight::group('/users', function() {
Flight::route('/@id', function($id) { echo 'user:'.$id; }, false, 'user_view');
// or
Flight::route('/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view');
});
Maršruta Informācijas Pārbaude
Ja vēlaties pārbaudīt saskanīgo maršruta informāciju, ir 2 veidi, kā to izdarīt:
- Jūs varat izmantot
executedRoute
īpašību uzFlight::router()
objekta. - Jūs varat pieprasīt, lai maršruta objekts tiktu nodots jūsu atgriezeniskajai funkcijai, nododot
true
kā trešo parametru maršruta metodē. Maršruta objekts vienmēr būs pēdējais parametrs, kas nodots jūsu atgriezeniskajai funkcijai.
executedRoute
Flight::route('/', function() {
$route = Flight::router()->executedRoute;
// Do something with $route
// Array of HTTP methods matched against
$route->methods;
// Array of named parameters
$route->params;
// Matching regular expression
$route->regex;
// Contains the contents of any '*' used in the URL pattern
$route->splat;
// Shows the url path....if you really need it
$route->pattern;
// Shows what middleware is assigned to this
$route->middleware;
// Shows the alias assigned to this route
$route->alias;
});
Piezīme:
executedRoute
īpašība tiks iestatīta tikai pēc tam, kad maršruts ir izpildīts. Ja mēģināsiet piekļūt tai pirms maršruta izpildes, tā būsNULL
. Jūs varat izmantot executedRoute arī middleware!
Nodošana true
maršruta definīcijā
Flight::route('/', function(\flight\net\Route $route) {
// Array of HTTP methods matched against
$route->methods;
// Array of named parameters
$route->params;
// Matching regular expression
$route->regex;
// Contains the contents of any '*' used in the URL pattern
$route->splat;
// Shows the url path....if you really need it
$route->pattern;
// Shows what middleware is assigned to this
$route->middleware;
// Shows the alias assigned to this route
$route->alias;
}, true);// <-- This true parameter is what makes that happen
Maršruta Grupēšana un Middleware
Var būt gadījumi, kad vēlaties grupēt saistītus maršrutus kopā (piemēram, /api/v1
).
Jūs varat to izdarīt, izmantojot group
metodi:
Flight::group('/api/v1', function () {
Flight::route('/users', function () {
// Matches /api/v1/users
});
Flight::route('/posts', function () {
// Matches /api/v1/posts
});
});
Jūs pat varat ligzdot grupu grupas:
Flight::group('/api', function () {
Flight::group('/v1', function () {
// Flight::get() gets variables, it doesn't set a route! See object context below
Flight::route('GET /users', function () {
// Matches GET /api/v1/users
});
Flight::post('/posts', function () {
// Matches POST /api/v1/posts
});
Flight::put('/posts/1', function () {
// Matches PUT /api/v1/posts
});
});
Flight::group('/v2', function () {
// Flight::get() gets variables, it doesn't set a route! See object context below
Flight::route('GET /users', function () {
// Matches GET /api/v2/users
});
});
});
Grupēšana ar Objekta Kontekstu
Jūs joprojām varat izmantot maršruta grupēšanu ar Engine
objektu šādā veidā:
$app = Flight::app();
$app->group('/api/v1', function (Router $router) {
// user the $router variable
$router->get('/users', function () {
// Matches GET /api/v1/users
});
$router->post('/posts', function () {
// Matches POST /api/v1/posts
});
});
Piezīme: Šī ir ieteiktā metode maršrutu un grupu definēšanai ar
$router
objektu.
Grupēšana ar Middleware
Jūs varat arī piešķirt middleware grupai maršrutu:
Flight::group('/api/v1', function () {
Flight::route('/users', function () {
// Matches /api/v1/users
});
}, [ MyAuthMiddleware::class ]); // or [ new MyAuthMiddleware() ] if you want to use an instance
Skatiet vairāk detaļu grupas middleware lapā.
Resursu Maršrutizācija
Jūs varat izveidot maršrutu kopu resursam, izmantojot resource
metodi. Tas izveidos maršrutu kopu resursam, kas seko RESTful konvencijām.
Lai izveidotu resursu, dariet šādu:
Flight::resource('/users', UsersController::class);
Un kas notiks fonā, tas izveidos šādus maršrutus:
[
'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 skatīt jaunos pievienotos maršrutus ar
runway
, palaižotphp runway routes
.
Pielāgošana Resursu Maršrutiem
Ir dažas opcijas resursu maršrutu konfigurēšanai.
Alias Bāze
Jūs varat konfigurēt aliasBase
. Pēc noklusējuma alias ir pēdējā URL daļa, kas norādīta.
Piemēram, /users/
rezultēs aliasBase
kā users
. Kad šie maršruti ir izveidoti, alias ir users.index
, users.create
utt. Ja vēlaties mainīt alias, iestatiet aliasBase
uz vēlamo vērtību.
Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]);
Tikai un Izņemot
Jūs varat arī norādīt, kurus maršrutus vēlaties izveidot, izmantojot only
un except
opcijas.
// Whitelist only these methods and blacklist the rest
Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' ] ]);
// Blacklist only these methods and whitelist the rest
Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]);
Šie ir pamatā balstīti uz balto sarakstu un melno sarakstu opcijām, lai jūs varētu norādīt, kurus maršrutus vēlaties izveidot.
Middleware
Jūs varat arī norādīt middleware, kas jāizpilda katram no maršrutiem, ko izveido resource
metode.
Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]);
Plūsmas Atbildes
Jūs tagad varat plūst atbildes klientam, izmantojot stream()
vai streamWithHeaders()
.
Tas ir noderīgi lielu failu nosūtīšanai, garām procesiem vai lielu atbilžu ģenerēšanai.
Maršruta plūsmošana tiek apstrādāta nedaudz savādāk nekā parasts maršruts.
Piezīme: Plūsmas atbildes ir pieejamas tikai tad, ja jums ir iestatīts
flight.v2.output_buffering
kāfalse
.
Plūsma ar Manuālām Galvenēm
Jūs varat plūst atbildi klientam, izmantojot stream()
metodi uz maršruta. Ja dariet to, jums jāiestata visas galvenes manuāli pirms izvades kaut ko klientam.
Tas tiek darīts ar header()
php funkciju vai Flight::response()->setRealHeader()
metodi.
Flight::route('/@filename', function($filename) {
$response = Flight::response();
// obviously you would sanitize the path and whatnot.
$fileNameSafe = basename($filename);
// If you have additional headers to set here after the route has executed
// you must define them before anything is echoed out.
// They must all be a raw call to the header() function or
// a call to Flight::response()->setRealHeader()
header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"');
// or
$response->setRealHeader('Content-Disposition: attachment; filename="'.$fileNameSafe.'"');
$filePath = '/some/path/to/files/'.$fileNameSafe;
if (!is_readable($filePath)) {
Flight::halt(404, 'File not found');
}
// manually set the content length if you'd like
header('Content-Length: '.filesize($filePath));
// or
$response->setRealHeader('Content-Length: '.filesize($filePath));
// Stream the file to the client as it's read
readfile($filePath);
// This is the magic line here
})->stream();
Plūsma ar Galvenēm
Jūs varat izmantot streamWithHeaders()
metodi, lai iestatītu galvenes pirms plūsmošanas sākšanas.
Flight::route('/stream-users', function() {
// you can add any additional headers you want here
// you just must use header() or Flight::response()->setRealHeader()
// however you pull your data, just as an example...
$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 ',';
}
// This is required to send the data to the client
ob_flush();
}
echo '}';
// This is how you'll set the headers before you start streaming.
})->streamWithHeaders([
'Content-Type' => 'application/json',
'Content-Disposition' => 'attachment; filename="users.json"',
// optional status code, defaults to 200
'status' => 200
]);
Skatīt Arī
- Middleware - Middleware lietošana ar maršrutiem autentifikācijai, žurnālošanai utt.
- Atkarību Injekcija - Objektu izveides un pārvaldības vienkāršošana maršrutos.
- Kāpēc Ietvars? - Ietvara kā Flight izmantošanas priekšrocību saprašana.
- Paplašināšana - Kā paplašināt Flight ar savu funkcionalitāti, ieskaitot
notFound
metodi. - php.net: preg_match - PHP funkcija regulāro izteiksmju saskaņošanai.
Traucējummeklēšana
- Maršruta parametri tiek saskaņoti pēc secības, nevis pēc nosaukuma. Pārliecinieties, ka atgriezeniskās funkcijas parametru secība atbilst maršruta definīcijai.
Flight::get()
lietošana nedefinē maršrutu; izmantojietFlight::route('GET /...')
maršrutizācijai vai Router objekta kontekstu grupās (piem.$router->get(...)
).- executedRoute īpašība tiek iestatīta tikai pēc maršruta izpildes; tā ir NULL pirms izpildes.
- Plūsmošanai nepieciešama legacy Flight izvades buferizācijas funkcionalitāte, kas ir atspējota (
flight.v2.output_buffering = false
). - Atkarību injekcijai tikai noteiktas maršruta definīcijas atbalsta konteineru balstītu instancēšanu.
404 Nav Atrasts vai Negaidīta Maršruta Uzvedība
Ja redzat 404 Nav Atrasts kļūdu (bet jūs zvērāt uz savu dzīvi, ka tas tiešām ir tur un tas nav drukas kļūda), tas patiesībā varētu būt problēma ar vērtības atgriešanu jūsu maršruta galapunktā, nevis tikai to izsaukšanu. Iemesls tam ir tīms, bet var uzmest dažus izstrādātājus.
Flight::route('/hello', function(){
// This might cause a 404 Not Found error
return 'Sveiks Pasaule';
});
// What you probably want
Flight::route('/hello', function(){
echo 'Sveiks Pasaule';
});
Iemesls tam ir īpašs mehānisms, kas iebūvēts maršrutētājā, kas apstrādā atgriezenisko izvadi kā signālu "iet uz nākamo maršrutu". Jūs varat redzēt uzvedību, kas dokumentēta Maršrutizācijas sadaļā.
Izmaiņu Žurnāls
- v3: Pievienota resursu maršrutizācija, maršruta aliasēšana un plūsmas atbalsts, maršruta grupas un middleware atbalsts.
- v1: Liela daļa pamata funkciju pieejamas.
Learn/learn
Uzzināt Par Flight
Flight ir ātrs, vienkāršs, paplašināms ietvars PHP. Tas ir diezgan daudzpusīgs un to var izmantot jebkura veida tīmekļa lietojumprogrammas izveidei. Tas ir izveidots ar vienkāršību prātā un ir uzrakstīts tā, lai būtu viegli saprast un izmantot.
Piezīme: Jūs redzēsiet piemērus, kas izmanto
Flight::
kā statisku mainīgo un dažus, kas izmanto$app->
Engine objektu. Abi darbojas savstarpēji aizstājami.$app
un$this->app
kontrolierī/vidējā ir ieteicamais pieeja no Flight komandas.
Kodola Komponenti
Maršrutēšana
Uzziniet, kā pārvaldīt maršrutus savai tīmekļa lietojumprogrammai. Tas ietver arī maršrutu grupēšanu, maršruta parametrus un vidējo.
Vidējais
Uzziniet, kā izmantot vidējo, lai filtrētu pieprasījumus un atbildes savā lietojumprogrammā.
Autoloadēšana
Uzziniet, kā automātiski ielādēt savas klases savā lietojumprogrammā.
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ā izmantot iebūvēto skata dzinēju, lai renderētu savas HTML veidnes.
Drošība
Uzziniet, kā nodrošināt savu lietojumprogrammu pret izplatītiem drošības draudiem.
Konfigurācija
Uzziniet, kā konfigurēt ietvaru savai lietojumprogrammai.
Notikumu Pārvaldnieks
Uzziniet, kā izmantot notikumu sistēmu, lai pievienotu pielāgotus notikumus savai lietojumprogrammai.
Paplašināšana Flight
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īglasu Klases
Kolekcijas
Kolekcijas tiek izmantotas, lai turētu datus un būtu pieejamas kā masīvs vai kā objekts vieglākai izmantošanai.
JSON Apvalks
Tam ir dažas vienkāršas funkcijas, lai kodēšana un dekodēšana jūsu JSON būtu konsekventa.
PDO Apvalks
PDO dažreiz var radīt vairāk galvassāpju nekā nepieciešams. Šī vienkāršā apvalka klase var ievērojami atvieglot mijiedarbību ar jūsu datubāzi.
Augšupielādētā Faila Apstrādātājs
Vienkārša klase, lai palīdzētu pārvaldīt augšupielādētos failus un pārvietot tos uz pastāvīgu atrašanās vietu.
Svarīgi Koncepti
Kāpēc Ietvars?
Šeit ir īss raksts par to, kāpēc jums vajadzētu izmantot ietvaru. Ir laba ideja saprast ietvara izmantošanas priekšrocības, pirms jūs sākat to izmantot.
Turklāt ir izveidots lielisks mācību ceļvedis no @lubiana. Lai gan tas neiet dziļi detaļās par Flight specifiski, šis ceļvedis palīdzēs jums saprast dažus no galvenajiem konceptiem, kas saistīti ar ietvaru, un kāpēc tie ir izdevīgi izmantot. Jūs varat atrast mācību ceļvedi šeit.
Flight Salīdzinājumā Ar Citiem Ietvariem
Ja jūs migrējat no cita ietvara, piemēram, Laravel, Slim, Fat-Free vai Symfony uz Flight, šī lapa palīdzēs jums saprast atšķirības starp tiem.
Citi Temati
Vienības Testēšana
Sekojiet šim ceļvedim, lai uzzinātu, kā veikt vienības testēšanu jūsu Flight kodam, lai tas būtu stingrs kā klints.
AI & Izstrādātāja Pieredze
Uzziniet, kā Flight darbojas ar AI rīkiem un modernām izstrādātāja darba plūsmēm, lai palīdzētu jums kodēt ātrāk un gudrāk.
Migrēšana v2 -> v3
Atpakaļsaderība lielākoties ir saglabāta, bet ir dažas izmaiņas, par kurām jums vajadzētu zināt, migrējot no v2 uz v3.
Learn/unit_testing
Vienības testēšana
Pārskats
Vienības testēšana Flight palīdz nodrošināt, ka jūsu lietojumprogramma darbojas kā paredzēts, agrīnā stadijā uztver kļūdas un padara jūsu koda bāzi vieglāk uzturamu. Flight ir izstrādāts, lai gludi darbotos ar PHPUnit, populārāko PHP testēšanas ietvaru.
Saprašana
Vienības testi pārbauda jūsu lietojumprogrammas mazo daļu uzvedību (piemēram, kontrolierus vai servisus) izolēti. Flight tas nozīmē testēšanu, kā jūsu maršruti, kontrolieri un loģika reaģē uz dažādām ievadēm — bez paļaušanās uz globālo stāvokli vai reāliem ārējiem servisiem.
Galvenie principi:
- Testējiet uzvedību, nevis ieviešanu: Koncentrējieties uz to, ko jūsu kods dara, nevis kā tas to dara.
- Izvairieties no globālā stāvokļa: Izmantojiet atkarību injekciju vietā
Flight::set()
vaiFlight::get()
. - Mock ārējos servisus: Aizstājiet tādas lietas kā datubāzes vai pasta sūtītājus ar testa dubultiem.
- Turiet testus ātrus un fokusētus: Vienības testi nedrīkst pieskarties reālām datubāzēm vai API.
Pamata izmantošana
PHPUnit iestatīšana
- Instalējiet PHPUnit ar Composer:
composer require --dev phpunit/phpunit
- Izveidojiet
tests
direktoriju jūsu projekta saknes mapē. - Pievienojiet testa skriptu jūsu
composer.json
:"scripts": { "test": "phpunit --configuration phpunit.xml" }
- Izveidojiet
phpunit.xml
failu:<?xml version="1.0" encoding="UTF-8"?> <phpunit bootstrap="vendor/autoload.php"> <testsuites> <testsuite name="Flight Tests"> <directory>tests</directory> </testsuite> </testsuites> </phpunit>
Tagad jūs 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-pastu:
// 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 kontrolierim:
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:
- Simulējiet POST datus, izmantojot
$app->request()->data
. - Izvairieties no
Flight::
statiskām metodēm savos testos — izmantojiet$app
экземпlāru.
Atkarību injekcijas izmantošana testējamu kontrolieru gadījumā
Injicējiet atkarības (piemēram, datubāzi vai pasta sūtītāju) savos kontrolieros, lai tos būtu viegli mock testos:
use flight\database\PdoWrapper;
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:
use PHPUnit\Framework\TestCase;
class UserControllerDICTest extends TestCase {
public function testValidEmailSavesAndSendsEmail() {
$mockDb = $this->createMock(flight\database\PdoWrapper::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);
}
}
Uzlabota izmantošana
- Mocking: Izmantojiet PHPUnit iebūvētos mock vai anonīmas klases, lai aizstātu atkarības.
- Tieša kontrolieru testēšana: Instantējiet kontrolierus ar jaunu
Engine
un mock atkarības. - Izvairieties no pārmērīga mocking: Ļaujiet reālajai loģikai darboties, kur iespējams; mock tikai ārējos servisus.
Skatīt arī
- Unit Testing Guide - Visaptverošs ceļvedis par vienības testēšanas labākajām praksēm.
- Dependency Injection Container - Kā izmantot DIC, lai pārvaldītu atkarības un uzlabotu testējamību.
- Extending - Kā pievienot savus palīglīdzekļus vai pārrakstīt kodola klases.
- PDO Wrapper - Vienkāršo datubāzes mijiedarbību un ir vieglāk mock testos.
- Requests - HTTP pieprasījumu apstrāde Flight.
- Responses - Atbilžu sūtīšana lietotājiem.
- Unit Testing and SOLID Principles - Uzziniet, kā SOLID principi var uzlabot jūsu vienības testus.
Traucējumu novēršana
- Izvairieties no globālā stāvokļa (
Flight::set()
,$_SESSION
utt.) izmantošanas savā kodā un testos. - Ja jūsu testi ir lēni, iespējams, jūs rakstāt integrācijas testus — mock ārējos servisus, lai vienības testi paliktu ātri.
- Ja testa iestatīšana ir sarežģīta, apsveriet sava koda refaktoringu, lai izmantotu atkarību injekciju.
Izmaiņu žurnāls
- v3.15.0 - Pievienoti piemēri atkarību injekcijai un mocking.
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īgdarbības klase
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 lietotnes veiktspējas uzraudzību (APM) sarežģītām lietošanas situācijām.
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 iegūstat 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ā koplietojamu servisu Flight un pēc tam izmantot to jebkur savā lietotnē caur Flight::db()
.
Pamatlietošana
PDO palīgdarbības reģistrēšana
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 izpildīšana
runQuery()
function runQuery(string $sql, array $params = []): PDOStatement
Izmantojiet to INSERT, UPDATE vai kad vēlaties manuāli 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;
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;
}
Izmantojot IN()
aizstājē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 lietošana
Vaicājumu reģistrēšana & APM
Ja vēlaties izsekot vaicājumu veiktspēju, iespējiet APM izsekošanu reģistrēšanas laikā:
Flight::register('db', \flight\database\PdoWrapper::class, [
'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // pēdējais parametrs iespējina APM
]);
Pēc vaicājumu izpildes jūs varat manuāli reģistrēt tos, 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ājumu metrikiem, ko jūs varat klausīties, izmantojot Flight notikumu sistēmu.
Pilns piemērs
Flight::route('/users', function () {
// Iegūstiet visus lietotājus
$users = Flight::db()->fetchAll('SELECT * FROM users');
// Plūsma visiem lietotājiem
$statement = Flight::db()->runQuery('SELECT * FROM users');
while ($user = $statement->fetch()) {
echo $user['name'];
}
// Iegūstiet vienu lietotāju
$user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]);
// Iegūstiet vienu vērtību
$count = Flight::db()->fetchField('SELECT COUNT(*) FROM users');
// Īpašā 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']);
// Ievietojiet jaunu lietotāju
Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']);
$insert_id = Flight::db()->lastInsertId();
// Atjauniniet lietotāju
Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]);
// Dzēsiet lietotāju
Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]);
// Iegūstiet skarto rindiņu 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ājumu un iegūšanas metodēm.
Learn/dependency_injection_container
Atkarību Injekcijas Konteiners
Pārskats
Atkarību Injekcijas Konteiners (DIC) ir spēcīgs uzlabojums, kas ļauj jums pārvaldīt jūsu lietojumprogrammas atkarības.
Saprašana
Atkarību Injekcija (DI) ir galvenā koncepcija mūsdienu PHP ietvaros un tiek izmantota, lai pārvaldītu objektu instantiāciju un konfigurāciju. Daži DIC bibliotēku piemēri ir: flightphp/container, Dice, Pimple, PHP-DI, un league/container.
DIC ir izsmalcināts veids, kā ļaut jums izveidot un pārvaldīt savas klases centralizētā vietā. Tas ir noderīgi, kad jums jānodod tas pats objekts uz vairākām klasēm (piemēram, jūsu kontrolieriem vai starpprogrammatūras programmatūrai).
Pamata Izmantošana
Vecais veids, kā darīt lietas, var 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 iepriekšējā koda var redzēt, ka mēs izveidojam jaunu PDO
objektu un nododam to
mūsu UserController
klasei. Tas ir labi mazai lietojumprogrammai, bet kad jūsu
lietojumprogramma aug, jūs atklāsiet, ka izveidojat vai nododat to pašu PDO
objektu vairākās vietās. Tieši šeit DIC nāk palīgā.
Šeit ir tas pats piemērs, izmantojot DIC (izmantojot 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());
}
}
// izveidojiet jaunu konteineru
$container = new \Dice\Dice;
// pievienojiet noteikumu, lai pastāstītu konteineram, kā izveidot PDO objektu
// neaizmirstiet to piešķirt atpakaļ sev, 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' ]
]);
// 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();
Es deru, ka jūs varētu domāt, ka piemēram ir pievienots daudz papildu koda.
Burvība nāk tad, kad jums ir cits kontrolieris, kam nepieciešams PDO
objekts.
// Ja visiem jūsu kontrolieriem ir konstruktors, kam nepieciešams PDO objekts
// katrs no maršrutiem zemāk automātiski to saņems injicē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 bonuss, izmantojot DIC, ir tas, ka vienības testēšana kļūst daudz vieglāka. Jūs varat izveidot viltotu objektu un nodot to jūsu klasei. Tas ir liels ieguvums, kad jūs rakstāt testus savai lietojumprogrammai!
Centralizēta DIC apstrādātāja izveide
Jūs varat izveidot centralizētu DIC apstrādātāju savā servisu failā, paplašinot [/learn/extending] jūsu lietojumprogrammu. Šeit ir piemērs:
// services.php
// izveidojiet jaunu konteineru
$container = new \Dice\Dice;
// neaizmirstiet to piešķirt atpakaļ sev, 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/starpprogrammatūrai
Flight::registerContainerHandler(function($class, $params) {
Flight::make($class, $params);
});
// pieņemsim, ka mums ir šāda parauga klase, kas prasa 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();
flightphp/container
Flight ir spraudnis, kas nodrošina vienkāršu PSR-11 atbilstošu konteineru, ko jūs varat izmantot, lai apstrādātu jūsu atkarību injekciju. Šeit ir ātrs piemērs, kā to izmantot:
// 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);
// pareizi izvadīs šo!
}
}
Flight::route('GET /', [TestController::class, 'index']);
Flight::start();
Uzlabota flightphp/container
Izmantošana
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, ko vēlaties izmantot, kas nav PSR-11 (Dice). Skatiet pamata izmantošanu sadaļu, kā to izdarīt.
Turklāt ir daži noderīgi noklusējumi, kas padarīs jūsu dzīvi vieglāku, izmantojot Flight.
Engine Instances
Ja jūs izmantojat Engine
instanci savos kontrolieros/starpprogrammatūrā, šeit ir
kā jūs to konfigurētu:
// Kur kur jūsu bootstrap failā
$engine = Flight::app();
$container = new \Dice\Dice;
$container = $container->addRule('*', [
'substitutions' => [
// Šeit jūs nododāt instanci
Engine::class => $engine
]
]);
$engine->registerContainerHandler(function($class, $params) use ($container) {
return $container->create($class, $params);
});
// Tagad jūs varat izmantot Engine instanci savos kontrolieros/starpprogrammatūrā
class MyController {
public function __construct(Engine $app) {
$this->app = $app;
}
public function index() {
$this->app->render('index');
}
}
Citu Klases Pievienošana
Ja jums ir citas klases, ko vēlaties pievienot konteineram, ar Dice tas ir viegli, jo tās automātiski atrisināsies ar konteineru. Šeit ir piemērs:
$container = new \Dice\Dice;
// Ja jums nav jāinjekē atkarības savās klasēs
// jums nav jādefinē nekas!
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 jebkuru PSR-11 atbilstošu konteineru. Tas nozīmē, ka jūs varat izmantot jebkuru konteineru, kas implementē PSR-11 interfeisu. Šeit ir piemērs, izmantojot League PSR-11 konteineru:
require 'vendor/autoload.php';
// tā pati UserController klase kā iepriekš
$container = new \League\Container\Container();
$container->add(UserController::class)->addArgument(PdoWrapper::class);
$container->add(PdoWrapper::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 verboseāks nekā iepriekšējais Dice piemērs, tas joprojām izpilda darbu ar tiem pašiem ieguvumiem!
Skatīt Arī
- Paplašināšana Flight - Uzziniet, kā jūs varat pievienot atkarību injekciju 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 injekcija darbojas ar kontrolieriem.
- Starpprogrammatūra - Uzziniet, kā izveidot starpprogrammatūru savai lietojumprogrammai un kā atkarību injekcija darbojas ar starpprogrammatūru.
Traucējummeklēšana
- Ja jums ir problēmas ar savu konteineru, pārliecinieties, ka nododat pareizos klases nosaukumus konteineram.
Izmaiņu Žurnāls
- 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,
map
unregister
, 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
false
no 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ē
$_SERVER
masī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
Accept
galvenē, metode atgriezīsnull
. Ja nav definētaAccept
galvene, metode atgriezīs pirmo veidu$availableTypes
masī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()->ip
unrequest()->proxy_ip
var 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ājuKontrolieris
klasē, padodot1234
kā$id
argumentu š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/1234
savā kodā, jūs varētu atsauce vietā lietotlietotājs_skatīt
un padotid
kā 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/json
galveni ar atbildi. Tas arī izmantos karodziņusJSON_THROW_ON_ERROR
unJSON_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 izmantotexit
vaireturn
pē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
$fileName
downloadFile()
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.php
fokusē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.php
failu. 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.$executionTime
ir 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.$executionTime
ir laiks, kas vajadzīgs veidnes renderēšanai. Piezīme: Ja jūs pārdefinējatrender
metodi, 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.$executionTime
ir 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 nodrošina dažas pamata HTML veidņu funkcionalitātes pēc noklusējuma. Veidņošana ir ļoti efektīvs veids, kā atdalīt jūsu lietojumprogrammas loģiku no jūsu prezentācijas slāņa.
Saprašana
Kad jūs būvējat lietojumprogrammu, jums, visticamāk, būs HTML, ko vēlaties nodot atpakaļ gala lietotājam. PHP pats par sevi ir veidņu valoda, bet ir ļoti viegli iekļaut biznesa loģiku, piemēram, datubāzes izsaukumus, API izsaukumus utt., jūsu HTML failā un padarīt testēšanu un atdalīšanu par ļoti sarežģītu procesu. Ievadot datus veidnē un ļaujot veidnei renderēt sevi, kļūst daudz vieglāk atdalīt un veikt vienības testus jūsu kodam. Jūs mums pateiksieties, ja izmantosiet veidnes!
Pamata Izmantošana
Flight ļauj nomainīt noklusējuma skata dzinēju, vienkārši reģistrējot savu paša skata klasi. Ritiniet uz leju, lai redzētu piemērus, kā izmantot Smarty, Latte, Blade un vairāk!
Latte
ieteicams
Šeit ir aprakstīts, kā izmantot Latte veidņu dzinēju jūsu skatiem.
Instalācija
composer require latte/latte
Pamata Konfigurācija
Galvenā ideja ir tā, ka jūs pārrakstāt render
metodi, lai izmantotu Latte nevis noklusējuma PHP renderētāju.
// overwrite the render method to use latte instead of the default PHP renderer
Flight::map('render', function(string $template, array $data, ?string $block): void {
$latte = new Latte\Engine;
// Where latte specifically stores its cache
$latte->setTempDirectory(__DIR__ . '/../cache/');
$finalPath = Flight::get('flight.views.path') . $template;
$latte->render($finalPath, $data, $block);
});
Latte Izmantošana Flight
Tagad, kad jūs varat renderēt ar Latte, jūs varat darīt kaut ko šāda:
<!-- 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 jūs apmeklējat /Bob
savā pārlūkā, 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>
Tālāka Lasīšana
Sarežģītāks Latte izmantošanas piemērs ar izkārtojumiem ir parādīts šīs dokumentācijas awesome plugins sadaļā.
Jūs varat uzzināt vairāk par Latte pilnām iespējām, tostarp tulkošanu un valodas iespējām, lasot oficiālo dokumentāciju.
Iebūvētais Skata Dzinējs
novecojis
Piezīme: Lai gan tas joprojām ir noklusējuma funkcionalitāte un tehniski joprojām darbojas.
Lai parādītu skata veidni, izsauciet render
metodi ar veidnes faila nosaukumu
un opcionāliem veidnes datiem:
Flight::render('hello.php', ['name' => 'Bob']);
Veidnes dati, ko jūs ievadāt, automātiski tiek ievadīti veidnē un var
tikt atsauce kā lokāla mainīgā. Veidnes faili ir vienkārši PHP faili. Ja
satura hello.php
veidnes faila ir:
Hello, <?= $name ?>!
Izvade būtu:
Hello, Bob!
Jūs 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 jūs varat vienkārši darīt:
Flight::render('hello');
Ņemiet vērā, ka norādot veidnes nosaukumu render metodē, jūs varat
izlaist .php
paplašinājumu.
Pēc noklusējuma Flight meklēs views
direktoriju veidnes failiem. Jūs varat
iestatīt alternatīvu ceļu jūsu veidnēm, iestatot šādu konfigurāciju:
Flight::set('flight.views.path', '/path/to/views');
Izkārtojumi
Ir izplatīti, ka tīmekļa vietnēm ir viens izkārtojuma veidnes fails ar mainīgu
saturu. Lai renderētu saturu, ko izmantot izkārtojumā, jūs varat ievadīt opcionālu
parametru render
metodē.
Flight::render('header', ['heading' => 'Hello'], 'headerContent');
Flight::render('body', ['body' => 'World'], 'bodyContent');
Jūsu skats tad būs saglabājis mainīgos, ko sauc par headerContent
un bodyContent
.
Jūs tad varat renderēt savu izkārtojumu darot:
Flight::render('layout', ['title' => 'Home Page']);
Ja veidnes 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
Šeit ir aprakstīts, kā izmantot Smarty veidņu dzinēju jūsu skatiem:
// Load Smarty library
require './Smarty/libs/Smarty.class.php';
// Register Smarty as the view class
// Also pass a callback function to configure Smarty on load
Flight::register('view', Smarty::class, [], function (Smarty $smarty) {
$smarty->setTemplateDir('./templates/');
$smarty->setCompileDir('./templates_c/');
$smarty->setConfigDir('./config/');
$smarty->setCacheDir('./cache/');
});
// Assign template data
Flight::view()->assign('name', 'Bob');
// Display the template
Flight::view()->display('hello.tpl');
Pilnīgumam, 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
Šeit ir aprakstīts, kā izmantot Blade veidņu dzinēju jūsu skatiem:
Vispirms jums jāinstalē BladeOne bibliotēka caur Composer:
composer require eftec/bladeone
Tad jūs varat konfigurēt BladeOne kā skata klasi Flight:
<?php
// Load BladeOne library
use eftec\bladeone\BladeOne;
// Register BladeOne as the view class
// Also pass a callback function to configure BladeOne on load
Flight::register('view', BladeOne::class, [], function (BladeOne $blade) {
$views = __DIR__ . '/../views';
$cache = __DIR__ . '/../cache';
$blade->setPath($views);
$blade->setCompiledPath($cache);
});
// Assign template data
Flight::view()->share('name', 'Bob');
// Display the template
echo Flight::view()->run('hello', []);
Pilnīgumam, 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 izskatīties šādi:
<?php
Hello, {{ $name }}!
Izvade būtu:
Hello, Bob!
Skatīt Arī
- Paplašināšana - Kā pārrakstīt
render
metodi, lai izmantotu citu veidņu dzinēju. - Maršrutēšana - Kā kartēt maršrutus uz kontrolieriem un renderēt skatus.
- Atbildes - Kā pielāgot HTTP atbildes.
- Kāpēc Ietvars? - Kā veidnes iederas lielajā attēlā.
Traucējummeklēšana
- Ja jums ir pāradresēšana jūsu starpprogrammatūrā, bet jūsu lietojumprogramma nešķiet pāradresējamies, pārliecinieties, ka pievienojat
exit;
paziņojumu jūsu starpprogrammatūrā.
Izmaiņu Žurnāls
- v2.0 - Sākotnējais izdevums.
Learn/collections
Kolekcijas
Pārskats
Collection
klase Flight ir ērts rīks datu kopu pārvaldībai. Tā ļauj piekļūt un manipulēt datus, izmantojot gan masīva, gan objekta notāciju, padarot jūsu kodu tīrāku un elastīgāku.
Saprašana
Collection
būtībā ir apvalks ap masīvu, bet ar dažām papildu spējām. Jūs varat izmantot to kā masīvu, iterēt pār to, skaitīt tā vienumus un pat piekļūt vienumiem tā, it kā tie būtu objekta īpašības. Tas ir īpaši noderīgi, kad vēlaties nodot strukturētus datus savā lietojumprogrammā vai kad vēlaties padarīt savu kodu nedaudz lasāmāku.
Kolekcijas īsteno vairākas PHP saskarnes:
ArrayAccess
(tāpēc jūs varat izmantot masīva sintaksi)Iterator
(tāpēc jūs varat iterēt arforeach
)Countable
(tāpēc jūs varat izmantotcount()
)JsonSerializable
(tāpēc jūs varat viegli konvertēt uz JSON)
Pamata Izmantošana
Kolekcijas Izveidošana
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);
Vienumu Piekļūšana
Jūs varat piekļūt vienumiem, izmantojot gan masīva, gan objekta notāciju:
// Masīva notācija
echo $collection['name']; // Izvade: Flight
// Objekta notācija
echo $collection->version; // Izvade: 3
Ja mēģināsiet piekļūt atslēgai, kas nepastāv, saņemsiet null
nevis kļūdu.
Vienumu Iestatīšana
Jūs varat iestatīt vienumus, izmantojot gan notāciju:
// Masīva notācija
$collection['author'] = 'Mike Cao';
// Objekta notācija
$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);
Iterēšana Pār Kolekciju
Kolekcijas ir iterējamas, tāpēc jūs varat izmantot tās foreach
cilpā:
foreach ($collection as $key => $value) {
echo "$key: $value\n";
}
Vienumu Skaitīšana
Jūs varat skaitīt vienumu skaitu kolekcijā:
echo count($collection); // Izvade: 4
Visu Atslēgu vai Datu Iegūšana
Iegūstiet visas atslēgas:
$keys = $collection->keys(); // ['name', 'version', 'features', 'license']
Iegūstiet visus datus kā masīvu:
$data = $collection->getData();
Kolekcijas Notīrīšana
Noņemiet visus vienumus:
$collection->clear();
JSON Serializācija
Kolekcijas var viegli konvertēt uz JSON:
echo json_encode($collection);
// Izvade: {"name":"Flight","version":3,"features":["routing","views","extending"],"license":"MIT"}
Uzlabota Izmantoš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, kad vēlaties nodot strukturētus datus starp komponentiem vai kad vēlaties nodrošināt vairāk objektorientētu saskarni masīva datiem.
Skatīt Arī
- Requests - Uzziniet, kā apstrādāt HTTP pieprasījumus un kā kolekcijas var tikt izmantotas, lai pārvaldītu pieprasījuma datus.
- PDO Wrapper - Uzziniet, kā izmantot PDO apvalku Flight un kā kolekcijas var tikt izmantotas, lai pārvaldītu datubāzes rezultātus.
Traucējumu Novēršana
- Ja mēģināsiet piekļūt atslēgai, kas nepastāv, saņemsiet
null
nevis kļūdu. - Atcerieties, ka kolekcijas nav rekursīvas: iekļautie masīvi netiek automātiski konvertēti uz kolekcijām.
- Ja nepieciešams atiestatīt kolekciju, izmantojiet
$collection->clear()
vai$collection->setData([])
.
Izmaiņu Žurnāls
- v3.0 - Uzlaboti tipa mājieni un PHP 8+ atbalsts.
- v1.0 - Sākotnējā Collection klases izlaišana.
Learn/flight_vs_fat_free
Flight salīdzinājumā ar Fat-Free
Kas ir Fat-Free?
Fat-Free (mīļi saukts par F3) ir jaudīgs, bet viegli lietojams PHP mikroietvars, kas paredzēts, lai palīdzētu jums ātri izveidot dinamiskas un robustas tīmekļa lietojumprogrammas!
Flight salīdzinājumā ar Fat-Free ir daudz kopīga un, iespējams, ir tuvākais radniecīgais ziņā par funkcijām un vienkāršību. Fat-Free ir daudzas funkcijas, kuras Flight nepiedāvā, bet tam ir arī daudz funkciju, kuras Flight piedāvā. Fat-Free sāk parādīt savu vecumu un nav tik populārs, kā tas reiz bija.
Atjauninājumi kļūst retāki, un kopiena nav tik aktīva, kā tas reiz bija. Kods ir pietiekami vienkāršs, bet dažreiz sintakses disciplīnas trūkums var padarīt to grūti lasāmu un saprotamu. Tas darbojas ar PHP 8.3, bet pats kods joprojām izskatās tā, it kā dzīvotu PHP 5.3.
Priekšrocības salīdzinājumā ar Flight
- Fat-Free ir nedaudz vairāk zvaigznes GitHub, nekā Flight.
- Fat-Free ir diezgan laba dokumentācija, bet tai trūkst skaidrības dažās jomās.
- Fat-Free ir daži resursi, piemēram, YouTube apmācības un tiešsaistes raksti, ko var izmantot, lai mācītos ietvaru.
- Fat-Free ir daži noderīgi spraudņi, kas iebūvēti un dažreiz ir noderīgi.
- Fat-Free ir iebūvēts ORM, ko sauc par Mapper, ko var izmantot, lai mijiedarbotos ar jūsu datubāzi. Flight ir active-record.
- Fat-Free ir iebūvētas sesijas, kešošana un lokalizācija. Flight prasa izmantot trešo pušu bibliotēkas, bet tas ir aprakstīts dokumentācijā.
- Fat-Free ir neliela kopienas izveidoto spraudņu grupa, ko var izmantot, lai paplašinātu ietvaru. Flight ir daži, kas aprakstīti dokumentācijā un piemēru lapās.
- Fat-Free, tāpat kā Flight, nav atkarību.
- Fat-Free, tāpat kā Flight, ir paredzēts, lai dotu izstrādātājam kontroli pār viņu lietojumprogrammu un vienkāršu izstrādātāja pieredzi.
- Fat-Free uztur atpakaļ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 tikai iepazīstas ar ietvaru pasauli pirmo reizi.
- Fat-Free ir iebūvēts veidņu dzinējs, kas ir robustāks nekā Flight veidņu dzinējs. Flight iesaka izmantot Latte, lai to sasniegtu.
- Fat-Free ir unikāla CLI veida "route" komanda, kurā varat izveidot CLI lietojumprogrammas pašā Fat-Free un apstrādāt to gandrīz kā
GET
pieprasījumu. Flight to sasniegs ar runway.
Trūkumi salīdzinājumā ar Flight
- Fat-Free ir daži ieviešanas testi un pat savs tests klase, kas ir ļoti pamata. Tomēr, tas nav 100% vienības testēts, kā Flight.
- Jums jāizmanto meklēšanas dzinējs, piemēram, Google, lai faktiski meklētu dokumentācijas vietnē.
- Flight dokumentācijas vietnē ir tumšais režīms. (mic drop)
- Fat-Free ir daži moduļi, kas ir bēdīgi uzturēti.
- Flight ir vienkāršs PdoWrapper, kas ir nedaudz vienkāršāks nekā Fat-Free iebūvētais
DB\SQL
klase. - Flight ir atļauju spraudnis, ko var izmantot, lai nodrošinātu jūsu lietojumprogrammu. Fat Free prasa izmantot trešo pušu bibliotēku.
- Flight ir ORM, ko sauc par active-record, kas jūtas vairāk kā ORM nekā Fat-Free Mapper.
Papildu ieguvums
active-record
ir tas, ka varat definēt saiknes starp ierakstiem automātiskiem savienojumiem, kur Fat-Free Mapper prasa izveidot SQL skatus. - Pārsteidzoši, bet Fat-Free nav saknes vārdtelpas. Flight ir vārdtelpota visā garumā, lai nekonfliktētu ar jūsu paša kodu.
Cache
klase ir lielākais pārkāpējs šeit. - Fat-Free nav starpprogrammatūras. Tā vietā ir
beforeroute
unafterroute
āķi, ko var izmantot, lai filtrētu pieprasījumus un atbildes kontroteros. - Fat-Free nevar grupēt maršrutus.
- Fat-Free ir atkarību injekcijas konteinera apstrādātājs, bet dokumentācija ir neticami skopa par to, kā to izmantot.
- Kļūdu labošana var kļūt nedaudz sarežģīta, jo faktiski viss ir saglabāts tajā, ko sauc par
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 jums ātri rakstīt vienkāršas, bet spēcīgas tīmekļa lietojumprogrammas un API.
Liela daļa iedvesmas dažām no Flight 3. versijas funkcijām faktiski nāca no Slim. Maršrutu grupēšana un starpprogrammatūras izpilde noteiktā secībā ir divas funkcijas, kas tika iedvesmotas no Slim. Slim 3. versija iznāca ar mērķi uz vienkāršību, bet attiecībā uz 4. versiju ir bijušas pretrunīgas atsauksmes.
Priekšrocības salīdzinājumā ar Flight
- Slim ir lielāka izstrādātāju kopiena, kuri savukārt izveido noderīgus moduļus, lai palīdzētu jums neizgudrot ratu no jauna.
- Slim ievēro daudzas saskarnes un standartus, kas ir izplatīti PHP kopienā, kas palielina savietojamību.
- Slim ir labas dokumentācijas un apmācību materiāli, ko var izmantot, lai mācītos ietvaru (nekas salīdzinājumā ar Laravel vai Symfony gan).
- Slim ir dažādi resursi, piemēram, YouTube apmācības un tiešsaistes raksti, ko var izmantot, lai mācītos ietvaru.
- Slim ļauj izmantot jebkuru komponentu, 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, Slim nav tik ātrs, kā jūs domājat, ka tas būtu mikro-ietvaram. Skatiet TechEmpower etalonus 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, savukārt Slim ir dažas atkarības, kuras jums jāinstalē.
- Flight ir paredzēts vienkāršībai un vieglai lietošanai.
- Viena no Flight galvenajām funkcijām ir tā, ka tā dara visu iespējamo, lai uzturētu atpakaļsaderību. Slim no 3. uz 4. versiju bija salauzta izmaiņa.
- Flight ir paredzēts izstrādātājiem, kuri pirmo reizi dodas ietvaru pasaulē.
- Flight var veikt arī uzņēmējdarbības 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, savukārt Slim var ieviesies dažus burvjus aizkulisēs.
- Flight ir vienkāršs PdoWrapper, ko var izmantot, lai mijiedarbotos ar jūsu datubāzi. Slim prasa izmantot trešās puses bibliotēku.
- Flight ir atļauju spraudnis [/awesome-plugins/permissions], ko var izmantot, lai nodrošinātu jūsu lietojumprogrammu. Slim prasa izmantot trešās puses bibliotēku.
- Flight ir ORM, ko sauc par active-record, ko var izmantot, lai mijiedarbotos ar jūsu datubāzi. Slim prasa izmantot trešās puses bibliotēku.
- Flight ir CLI lietojumprogramma, ko sauc par runway, ko var izmantot, lai palaistu jūsu lietojumprogrammu no komandrindas. Slim to nedara.
Learn/autoloading
Autoloading
Pārskats
Autoloading ir PHP koncepts, kurā jūs norādāt direktoriju vai direktorijus, no kuriem ielādēt klases. Tas ir daudz izdevīgāk nekā izmantot require
vai include
klašu ielādei. Tas ir arī prasība Composer pakotņu izmantošanai.
Saprašana
Pēc noklusējuma jebkura Flight
klase tiek automātiski autoloadēta jums, pateicoties composer. Tomēr, ja vēlaties autoloadēt savas klases, jūs varat izmantot Flight::path()
metodi, lai norādītu direktoriju, no kura ielādēt klases.
Autoloadera izmantošana var palīdzēt ievērojami vienkāršot jūsu kodu. Tā vietā, lai faili sāktos ar daudziem include
vai require
paziņojumiem augšpusē, lai uztvertu visas tajā failā izmantotās klases, jūs varat dinamiski izsaukt savas klases, un tās tiks iekļautas automātiski.
Pamatlietojums
Pieņemsim, ka mums ir direktoriju koks šāds:
# Piemēra ceļš
/home/user/project/my-flight-project/
├── app
│ ├── cache
│ ├── config
│ ├── controllers - satur šī projekta kontrolierus
│ ├── translations
│ ├── UTILS - satur klases tikai šai lietojumprogrammai (tas ir visi lielie burti mērķtiecīgi piemēram vēlāk)
│ └── views
└── public
└── css
└── js
└── index.php
Jūs varbūt pamanījāt, ka tas ir tāds pats failu struktūra kā šī dokumentācijas vietnei.
Jūs varat norādīt katru direktoriju, no kura ielādēt, šādi:
/**
* public/index.php
*/
// Pievienojiet ceļu autoloaderim
Flight::path(__DIR__.'/../app/controllers/');
Flight::path(__DIR__.'/../app/utils/');
/**
* app/controllers/MyController.php
*/
// nav nepieciešama vārdu telpa
// Visām autoloadētajām klasēm ieteicams būt Pascal Case (katrs vārds ar lielu burtu, bez atstarpēm)
class MyController {
public function index() {
// dariet kaut ko
}
}
Vārdu telpas
Ja jums ir vārdu telpas, tas faktiski kļūst ļoti viegli ieviest. Jums vajadzētu izmantot Flight::path()
metodi, lai norādītu jūsu lietojumprogrammas saknes direktoriju (nevis dokumenta sakni vai public/
mapi).
/**
* public/index.php
*/
// Pievienojiet ceļu autoloaderim
Flight::path(__DIR__.'/../');
Tagad tas ir jūsu kontrolieris izskatītos. Skatiet piemēru zemāk, bet pievērsiet uzmanību komentāriem svarīgai informācijai.
/**
* app/controllers/MyController.php
*/
// vārdu telpas ir nepieciešamas
// vārdu telpas ir tādas pašas kā direktoriju struktūra
// vārdu telpām jāatbilst tāpat kā direktoriju struktūrai
// vārdu telpām un direktorijiem nevar būt apakšsvītras (ja vien nav iestatīts Loader::setV2ClassLoading(false))
namespace app\controllers;
// Visām autoloadētajām klasēm ieteicams būt Pascal Case (katrs vārds ar lielu burtu, bez atstarpēm)
// No 3.7.2 versijas, jūs varat izmantot Pascal_Snake_Case savām klases nosaukumiem, palaižot Loader::setV2ClassLoading(false);
class MyController {
public function index() {
// dariet kaut ko
}
}
Un ja jūs vēlaties autoloadēt klasi jūsu utils direktorijā, jūs darītu gandrīz to pašu:
/**
* app/UTILS/ArrayHelperUtil.php
*/
// vārdu telpai jāatbilst direktoriju struktūrai un reģistram (pamaniet, ka UTILS direktorija ir visi lielie burti
// kā failu kokā augstāk)
namespace app\UTILS;
class ArrayHelperUtil {
public function changeArrayCase(array $array) {
// dariet kaut ko
}
}
Apakšsvītras klases nosaukumos
No 3.7.2 versijas, jūs varat izmantot Pascal_Snake_Case savām klases nosaukumiem, palaižot Loader::setV2ClassLoading(false);
.
Tas ļaus izmantot apakšsvītras jūsu klases nosaukumos.
Tas nav ieteicams, bet tas ir pieejams tiem, kam tas ir nepieciešams.
use flight\core\Loader;
/**
* public/index.php
*/
// Pievienojiet ceļu autoloaderim
Flight::path(__DIR__.'/../app/controllers/');
Flight::path(__DIR__.'/../app/utils/');
Loader::setV2ClassLoading(false);
/**
* app/controllers/My_Controller.php
*/
// nav nepieciešama vārdu telpa
class My_Controller {
public function index() {
// dariet kaut ko
}
}
Skatīt arī
- Routing - Kā kartēt maršrutus uz kontrolieriem un renderēt skatus.
- Why a Framework? - Saprast ieguvumus, izmantojot ietvaru kā Flight.
Traucējummeklēšana
- Ja jūs nevarat saprast, kāpēc jūsu vārdu telpās esošās klases netiek atrastas, atcerieties izmantot
Flight::path()
uz jūsu projekta saknes direktoriju, nevis jūsuapp/
vaisrc/
direktoriju vai ekvivalentu.
Klase netika atrasta (autoloading nedarbojas)
Šim var būt pāris iemesli. Zemāk ir daži piemēri, bet pārliecinieties, ka jūs arī apskatāt autoloading sadaļu.
Nepareizs faila nosaukums
Visbiežākais ir tas, ka klases nosaukums neatbilst faila nosaukumam.
Ja jums ir klase ar nosaukumu MyClass
, tad failam jābūt nosauktam MyClass.php
. Ja jums ir klase ar nosaukumu MyClass
un fails ir nosaukts myclass.php
tad autoloader nevarēs to atrast.
Nepareiza vārdu telpa
Ja jūs izmantojat vārdu telpas, tad vārdu telpai jāatbilst direktoriju struktūrai.
// ...kods...
// ja jūsu MyController ir app/controllers direktorijā un tas ir ar vārdu telpu
// tas nedarbosies.
Flight::route('/hello', 'MyController->hello');
// jums jāizvēlas viena no šīm opcijām
Flight::route('/hello', 'app\controllers\MyController->hello');
// vai ja jums ir use paziņojums augšpusē
use app\controllers\MyController;
Flight::route('/hello', [ MyController::class, 'hello' ]);
// var arī rakstīt
Flight::route('/hello', MyController::class.'->hello');
// arī...
Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]);
path()
nav definēts
Skeletā lietojumprogrammā tas ir definēts config.php
failā, bet lai jūsu klases tiktu atrastas, jums jāpārliecinās, ka path()
metode ir definēta (droši vien uz jūsu direktorijas sakni) pirms mēģināt to izmantot.
// Pievienojiet ceļu autoloaderim
Flight::path(__DIR__.'/../');
Izmaiņu žurnāls
- v3.7.2 - Jūs varat izmantot Pascal_Snake_Case savām klases nosaukumiem, palaižot
Loader::setV2ClassLoading(false);
- v2.0 - Autoload funkcionalitāte pievienota.
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_filesize
unpost_max_size
iestatījumi var ierobežot failu augšupielādi. - Vairāku failu augšupielādes gadījumā vienmēr iterējiet caur
UploadedFile
objektu masīvu.
Izmaiņu žurnāls
- v3.12.0 - Pievienota
UploadedFile
klase pieprasījuma objektam vieglākai failu apstrādei.
Guides/unit_testing
Vienības testēšana Flight PHP ar PHPUnit
Šis ceļvedis iepazīstina ar vienības testēšanu Flight PHP, izmantojot PHPUnit, kas paredzēts iesācējiem, kuri vēlas saprast, kāpēc vienības testēšana ir svarīga un kā to praktiski pielietot. Mēs koncentrēsimies uz testēšanu uzvedības — nodrošinot, ka jūsu lietojumprogramma darbojas tā, kā jūs sagaidāt, piemēram, nosūtot e-pastu vai saglabājot ierakstu — nevis uz sīkumainiem aprēķiniem. Mēs sāksim ar vienkāršu maršruta apstrādātāju un pakāpeniski pāriesim pie sarežģītāka kontrolera, iekļaujot atkarību injekciju (DI) un trešo pušu servisu mockēšanu.
Kāpēc veikt vienības testus?
Vienības testēšana nodrošina, ka jūsu kods uzvedas kā paredzēts, uztverot 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 radīt sarežģītas mijiedarbības. Vienības testi darbojas kā drošības tīkls solo izstrādātājiem vai komandām, dokumentējot paredzēto uzvedību un novēršot regresijas, kad jūs vēlāk atgriežaties pie koda. Tie arī uzlabo dizainu: kodu, kas ir grūti testēt, bieži norāda uz pārmērīgi sarežģītām vai cieši saistītām klasēm.
Atšķirībā no vienkāršiem piemēriem (piemēram, testēšana x * y = z
), mēs koncentrēsimies uz reālās pasaules uzvedībām, piemēram, ievades validēšanu, datu saglabāšanu vai darbību izraisīšanu, piemēram, e-pastus. Mūsu mērķis ir padarīt testēšanu pieejamu un jēgpilnu.
Vispārīgi vadības principi
- Testējiet uzvedību, nevis realizāciju: 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 refaktoringu.
- Pārtrauciet izmantot
Flight::
: Flight statiskās metodes ir ārkārtīgi ērtas, bet apgrūtina testēšanu. Jums vajadzētu pierast izmantot$app
mainīgo no$app = Flight::app();
.$app
satur visas tās pašas metodes, kasFlight::
. Jūs joprojām varēsiet izmantot$app->route()
vai$this->app->json()
savā kontrolerī utt. Jums arī vajadzētu izmantot īsto Flight maršrutētāju ar$router = $app->router()
un tad varēsiet izmantot$router->get()
,$router->post()
,$router->group()
utt. Skatiet Routing. - Uzturiet testus ātrus: Ātri testi veicina biežu izpildi. Izvairieties no lēnām operācijām, piemēram, datubāzes izsaukumiem vienības testos. Ja jums ir lēns tests, tas ir zīme, ka jūs rakstāt integrācijas testu, nevis vienības testu. Integrācijas testi ir tad, kad jūs patiešām 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žreiz neizdodas nezināma iemesla dēļ.
- Izmantojiet aprakstošus nosaukumus: Testu nosaukumiem jāapraksta skaidri testētā uzvedība. Tas uzlabo lasāmību un uzturējamību.
- Izvairieties no globāliem mainīgajiem kā no mēra: Minimāli izmantojiet
$app->set()
un$app->get()
, jo tie darbojas kā globālais stāvoklis, prasot mockus katrā testā. Dodiet priekšroku DI vai DI konteineram (skatiet Dependency Injection Container). Pat izmantojot$app->map()
metodi, tehniski ir "globāls" un jāizvairās no tā par labu DI. Izmantojiet sesijas bibliotēku, piemēram, flightphp/session, lai varētu mockēt sesijas objektu savos testos. Neizsauciet$_SESSION
tieši savā kodā, jo tas ievada globālo mainīgo jūsu kodā, apgrūtinot testēšanu. - Izmantojiet atkarību injekciju: Injektējiet atkarības (piemēram,
PDO
, pasta sūtītājus) kontroleros, lai izolētu loģiku un atvieglotu mockēšanu. Ja jums ir klase ar pārāk daudzām atkarībām, apsvēriet tās refaktoringu mazākās klasēs, kurām katrai ir viena atbildība, ievērojot SOLID principus. - Mockējiet trešo pušu servisus: Mockējiet datubāzes, HTTP klientus (cURL) vai e-pasta servisus, lai izvairītos no ārējiem izsaukumiem. Testējiet vienu vai divus slāņus dziļi, bet ļaujiet jūsu kodola loģikai darboties. Piemēram, ja jūsu lietojumprogramma nosūta īsziņu, jūs NEGRIBAT patiešām sūtīt īsziņu katru reizi, kad palaižat testus, jo šie maksājumi sakopsies (un tas būs lēnāks). Tā vietā mockējiet īsziņas servisu un tikai pārbaudiet, ka jūsu kods izsauca īsziņas servisu ar pareizajiem parametriem.
- Mērķis 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 (droši vien pētiet zaru/ceļa pārklājumu PHPUnit). Prioritizējiet kritiskās uzvedības (piemēram, lietotāja reģistrāciju, API atbildes un neizdevušos atbilžu uztveršanu).
- Izmantojiet kontrolerus maršrutiem: Savos maršruta definīcijās izmantojiet kontrolerus, nevis aizvēršanas.
flight\Engine $app
pēc noklusējuma tiek injicēts katrā kontrolerā caur konstruktoru. Testos izmantojiet$app = new Flight\Engine()
, lai inicializētu Flight testā, injicējiet to kontrolerī un izsauciet metodes tieši (piemēram,$controller->register()
). Skatiet Extending Flight un Routing. - Izvēlieties mockēšanas stilu un turieties pie tā: PHPUnit atbalsta vairākus mockēšanas stilus (piemēram, prophecy, iebūvēti mocki), vai varat izmantot anonīmas klases, kurām ir savas priekšrocības, piemēram, koda pabeigšana, salūšana, ja maināt metodes definīciju utt. Tikai esiet konsekventi visos savos testos. Skatiet PHPUnit Mock Objects.
- Izmantojiet
protected
redzamību metodēm/īpašībām, kuras vēlaties testēt apakšklasēs: Tas ļauj jums tās pārrakstīt testu apakšklasēs, nepadarot tās publiskām, tas ir īpaši noderīgi anonīmu klašu mockiem.
PHPUnit iestatīšana
Vispirms iestatiet PHPUnit savā Flight PHP projektā, izmantojot Composer vieglai testēšanai. Skatiet PHPUnit Sākuma ceļvedi sīkākiem detalizācijām.
-
Savā projektu direktorijā palaidiet:
composer require --dev phpunit/phpunit
Tas instalē jaunāko PHPUnit kā izstrādes atkarību.
-
Izveidojiet
tests
direktoriju jūsu projekta saknē testu failiem. -
Pievienojiet testa skriptu
composer.json
ērtībai:// cits composer.json saturs "scripts": { "test": "phpunit --configuration phpunit.xml" }
-
Izveidojiet
phpunit.xml
failu saknē:<?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 palaidiet 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: atgriežot veiksmīgu ziņu derīgiem e-pastiem un kļūdu nederīgiem. E-pasta validēšanai 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 Unit Testing and SOLID Principles par vairāk informācijas par testu struktūru:
// 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'; // Simulate POST data
$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'; // Simulate POST data
$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ālos mainīgos, piemēram,
$_POST
,$_GET
utt., jo tas padara testēšanu sarežģītāku (jums vienmēr jāatstata šīs vērtības, vai citādi citi testi var sabrukt). - Visi kontroleri pēc noklusējuma saņems
flight\Engine
instanci, kas injicēta tajos pat bez DIC konteinera iestatīšanas. Tas ievērojami atvieglo kontroleru tiešo testēšanu. - Nav nekādas
Flight::
izmantošanas vispār, padarot kodu vieglāku testēšanai. - Testi pārbauda uzvedību: pareizu statusu un ziņu derīgiem/nederīgiem e-pastiem.
Palaidiet composer test
, lai pārbaudītu, vai maršruts uzvedas kā paredzēts. Par vairāk informācijas par pieprasījumiem un atbildēm Flight, skatiet attiecīgos dokumentus.
Atkarību injekcijas izmantošana testējamu kontroleru izveidošanai
Sarežģītākiem scenārijiem izmantojiet atkarību injekciju (DI), lai padarītu kontrolerus testējamus. Izvairieties no Flight globāliem (piemēram, Flight::set()
, Flight::map()
, Flight::register()
), jo tie darbojas kā globālais stāvoklis, prasot mockus katram testam. Tā vietā izmantojiet Flight DI konteineru, DICE, PHP-DI vai manuālu DI.
Izmantojiet flight\database\PdoWrapper
nevis neapstrādātu PDO. Šis apvalks ir daudz vieglāk mockēt un veikt vienības testus!
Šeit ir kontroleris, kas saglabā lietotāju datubāzē un nosūta laipnu e-pastu:
use flight\database\PdoWrapper;
class UserController {
protected $app;
protected $db;
protected $mailer;
public function __construct(Engine $app, PdoWrapper $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)) {
// adding the return here helps unit testing to stop execution
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:
- Kontroleris ir atkarīgs no
PdoWrapper
instances unMailerInterface
(izdomāts trešās puses e-pasta serviss). - Atkarības tiek injicētas caur konstruktoru, izvairoties no globāliem.
Kontrolera testēšana ar mockiem
Tagad testēsim UserController
uzvedību: e-pasta validēšanu, saglabāšanu datubāzē un e-pasta sūtīšanu. Mēs mockēsim datubāzi un pasta sūtītāju, lai izolētu kontroleri.
// tests/UserControllerDICTest.php
use PHPUnit\Framework\TestCase;
class UserControllerDICTest extends TestCase {
public function testValidEmailSavesAndSendsEmail() {
// Sometimes mixing mocking styles is necessary
// Here we use PHPUnit's built-in mock for PDOStatement
$statementMock = $this->createMock(PDOStatement::class);
$statementMock->method('execute')->willReturn(true);
// Using an anonymous class to mock PdoWrapper
$mockDb = new class($statementMock) extends PdoWrapper {
protected $statementMock;
public function __construct($statementMock) {
$this->statementMock = $statementMock;
}
// When we mock it this way, we are not really making a database call.
// We can further setup this to alter the PDOStatement mock to simulate failures, etc.
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 PdoWrapper {
// An empty constructor bypasses the parent constructor
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';
// Need to map jsonHalt to avoid exiting
$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 mockējam
PdoWrapper
unMailerInterface
, lai izvairītos no reāliem datubāzes vai e-pasta izsaukumiem. - Testi pārbauda uzvedību: derīgi e-pasti izraisa datubāzes ievietošanu un e-pasta sūtīšanu; nederīgi e-pasti izlaiž abus.
- Mockējiet trešās puses atkarības (piemēram,
PdoWrapper
,MailerInterface
), ļaujot kontrolera loģikai darboties.
Pārāk daudz mockēšana
Esiet uzmanīgi, lai nemockētu pārāk daudz sava koda. Ļaujiet man dot piemēru zemāk par to, kāpēc tas var būt sliktas lietas, izmantojot mūsu UserController
. Mēs mainīsim šo pārbaudi uz metodi, ko sauc isEmailValid
(izmantojot filter_var
) un citas jaunas pievienojumus uz atsevišķu metodi, ko sauc registerUser
.
use flight\database\PdoWrapper;
use flight\Engine;
// UserControllerDICV2.php
class UserControllerDICV2 {
protected $app;
protected $db;
protected $mailer;
public function __construct(Engine $app, PdoWrapper $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)) {
// adding the return here helps unit testing to stop execution
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 mockētais vienības tests, kas patiesībā neko netestē:
use PHPUnit\Framework\TestCase;
class UserControllerTest extends TestCase {
public function testValidEmailSavesAndSendsEmail() {
$app = new Engine();
$app->request()->data->email = 'test@example.com';
// we are skipping the extra dependency injection here cause it's "easy"
$controller = new class($app) extends UserControllerDICV2 {
protected $app;
// Bypass the deps in the construct
public function __construct($app) {
$this->app = $app;
}
// We'll just force this to be valid.
protected function isEmailValid($email) {
return true; // Always return true, bypassing real validation
}
// Bypass the actual DB and mailer calls
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']);
}
}
Hurā, mums ir vienības testi un tie iziet! Bet pagaidi, ko tad, ja es patiesībā mainu isEmailValid
vai registerUser
iekšējo darbību? Mani testi joprojām izies, jo esmu mockējis visu funkcionalitāti. Ļaujiet man parādīt, ko es domāju.
// UserControllerDICV2.php
class UserControllerDICV2 {
// ... other methods ...
protected function isEmailValid($email) {
// Changed logic
$validEmail = filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
// Now it should only have a specific domain
$validDomain = strpos($email, '@example.com') !== false;
return $validEmail && $validDomain;
}
}
Ja es palaižu savus iepriekšējos vienības testus, tie joprojām iziet! Bet tāpēc, ka es netestēju uzvedību (patiesībā neļāvu daļai koda darboties), esmu potenciāli ieprogrammējis kļūdu, kas gaida ražošanā. Tests vajadzētu modificēt, lai ņemtu vērā jauno uzvedību, un arī pretējo, kad uzvedība nav tā, ko mēs sagaidām.
Pilns piemērs
Varat atrast pilnu Flight PHP projektu piemēru ar vienības testiem GitHub: n0nag0n/flight-unit-tests-guide. Lai iegūtu dziļāku izpratni, skatiet Unit Testing and SOLID Principles.
Biežas kļūdas
- Pārāk daudz mockēšana: Nemockējiet katru atkarību; ļaujiet daļai loģikas (piemēram, kontrolera validēšanai) darboties, lai testētu reālo uzvedību. Skatiet Unit Testing and SOLID Principles.
- Globālais stāvoklis: Izmantojot globālos PHP mainīgos (piemēram,
$_SESSION
,$_COOKIE
) intensīvi, testi kļūst trausli. Tas pats attiecas uzFlight::
. Refaktorējiet, lai eksplíciti nodotu atkarības. - Sarežģīta iestatīšana: Ja testa iestatīšana ir apgrūtinoša, jūsu klasei var būt pārāk daudz atkarību vai atbildību, kas pārkāpj SOLID principus.
Mērogošana ar vienības testiem
Vienības testi spīd lielākos projektos vai kad atgriežaties pie koda pēc mēnešiem. Tie dokumentē uzvedību un uztver regresijas, ietaupot laiku no atkārtotas mācīšanās jūsu lietojumprogrammai. Solo 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 ieguldījumos. Skatiet Why Frameworks? par vairāk priekšrocībām, izmantojot ietvarus un testus.
Iesaistiet savus testēšanas padomus Flight PHP dokumentācijas repozitorijā!
Rakstījis n0nag0n 2025
Guides/blog
Vienkārša emuāra izveide ar Flight PHP
Šis ceļvedis nodrošina soļus, kā izveidot pamata emuāru, izmantojot Flight PHP ietvaru. Jūs izveidosiet projektu, definēsiet maršrutus, pārvaldīsiet ierakstus, izmantojot JSON, un attēlosiet tos ar Latte veidņu dzinēju, tādējādi demonstrējot Flight vienkāršību un elastību. Ceļojuma beigās jums būs funkcionāls emuārs ar sākumlapu, individuālām ierakstu lapām un izveides formu.
Prasības
- 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.
- Pamata zināšanas par PHP un tīmekļa izstrādi.
1. solis: Iestatiet savu projektu
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
). Izveidojietpublic/
mapi tam:mkdir public
-
Pamata
index.php
: Izveidojietpublic/index.php
ar vienkāršu “hello world” maršrutu:<?php require '../vendor/autoload.php'; Flight::route('/', function () { echo 'Sveiki, Flight!'; }); Flight::start();
-
Palaidiet iebūvēto serveri: Pārbaudiet savu iestatījumu, izmantojot PHP izstrādes serveri:
php -S localhost:8000 -t public/
Apmeklējiet
http://localhost:8000
, lai redzētu “Sveiki, Flight!”.
2. solis: Organizējiet sava projekta struktūru
Lai nodrošinātu tīru iestatījumu, strukturējiet savu 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 attēlošanai.data/
: JSON fails emuāru ierakstu glabāšanai.public/
: Tīmekļa sakne arindex.php
.
3. solis: Instalējiet un konfigurējiet Latte
Latte ir viegla veidņu dzinēja, 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ā skata 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' => 'Mans emuārs']); }); Flight::start();
-
Izveidojiet izkārtojuma veidni:
app/views/layout.latte
:<!DOCTYPE html> <html> <head> <title>{$title}</title> </head> <body> <header> <h1>Mans emuārs</h1> <nav> <a href="/">Sākums</a> | <a href="/create">Izveidot ierakstu</a> </nav> </header> <main> {block content}{/block} </main> <footer> <p>© {date('Y')} Flight emuārs</p> </footer> </body> </html>
-
Izveidojiet sākumlapa veidni:
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 to izslēguši, un apmeklējiet
http://localhost:8000
, lai redzētu attēloto lapu. -
Izveidojiet datu failu:
Izmantojiet JSON failu, lai simulētu datu bāzi vienkāršības labad.
data/posts.json
:[ { "slug": "pirmais-ieraksts", "title": "Mans pirmais ieraksts", "content": "Šis ir mans pirmais emuāra ieraksts ar Flight PHP!" } ]
4. solis: Definējiet maršrutus
Atsevišķiet savus maršrutus konfigurācijas failā labākai organizācijai.
-
Izveidojiet
routes.php
:app/config/routes.php
:<?php Flight::route('/', function () { Flight::view()->render('home.latte', ['title' => 'Mans emuārs']); }); Flight::route('/post/@slug', function ($slug) { Flight::view()->render('post.latte', ['title' => 'Ieraksts: ' . $slug, 'slug' => $slug]); }); Flight::route('GET /create', function () { Flight::view()->render('create.latte', ['title' => 'Izveidot ierakstu']); });
-
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: Glabājiet un iegūstiet emuāru ierakstus
Pievienojiet metodes, lai ielādētu un saglabātu ierakstus.
-
Pievienojiet ierakstu metodi:
index.php
pievienojiet metodi ierakstu ielādei:Flight::map('posts', function () { $file = __DIR__ . '/../data/posts.json'; return json_decode(file_get_contents($file), true); });
-
Atjauniniet maršrutus: Izmainiet
app/config/routes.php
, lai izmantotu ierakstus:<?php Flight::route('/', function () { $posts = Flight::posts(); Flight::view()->render('home.latte', [ 'title' => 'Mans emuārs', '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' => 'Izveidot ierakstu']); });
6. solis: Izveidojiet veidnes
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: Pievienojiet ierakstu izveidi
Rīkojieties ar formas iesniegšanu, lai pievienotu jaunus ierakstus.
-
Izveidojiet formu (
app/views/create.latte
):{extends 'layout.latte'} {block content} <h2>{$title}</h2> <form method="POST" action="/create"> <div class="form-group"> <label for="title">Nosaukums:</label> <input type="text" name="title" id="title" required> </div> <div class="form-group"> <label for="content">Saturs:</label> <textarea name="content" id="content" required></textarea> </div> <button type="submit">Saglabāt ierakstu</button> </form> {/block}
-
Pievienojiet POST maršrutu:
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('/'); });
-
Pārbaudiet 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: Uzlabojiet ar kļūdu apstrādi
Pārdefinējiet notFound
metodi, lai uzlabotu 404 pieredzi.
index.php
:
Flight::map('notFound', function () {
Flight::view()->render('404.latte', ['title' => 'Lapa nav atrasta']);
});
Izveidojiet app/views/404.latte
:
{extends 'layout.latte'}
{block content}
<h2>404 - {$title}</h2>
<p>Atvainojiet, šī lapa neeksistē!</p>
{/block}
Nākamie soļi
- Pievienojiet stilu: Izmantojiet CSS savās veidnēs labākam izskatam.
- Datu bāze: Aizvietojiet
posts.json
ar datu bāzi, piemēram, SQLite, izmantojotPdoWrapper
. - Validācija: Pievienojiet pārbaudes dublēto slogu vai tukšu ievadi.
- Middleware: Ieviesiet autentifikāciju ierakstu izveidei.
Secinājums
Jūs esat izveidojis vienkāršu emuāru ar Flight PHP! Šis ceļvedis demonstrē pamatfunkcijas, piemēram, maršrutēšanu, veidņu veidošanu ar Latte un formu iesniegšanu, vienlaikus saglabājot lietas vieglas. Izpētiet Flight dokumentāciju, lai uzzinātu vairāk par uzlabotām 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 ietvars PHP—izveidots izstrādātājiem, kuri vēlas ātri paveikt darbus, bez liekām raizēm. Vai jūs veidojat klasisku tīmekļa lietotni, ātru API vai eksperimentējat ar jaunākajām AI balstītajām rīkiem, Flight zems nospiedums un vienkāršais dizains padara to par ideālu izvēli. Flight ir domāts, lai būtu viegls, bet tas var arī tikt galā ar uzņēmuma arhitektūras prasībām.
Kāpēc izvēlēties Flight?
- Sācējiem draudzīgs: Flight ir lielisks sākumpunkts jauniem PHP izstrādātājiem. Tā skaidrā struktūra un vienkāršā sintakse palīdz iemācīties tīmekļa attīstību, nezaudējot laiku liekā kodā.
- Profesionāļu mīlulis: Pieredzējuši izstrādātāji mīl Flight par tās elastību un kontroli. Jūs varat augt no neliela prototipa līdz pilnvērtīgai lietotnei, neizmainot ietvarus.
- AI draudzīgs: Flight minimālais slogs un tīrais arhitektūras dizains padara to ideālu AI rīku un API integrācijai. Vai jūs veidojat gudrus čatbotus, AI vadītas paneļus vai vienkārši vēlaties eksperimentēt, Flight netraucē, ļaujot koncentrēties uz svarīgo. Skeletapp nāk ar iepriekš sagatavotiem instrukciju failiem galvenajiem AI kodēšanas asistentiem jau no kastes! Uzziniet vairāk par AI izmantošanu ar Flight
Video Overview
Quick Start
Lai veiktu ātru, pamata instalāciju, instalējiet to ar Composer:
composer require flightphp/core
Vai jūs varat lejupielādēt zip failu no repozitorijas šeit. Tad jums būs pamata index.php
fails, piemēram, šāds:
<?php
// ja instalēts ar composer
require 'vendor/autoload.php';
// vai ja instalēts manuāli ar zip failu
// 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 jūs varat palaist šo failu ar php -S localhost:8000
un apmeklēt http://localhost:8000
savā pārlūkā, lai redzētu izvadi.
Skeleton/Boilerplate App
Ir piemērs app, lai palīdzētu jums sākt projektu ar Flight. Tajā ir strukturēta izkārtojums, pamata konfigurācijas un saderība ar composer skriptiem jau no sākuma! Apskatiet flightphp/skeleton gatavam projektam vai apmeklējiet piemērus lapu iedvesmai. Vēlaties redzēt, kā AI iederas? Izpētiet AI balstītus piemērus.
Installing the Skeleton App
Tas ir pietiekami vienkārši!
# Izveidojiet jauno projektu
composer create-project flightphp/skeleton my-project/
# Ieejiet jaunajā projektu direktorijā
cd my-project/
# Palaidiet lokālo attīstības serveri, lai sāktu nekavējoties!
composer start
Tas izveidos projektu struktūru, iestatīs vajadzīgos failus, un jūs esat gatavs!
High Performance
Flight ir viens no ātrākajiem PHP ietvariem. Tā vieglais kodols nozīmē mazāku slogu un vairāk ātrumu—ideāli piemērots gan tradicionālām lietotnēm, gan mūsdienu AI balstītiem projektiem. Jūs varat redzēt visus benchmarkus TechEmpower
Skatiet benchmarku 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 and AI
Vai jūs interesē, kā tas darbojas ar AI? Atklājiet, kā Flight atvieglo darbu ar jūsu mīļākajiem kodēšanas LLM!
Community
Mēs esam Matrix Chat
Un Discord
Contributing
Ir divi veidi, kā jūs varat piedalīties Flight:
- Piedalieties kodola ietvara izstrādē, apmeklējot core repozitoriju.
- Palīdziet uzlabot dokumentāciju! Šī dokumentācijas vietne ir mitināta Github. Ja jūs pamanāt kļūdu vai vēlaties kaut ko uzlabot, iesniedziet pull request. Mēs mīlam atjauninājumus un jaunas idejas—īpaši ap AI un jaunām tehnoloģijām!
Requirements
Flight prasa PHP 7.4 vai jaunāku.
Piezīme: PHP 7.4 tiek atbalstīts, jo šobrīd (2024. gadā) PHP 7.4 ir noklusētā versija dažām LTS Linux izdalēm. Spiešana uz pāreju uz PHP >8 izraisītu daudz neērtību lietotājiem. Ietvars arī atbalsta PHP >8.
License
Flight ir izlaists zem MIT licences.
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
Gaismas, vienkārša un neatkarīga PHP failā kešošanas klase, kas izveidota no Wruczek/PHP-File-Cache forka
Priekšrocības
- Gaisma, neatkarīga un vienkārša
- Viss kods vienā failā - bez bezjēdzīgiem draiveriem.
- Droša - katrs ģenerētais kešošanas fails satur PHP galvenes 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ēta un testēta
- Pareizi apstrādā vienlaicību, izmantojot flock
- Atbalsta PHP 7.4+
- Bezmaksas saskaņā ar MIT licenci
Šī dokumentācijas vietne izmanto šo bibliotēku, lai kešotu katru no lapām!
Noklikšķiniet šeit, lai skatītu kodu.
Instalācija
Instalējiet, izmantojot composer:
composer require flightphp/cache
Lietošana
Lietošana ir diezgan vienkārša. Tas saglabā kešošanas failu kešošanas direktorijā.
use flight\Cache;
$app = Flight::app();
// Jūs nododiet direktoriju, kurā kešs tiks saglabāts, konstruktorā
$app->register('cache', Cache::class, [ __DIR__ . '/../cache/' ], function(Cache $cache) {
// Tas nodrošina, ka kešs tiek izmantots tikai ražošanas režīmā
// ENVIRONMENT ir konstante, kas ir iestatīta jūsu bootstrap failā vai citur jūsu lietotnē
$cache->setDevMode(ENVIRONMENT === 'development');
});
Iegūt kešošanas vērtību
Jūs izmantojat get()
metodi, lai iegūtu kešotu vērtību. Ja vēlaties ērtu metodi, kas atsvaidzinās kešu, ja tas ir beidzies, varat izmantot refreshIfExpired()
.
// Iegūt kešošanas instanci
$cache = Flight::cache();
$data = $cache->refreshIfExpired('simple-cache-test', function () {
return date("H:i:s"); // return data to be cached
}, 10); // 10 sekundes
// or
$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šošanas vērtību
Jūs izmantojat set()
metodi, lai saglabātu vērtību kešā.
Flight::cache()->set('simple-cache-test', 'my cached data', 10); // 10 sekundes
Dzēst kešošanas vērtību
Jūs izmantojat delete()
metodi, lai dzēstu vērtību kešā.
Flight::cache()->delete('simple-cache-test');
Pārbaudīt, vai kešošanas vērtība pastāv
Jūs izmantojat exists()
metodi, lai pārbaudītu, vai vērtība pastāv kešā.
if(Flight::cache()->exists('simple-cache-test')) {
// do something
}
Notīrīt kešu
Jūs izmantojat flush()
metodi, lai notīrītu visu kešu.
Flight::cache()->flush();
Izvilkt meta datus ar kešu
Ja vēlaties izvilkt laika zīmes un citus meta datus par kešošanas ierakstu, pārliecinieties, ka nododiet true
kā pareizo parametru.
$data = $cache->refreshIfExpired("simple-cache-meta-test", function () {
echo "Refreshing data!" . PHP_EOL;
return date("H:i:s"); // return data to be cached
}, 10, true); // true = return with metadata
// or
$data = $cache->get("simple-cache-meta-test", true); // true = return with metadata
/*
Example cached item retrieved with metadata:
{
"time":1511667506, <-- save unix timestamp
"expire":10, <-- expire time in seconds
"data":"04:38:26", <-- unserialized data
"permanent":false
}
Using metadata, we can, for example, calculate when item was saved or when it expires
We can also access the data itself with the "data" key
*/
$expiresin = ($data["time"] + $data["expire"]) - time(); // get unix timestamp when data expires and subtract current timestamp from it
$cacheddate = $data["data"]; // we access the data itself with the "data" key
echo "Latest cache save: $cacheddate, expires in $expiresin seconds";
Dokumentācija
Apmeklējiet https://github.com/flightphp/cache, lai skatītu kodu. Pārliecinieties, ka skatāt examples mapi papildu veidiem, kā izmantot kešu.
Awesome-plugins/permissions
FlightPHP/Atļaujas
Tas ir atļauju modulis, ko var izmantot jūsu projektos, ja jums ir vairākas lomas jūsu lietotnē, un katram no tiem ir nedaudz atšķirīga funkcionalitāte. Šis modulis ļauj definēt atļaujas katrai rolei un pēc tam pārbaudīt, vai pašreizējam lietotājam ir atļauja piekļūt konkrētai lapai vai veikt konkrētu darbību.
Noklikšķiniet šeit GitHub repozitorijai.
Uzstādīšana
Izpildiet composer require flightphp/permissions
, un esat gatavs darbam!
Lietošana
Vispirms jums ir jāiestata savas atļaujas, tad jums jāpasaka savai lietotnei, ko šīs atļaujas nozīmē. Galu galā jūs pārbaudīsiet savas atļaujas ar $Permissions->has()
, ->can()
vai is()
. has()
un can()
ir vienādas funkcijas, bet sauktas atšķirīgi, lai jūsu kods būtu lasāmāks.
Pamata piemērs
Iedomāsimies, ka jums ir funkcija jūsu lietotnē, kas pārbauda, vai lietotājs ir pierakstījies. Jūs varat izveidot atļauju objektu šādi:
// index.php
require 'vendor/autoload.php';
// kods
// pēc tam, iespējams, jums ir kaut kas, kas jums paziņo, kāda ir pašreizējā lietotāja loma
// visticamāk, jums ir kaut kas, kas nosaka pašreizējo lomu
// no sesijas mainīgā, kas to definē
// pēc reģistrēšanās, pretējā gadījumā viņiem būs "viesis" vai "publiska" loma.
$current_role = 'admins';
// iestatīt atļaujas
$permission = new \flight\Permissions($current_role);
$permission->defineRule('pieslēdzies', function($current_role) {
return $current_role !== 'viesis';
});
// Iespējams, ka vēlēsieties šo objektu noturētiegavēkur visur
Flight::set('permission', $permission);
Tad kādā kontrolierī varētu būt kaut kas tāds.
<?php
// dažs kontrolieris
class DaļasKontrolieris {
public function daļasDarbība() {
$atļauja = Flight::get('permission');
if ($atļauja->has('pieslēdzies')) {
// dari kaut ko
} else {
// dari ko citu
}
}
}
Jūs varat izmantot arī to, lai sekotu, vai tiem ir atļauja kaut ko darīt jūsu lietotnē. Piemēram, ja jums ir veids, kā lietotāji var mijiedarboties ar saviem ierakstiem jūsu programmā, jūs varat pārbaudiet, vai viņiem ir atļauja veikt konkrētas darbības.
$current_role = 'admins';
// iestatīt atļaujas
$permission = new \flight\Permission($current_role);
$permission->defineRule('ieraksts', function($current_role) {
if($current_role === 'admins') {
$atļaujas = ['izveidot', 'lasīt', 'labot', 'dzēst'];
} else if($current_role === 'redaktors') {
$atļaujas = ['izveidot', 'lasīt', 'labot'];
} else if($current_role === 'autors') {
$atļaujas = ['izveidot', 'lasīt'];
} else if($current_role === 'līdzstrādnieks') {
$atļaujas = ['izveidot'];
} else {
$atļaujas = [];
}
return $atļaujas;
});
Flight::set('permission', $permission);
Tad kaut kur kontrolierī...
class IerakstaKontrolieris {
public function izveidot() {
$atļauja = Flight::get('permission');
if ($atļauja->can('ieraksts.izveidot')) {
// dari kaut ko
} else {
// dari ko citu
}
}
}
Injicēt atkarības
Jūs varat injicēt atkarības closure, kas definē atļaujas. Tas ir noderīgi, ja jums ir kāda veida pārslēgšana, ID vai jebkura cita dati, pret kuriem vēlaties pārbaudīt. Tas pats attiecas uz Klases->Metodes zvana veidiem, izņemot to, ka argumentus definējat metodē.
Closure
$Permission->defineRule('pasūtījums', function(string $current_role, MyDependency $MyDependency = null) {
// ... kods
});
// jūsu kontroliera failā
public function izveidotPasūtījumu() {
$MyDependency = Flight::myDependency();
$atļauja = Flight::get('permission');
if ($atļauja->can('pasūtījums.izveidot', $MyDependency)) {
// dari kaut ko
} else {
// dari ko citu
}
}
Klases
namespace ManLietotne;
class Atļaujas {
public function pasūtījums(string $current_role, MyDependency $MyDependency = null) {
// ... kods
}
}
Saīsinājums, lai iestatītu atļaujas ar klasēm
Jūs varat izmantot arī klases, lai definētu savas atļaujas. Tas ir noderīgi, ja jums ir daudz atļauju, un vēlaties uzturēt savu kodu tīru. Jūs varat darīt kaut ko tādu kā šis:
<?php
// palaistāmais kods
$Permissions = new \flight\Permission($current_role);
$Permissions->defineRule('pasūtījums', 'ManLietotne\Atļaujas->pasūtījums');
// myapp/Permissions.php
namespace ManLietotne;
class Atļaujas {
public function pasūtījums(string $current_role, int $lietotāja_id) {
// Asumējot, ka šis ir iestatīts iepriekš
/** @var \flight\database\PdoWrapper $db */
$db = Flight::db();
$atļautās_atļaujas = [ 'lasīt' ]; // ikviens var skatīties pasūtījumu
if($current_role === 'menedžeris') {
$atļautās_atļaujas[] = 'izveidot'; // vadītāji var izveidot pasūtījumus
}
$dažs īpašs_tētis_no_db = $db->fetchField('SELECT dažs_īpašs_tētis FROM iestatījumi WHERE id = ?', [ $lietotāja_id ]);
if($dažs_īpašs_tētis_no_db) {
$atļautās_atļaujas[] = 'labot'; // Ja lietotājam ir īpaša tētis, viņi var atjaunināt pasūtījumus
}
if($current_role === 'admins') {
$atļautās_atļaujas[] = 'dzēst'; // administratori var dzēst pasūtījumus
}
return $atļautās_atļaujas;
}
}
Cool daļa ir tāda, ka ir arī saīsinājums, ko varat izmantot (kas var būt arī kešēta!!!), kur vienkārši pateiksit atļauju klasei atkartot visus metodus klasē. Tāpēc, ja ir metode ar nosaukumu pasūtījums()
un metode ar nosaukumu uzņēmums()
, šīs automātiski tiks atkartotas, lai jūs varētu vienkārši izpildīt $Permissions->has('pasūtījums.lasīt')
vai $Permissions->has('uzņēmums.lasīt')
un tas strādās. To definēt ir ārkārtīgi grūti, tāpēc palieciet šeit kopā ar mani. Jums vienkārši jāizdara šādi:
Izveidojiet atļauju klases grupēšanai.
class ManasAtļaujas {
public function pasūtījums(string $current_role, int $pasūtījuma_id = 0): array {
// kods, lai noteiktu atļaujas
return $atļaujas_masīvs;
}
public function uzņēmums(string $current_role, int $uzņēmuma_id): array {
// kods, lai noteiktu atļaujas
return $atļaujas_masīvs;
}
}
Tad padarīt atļaujas atrodamas, izmantojot šo bibliotēku.
$Atļaujas = new \flight\Permission($current_role);
$Atļaujas->defineRulesFromClassMethods(ManasAtļaujas::class);
Flight::set('permissions', $Atļaujas);
Visbeidzot, zvaniet atļaujai savā kodā, lai pārbaudītu, vai lietotājam ir atļauts veikt noteiktu atļauju.
class DažsKontrolieris {
public function izveidotPasūtījumu() {
if(Flight::get('permissions')->can('pasūtījums.izveidot') === false) {
die('Jums nav atļauts izveidot pasūtījumu. Atvainojiet!');
}
}
}
Kešošana
Lai iespējotu kešošanu, skatiet vienkāršo wruczak/phpfilecache bibliotēku. Zemāk ir piemērs, kā iespējot to.
// šis $app var būt daļa no jūsu koda vai
// varat vienkārši padot null, un tas tiks iegūts
// no Flight::app() konstruktorā
$app = Flight::app();
// Pašlaik tas pieņem šo vienumu kā failu kešu. Citus var viegli
// pievienot nākotnē.
$Kešatmiņa = new Wruczek\PhpFailaKešatmiņa\PhpFailaKešatmiņa;
$Atļaujas = new \flight\Permission($current_role, $app, $Kešatmiņa);
$Atļaujas->defineRulesFromClassMethods(ManasAtļaujas::class, 3600); // 3600 ir cik daudz sekundes to kešot. Atstājiet to uz neatcelšanu
Un dodieties!
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/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-integration
mapi 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/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.db
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_close
sesijas 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_sessions
pē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$deleteOldFile
irtrue
, 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 noSessionHandlerInterface
un$id
ir 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_close
pē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
Lidmašīnas
Lidmašīnas ir CLI lietotne, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. Tā var ģenerēt kontrolierus, parādīt visus maršrutus un vairāk. Tā balstīta uz lielisko adhocore/php-cli bibliotēku.
Uzklikšķiniet šeit, lai skatītu kodu.
Instalēšana
Instalējiet to ar komponistu.
composer require flightphp/runway
Pamata konfigurācija
Pirmo reizi palaižot Lidmašīnas, tā vadīs jūs caur iestatīšanas procesu un izveidos .runway.json
konfigurācijas failu jūsu projekta saknē. Šajā failā būs dažas nepieciešamās konfigurācijas, lai Lidmašīnas pareizi darbotos.
Lietojums
Lidmašīnā ir vairākas komandas, ar kurām varat pārvaldīt savu Flight lietojumprogrammu. Ir divi viegli veidi, kā izmantot Lidmašīnas.
- Ja izmantojat ietvaru projektu, varat izpildīt
php runway [komanda]
no savu projekta saknes. - Ja izmantojat Lidmašīnas kā paketi, kas instalēts ar komponistu, varat izpildīt
vendor/bin/runway [komanda]
no savu projekta saknes.
Lai iegūtu papildinformāciju par jebkuru komandu, jūs varat padot --help
karodziņa.
php runway routes --help
Šeit ir daži piemēri:
Ģenerēt kontrolieri
Balstoties uz konfigurāciju jūsu .runway.json
failā, noklusējuma atrašanās vieta jums ģenerēs kontrolieri app/controllers/
direktorijā.
php runway make:controller MyController
Ģenerēt aktīvās ierakstu modeles
Balstoties uz konfigurāciju jūsu .runway.json
failā, noklusējuma atrašanās vieta jums ģenerēs kontrolieri app/records/
direktorijā.
php runway make:record users
Ja, piemēram, ir users
tabula ar sekojošu shēmu: id
, name
, email
, created_at
, updated_at
, fails līdzīgs sekojošajam tiks izveidots app/records/UserRecord.php
failā:
<?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 $name
* @property string $email
* @property string $created_at
* @property string $updated_at
* // šeit jūs varat pievienot attiecības, kad tās definētas $relations masīvā
* @property CompanyRecord $company Attēlots attiecību piemērs
*/
class UserRecord extends \flight\ActiveRecord
{
/**
* @var array $relations Uzstādiet attiecības modeļim
* https://docs.flightphp.com/awesome-plugins/active-record#relationships
*/
protected array $relations = [];
/**
* Konstruktors
* @param mixed $databaseConnection Datu bāzes savienojums
*/
public function __construct($databaseConnection)
{
parent::__construct($databaseConnection, 'users');
}
}
Parādīt visus maršrutus
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 konkrētus maršrutus, jūs varat padot karodziņu, lai filtrētu maršrutus.
# Parādīt tikai GET maršrutus
php runway routes --get
# Parādīt tikai POST maršrutus
php runway routes --post
# u.c.
Lidmašīnas pielāgošana
Ja jūs izveidojat paketi Flight, vai vēlaties pievienot savas pielāgotas komandas savā projektā, to varat izdarīt, izveidojot src/commands/
, flight/commands/
, app/commands/
vai commands/
direktoriju savam projektam/paketei.
Lai izveidotu komandu, jums vienkārši jāpaplašina AbstractBaseCommand
klase un jāimplementē vismaz __construct
metode un execute
metode.
<?php
declare(strict_types=1);
namespace flight\commands;
class ExampleCommand extends AbstractBaseCommand
{
/**
* Konstruktors
*
* @param array<string,mixed> $config JSON konfigurācija no .runway-config.json
*/
public function __construct(array $config)
{
parent::__construct('make:example', 'Izveidot piemēru dokumentācijai', $config);
$this->argument('<funny-gif>', 'Smaida GIF nosaukums');
}
/**
* Izpilda funkciju
*
* @return void
*/
public function execute(string $controller)
{
$io = $this->app()->io();
$io->info('Izveido piemēru...');
// Kaut ko dariet š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āgotas komandas savā Flight lietojumprogrammā!
Awesome-plugins/tracy_extensions
Tracy Flight Panel Extensions
Šis ir paplašinājumu kopums, lai darbs ar Flight būtu nedaudz bagātāks.
- Flight - Analizēt visas Flight mainīgās.
- Datubāze - Analizēt visus vaicājumus, kas ir palikuši izpildīti lapā (ja pareizi inicializējat datubāzes savienojumu).
- Pieprasījums - Analizēt visas
$_SERVER
mainīgās un izpētīt visus globālos slodzi ($_GET
,$_POST
,$_FILES
). - Sesija - Analizēt visas
$_SESSION
mainīgās, ja sesijas ir aktīvas.
Šis ir Panelis
Un katrs panelis parāda ļoti noderīgu informāciju par jūsu lietojumprogrammu!
Noklikšķiniet šeit, lai skatītu kodu.
Installation
Izpildiet composer require flightphp/tracy-extensions --dev
, un jūs esat ceļā!
Configuration
Ir ļoti maz konfigurācijas, kas jums jāveic, lai to sāktu. Jums būs jāinicializē Tracy atkļūdotājs pirms šī izmantošanas https://tracy.nette.org/en/guide:
<?php
use Tracy\Debugger;
use flight\debug\tracy\TracyExtensionLoader;
// bootstrap code
require __DIR__ . '/vendor/autoload.php';
Debugger::enable();
// Jums var būt jānorāda jūsu vide ar Debugger::enable(Debugger::DEVELOPMENT)
// ja jūs izmantojat datubāzes savienojumus savā lietojumprogrammā, ir nepieciešams PDO apvalks, ko izmantot TIKAI ATTĪSTĪBAS VIDĒ (nevis ražošanā, lūdzu!)
// Tam ir tie paši parametri kā regulāram PDO savienojumam
$pdo = new PdoQueryCapture('sqlite:test.db', 'user', 'pass');
// vai arī, ja jūs pievienojat to Flight framework
Flight::register('db', PdoQueryCapture::class, ['sqlite:test.db', 'user', 'pass']);
// tagad, kad vienreiz izpildīsiet vaicājumu, tas uztvers laiku, vaicājumu un parametrus
// Šis savieno punktus
if(Debugger::$showBar === true) {
// Šim jābūt false, vai Tracy nevarēs faktiski renderēt :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
// vairāk koda
Flight::start();
Additional Configuration
Session Data
Ja jums ir pielāgots sesijas apstrādātājs (piemēram, ghostff/session), jūs varat nodot jebkuru sesijas datu masīvu Tracy, un tas automātiski izvadīs to jums. Jūs to nododiet ar session_data
atslēgu otrajā parametru no TracyExtensionLoader
konstruktora.
use Ghostff\Session\Session;
// vai izmantojiet flight\Session;
require 'vendor/autoload.php';
$app = Flight::app();
$app->register('session', Session::class);
if(Debugger::$showBar === true) {
// Šim jābūt false, vai Tracy nevarēs faktiski renderēt :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
// maršruti un citas lietas...
Flight::start();
Latte
PHP 8.1+ ir nepieciešams šai sadaļai.
Ja jums ir Latte instalēts jūsu projektā, Tracy ir iebūvēta integrācija ar Latte, lai analizētu jūsu veidnes. Jūs vienkārši reģistrējat paplašinājumu ar jūsu Latte instanci.
require 'vendor/autoload.php';
$app = Flight::app();
$app->map('render', function($template, $data, $block = null) {
$latte = new Latte\Engine;
// citas konfigurācijas...
// pievienojiet paplašinājumu tikai tad, ja Tracy Debug Bar ir iespējots
if(Debugger::$showBar === true) {
// šeit jūs pievienojat Latte Paneli Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
}
$latte->render($template, $data, $block);
});
Awesome-plugins/apm
FlightPHP APM Dokumentācija
Laipni lūdzam FlightPHP APM — jūsu lietojumprogrammas personīgais veiktspējas treneris! Šis ceļvedis ir jūsu ceļakarte, lai iestatītu, izmantotu un apgūtu Lietojumprogrammas veiktspējas uzraudzību (APM) ar FlightPHP. Vai nu jūs meklējat lēnus pieprasījumus, vai vienkārši vēlaties iedziļināties latentuma diagrammās, mēs jums palīdzēsim. Padarīsim jūsu lietojumprogrammu ātrāku, jūsu lietotājus laimīgākus un jūsu atkļūdošanas sesijas vieglas!
Apskatiet demo Flight Docs vietnes panelim.
Kāpēc APM ir svarīga
Iedomājieties: jūsu lietojumprogramma ir aizņemta restorāns. Bez veida, kā izsekot, cik ilgi aizņem pasūtījumi vai kur virtuvē rodas aizkavēšanās, jūs minaties, kāpēc klienti aiziet neapmierināti. APM ir jūsu pavāra palīgs — tas uzrauga 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% aiziet, ja vietne ielādējas vairāk nekā 3 sekundes!), un APM palīdz jums noķert šīs problēmas pirms tās sadod. Tas ir proaktīvs mierinājums — mazāk “kāpēc tas ir salūzis?” brīžu, vairāk “paskatieties, cik gludi tas darbojas!” uzvaru.
Instalācija
Sāciet ar Composer:
composer require flightphp/apm
Jums būs nepieciešams:
- PHP 7.4+: Nodrošina saderību ar LTS Linux izplatījumiem, vienlaikus atbalstot modernu PHP.
- FlightPHP Core v3.15+: Vieglā ietvara, ko mēs uzlabojam.
Atbalstītās datubāzes
FlightPHP APM pašlaik atbalsta šādas datubāzes metriku uzglabāšanai:
- SQLite3: Vienkārša, failu balstīta, lieliska lokālai izstrādei vai mazām lietojumprogrammām. Noklusējuma opcija lielākajā daļā iestatījumu.
- MySQL/MariaDB: Ideāla lielākiem projektiem vai produkcijas vidēm, kur nepieciešama robusta, mērogojama uzglabāšana.
Jūs varat izvēlēties datubāzes tipu konfigurācijas solī (skatiet zemāk). Pārliecinieties, ka jūsu PHP videi ir instalētas nepieciešamās paplašinājumi (piem., pdo_sqlite
vai pdo_mysql
).
Sākšana
Šeit ir jūsu soli pa solim ceļš uz APM lieliskumu:
1. Reģistrējiet APM
Ievietojiet to savā index.php
vai services.php
failā, lai sāktu izsekošanu:
use flight\apm\logger\LoggerFactory;
use flight\Apm;
$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json');
$Apm = new Apm($ApmLogger);
$Apm->bindEventsToFlightInstance($app);
// Ja pievienojat datubāzes savienojumu
// Jābūt PdoWrapper vai PdoQueryCapture no Tracy Extensions
$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True nepieciešams, lai iespējotu izsekošanu 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 — pēc noklusējuma SQLite.Apm
ir zvaigzne — tas klausās Flight notikumus (pieprasījumus, maršrutus, kļūdas utt.) un savāc metrikas.bindEventsToFlightInstance($app)
saista visu ar jūsu Flight lietojumprogrammu.
Pro Padoms: Paraugšana Ja jūsu lietojumprogramma ir aizņemta, žurnālošana katra pieprasījuma var pārslodzes. Izmantojiet paraugu (0.0 līdz 1.0):
$Apm = new Apm($ApmLogger, 0.1); // Žurnālo 10% pieprasījumu
Tas saglabā veiktspēju ātru, vienlaikus dodot jums stingrus datus.
2. Konfigurējiet to
Palaidiet šo, lai izveidotu jūsu .runway-config.json
:
php vendor/bin/runway apm:init
Ko tas dara?
- Palaida vedni, kas jautā, no kurienes nāk neapstrādātās metrikas (avots) un kur iet apstrādātie dati (mērķis).
- Noklusējums ir SQLite — piem.,
sqlite:/tmp/apm_metrics.sqlite
avotam, cits mērķim. - Jūs iegūsiet konfigurāciju kā:
{ "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 vietas? Neapstrādātās metrikas uzkrājas ātri (domājiet nefiltrētus žurnālus). Darbinieks tās apstrādā strukturētā mērķī panelim. Saglabā visu kārtīgu!
3. Apstrādājiet metrikas ar darbinieku
Darbinieks pārvērš neapstrādātās metrikas datus, kas gatavi panelim. Palaidiet to vienreiz:
php vendor/bin/runway apm:worker
Ko tas dara?
- Lasīt no jūsu avota (piem.,
apm_metrics.sqlite
). - Apstrādā līdz 100 metriku (noklusējuma partijas lielums) jūsu mērķī.
- Apstājas, kad pabeigts vai ja nav metrikas.
Uzturiet to darbojošos Dzīvām lietojumprogrammām vēlaties nepārtrauktu apstrādi. Šeit ir jūsu opcijas:
-
Daemon režīms:
php vendor/bin/runway apm:worker --daemon
Darbojas mūžīgi, apstrādājot metrikas, kad tās nāk. Lieliski izstrādei vai maziem iestatījumiem.
-
Crontab: Pievienojiet to savam crontab (
crontab -e
):* * * * * php /path/to/project/vendor/bin/runway apm:worker
Palaid katru minūti — ideāli produkcijai.
-
Tmux/Screen: Sāciet atvienojamu sesiju:
tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon # Ctrl+B, tad D, lai atvienotu; `tmux attach -t apm-worker` lai savienotu atkārtoti
Uztur to darbojošos pat ja izreģistrējaties.
-
Pielāgoti uzstādījumi:
php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300
--batch_size 50
: Apstrādāt 50 metrikas uzreiz.--max_messages 1000
: Apstāties pēc 1000 metriku.--timeout 300
: Iziet pēc 5 minūtēm.
Kāpēc censties? Bez darbinieka jūsu panelis ir tukšs. Tas ir tilts starp neapstrādātiem žurnāliem un izmantojamiem ieskatiem.
4. Palaidiet paneli
Redziet jūsu lietojumprogrammas vitālos rādītājus:
php vendor/bin/runway apm:dashboard
Kas tas ir?
- Palaid PHP serveri pie
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īgs attālinātai skatīšanai).--port 8080
: Izmanto citu portu, ja 8001 ir aizņemts.--php-path
: Norāda uz PHP, ja tas nav jūsu PATH.
Atveriet URL savā pārlūkprogrammā un izpētiet!
Produkcijas režīms
Produkcijā jums var nākties izmēģināt dažas tehnikas, lai panelis darbotos, jo droši vien ir ugunsmūri un citas drošības pasākumi. Šeit ir dažas opcijas:
- Izmantojiet reverso proxy: Iestatiet Nginx vai Apache, lai pārsūtītu pieprasījumus panelim.
- SSH tunelis: Ja varat SSH uz serveri, izmantojiet
ssh -L 8080:localhost:8001 youruser@yourserver
, lai tunelētu paneli uz jūsu lokālo mašīnu. - VPN: Ja jūsu serveris ir aiz VPN, savienojieties ar to un piekļūstiet panelim tieši.
- Konfigurējiet ugunsmūri: Atveriet portu 8001 jūsu IP vai servera tīklam. (vai kādu portu jūs iestatījāt).
- Konfigurējiet Apache/Nginx: Ja jums ir tīmekļa serveris jūsu lietojumprogrammas priekšā, jūs varat to konfigurēt domēnam vai apakšdomēnam. Ja to darāt, iestatīsiet dokumentu sakni uz
/path/to/your/project/vendor/flightphp/apm/dashboard
Vai vēlaties citu paneli?
Jūs varat izveidot savu paneli, ja vēlaties! Apskatiet vendor/flightphp/apm/src/apm/presenter direktoriju idejām, kā prezentēt datus savam panelim!
Panaļa funkcijas
Panels ir jūsu APM galvenā mītne — šeit ir, ko redzēsiet:
- Pieprasījumu žurnāls: Katrs pieprasījums ar laika zīmi, URL, atbildes kodu un kopējo laiku. Noklikšķiniet “Detalizēti”, lai redzētu starprogrammatūru, vaicājumus un kļūdas.
- Lēnākie pieprasījumi: Top 5 pieprasījumi, kas aizņem laiku (piem., “/api/heavy” 2.5s).
- Lēnākie maršruti: Top 5 maršruti pēc vidējā laika — lieliski, lai pamanītu modeļus.
- Kļūdu līmenis: Procentos no pieprasījumiem, kas neizdodas (piem., 2.3% 500s).
- Latentuma percentīļi: 95. (p95) un 99. (p99) atbilžu laiki — ziniet savus sliktākos scenārijus.
- Atbildes koda diagramma: Vizualizējiet 200s, 404s, 500s laika gaitā.
- Gari vaicājumi/Starpprogrammatūra: Top 5 lēni datubāzes zvani un starprogrammatūras slāņi.
- Kešs trāpījums/Praids: Cik bieži jūsu kešs glābj dienu.
Ekstras:
- Filtrēt pēc “Pēdējā stunda,” “Pēdējā diena,” vai “Pēdējā nedēļa.”
- Pārslēdziet tumšo režīmu tiem vēlošajiem seansiem.
Piemērs:
Pieprasījums uz /users
var rādīt:
- Kopējais laiks: 150ms
- Starpprogrammatūra:
AuthMiddleware->handle
(50ms) - Vaicājums:
SELECT * FROM users
(80ms) - Kešs: Trāpījums uz
user_list
(5ms)
Pievienošana pielāgotu notikumu
Izsekot jebko — piemēram, API zvanu vai maksājumu 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? Panelī pieprasījuma detaļās zem “Pielāgoti notikumi” — paplašināms 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 tas API velk jūsu lietojumprogrammu lejup!
Datubāzes uzraudzība
Izsekot PDO vaicājumus šādi:
use flight\database\PdoWrapper;
$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True nepieciešams, lai iespējotu izsekošanu APM.
$Apm->addPdoConnection($pdo);
Ko jūs iegūstat:
- Vaicājuma tekstu (piem.,
SELECT * FROM users WHERE id = ?
) - Izpildes laiku (piem., 0.015s)
- Rindu skaitu (piem., 42)
Brīdinājums:
- Opsionāli: Izlaidiet to, ja nevajag DB izsekošanu.
- Tikai PdoWrapper: Kodols PDO vēl nav savienots — sekojiet līdzi!
- Veiktspējas brīdinājums: Žurnālošana katra vaicājuma uz DB smagas vietnes var palēnināt. Izmantojiet paraugu (
$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
Darbinieka opcijas
Pielāgojiet darbinieku savai gaumei:
--timeout 300
: Apstājas pēc 5 minūtēm — labi testēšanai.--max_messages 500
: Ierobežo līdz 500 metriku — saglabā to ierobežotu.--batch_size 200
: Apstrādā 200 uzreiz — līdzsvaro ātrumu un atmiņu.--daemon
: Darbojas bez apstājas — ideāli dzīvai uzraudzībai.
Piemērs:
php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600
Darbojas stundu, apstrādājot 100 metrikas uzreiz.
Pieprasījuma ID lietojumprogrammā
Katram pieprasījumam ir unikāls pieprasījuma ID izsekošanai. Jūs varat izmantot šo ID savā lietojumprogrammā, lai korelētu žurnālus un metrikas. Piemēram, jūs varat pievienot pieprasījuma ID kļūdu lapai:
Flight::map('error', function($message) {
// Iegūt pieprasījuma ID no atbildes galvenes X-Flight-Request-Id
$requestId = Flight::response()->getHeader('X-Flight-Request-Id');
// Papildus jūs varētu to iegūt no Flight mainīgā
// Šī metode labi nedarbosies swoole vai citās async platformās.
// $requestId = Flight::get('apm.request_id');
echo "Kļūda: $message (Pieprasījuma ID: $requestId)";
});
Atjaunināšana
Ja atjaunināt uz jaunāku APM versiju, ir iespēja, ka ir datubāzes migrācijas, kas jāpalaid. Jūs varat to izdarīt, palaižot šādu komandu:
php vendor/bin/runway apm:migrate
Tas palaidīs visas nepieciešamās migrācijas, lai atjauninātu datubāzes shēmu uz jaunāko versiju.
Piezīme: Ja jūsu APM datubāze ir liela izmērā, šīs migrācijas var prasīt laiku. Jūs varat vēlēties palaidīt šo komandu ārpus maksimālās slodzes stundām.
Veco datu dzēšana
Lai saglabātu jūsu datubāzi kārtīgu, jūs varat dzēst vecus datus. Tas ir īpaši noderīgi, ja darbojaties aizņemtu lietojumprogrammu un vēlaties uzturēt datubāzes izmēru vadāmu. Jūs varat to izdarīt, palaižot šādu komandu:
php vendor/bin/runway apm:purge
Tas noņems visus datus vecākus 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 vecākus par 7 dienām no datubāzes.
Problēmu risināšana
Iestrēdzis? Mēģiniet šos:
-
Nav paneļa datu?
- Vai darbinieks darbojas? Pārbaudiet
ps aux | grep apm:worker
. - Konfigurācijas ceļi sakrīt? Pārbaudiet
.runway-config.json
DSN norāda uz reāliem failiem. - Palaidiet
php vendor/bin/runway apm:worker
manuāli, lai apstrādātu gaidošās metrikas.
- Vai darbinieks darbojas? Pārbaudiet
-
Darbinieka kļūdas?
- Apskatiet jūsu SQLite failus (piem.,
sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"
). - Pārbaudiet PHP žurnālus uz steka pēdzīmēm.
- Apskatiet jūsu SQLite failus (piem.,
-
Panels nesākas?
- Ports 8001 aizņemts? Izmantojiet
--port 8080
. - PHP nav atrasts? Izmantojiet
--php-path /usr/bin/php
. - Ugunsmūris bloķē? Atveriet portu vai izmantojiet
--host localhost
.
- Ports 8001 aizņemts? Izmantojiet
-
Pārāk lēns?
- Samaziniet parauga līmeni:
$Apm = new Apm($ApmLogger, 0.05)
(5%). - Samaziniet partijas lielumu:
--batch_size 20
.
- Samaziniet parauga līmeni:
-
Netiek izsekotas izņēmumi/Kļūdas?
- Ja jums ir Tracy iespējots projektam, tas pārņems Flight kļūdu apstrādi. Jums jāatspējo Tracy un tad jāpārliecinās, ka
Flight::set('flight.handle_errors', true);
ir iestatīts.
- Ja jums ir Tracy iespējots projektam, tas pārņems Flight kļūdu apstrādi. Jums jāatspējo Tracy un tad jāpārliecinās, ka
-
Netiek izsekoti datubāzes vaicājumi?
- Pārliecinieties, ka izmantojat
PdoWrapper
savām datubāzes savienojumiem. - Pārliecinieties, ka konstruktorā pēdējais arguments ir
true
.
- Pārliecinieties, ka izmantojat
Awesome-plugins/tracy
Tracy
Tracy ir fantastisks kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairākas panelis, kas var palīdzēt jums atkļūdot jūsu lietojumprogrammu. Ir ļoti viegli paplašināt un pievienot savus paneļus. Flight komanda ir izveidojusi dažus paneļus speciāli Flight projektam, izmantojot flightphp/tracy-extensions spraudni.
Instalācija
Instalējiet ar komponistu. Un jums faktiski vajadzēs instalēt to bez izstrādes versijas, jo Tracy tiek piegādāts ar ražošanas kļūdu apstrādes komponentu.
composer require tracy/tracy
Pamata konfigurācija
Ir dažas pamata konfigurācijas opcijas, lai sāktu. Par tām varat lasīt vairāk Tracy dokumentācijā.
require 'vendor/autoload.php';
use Tracy\Debugger;
// Iespējot Tracy
Debugger::enable();
// Debugger::enable(Debugger::DEVELOPMENT) // dažreiz ir jābūt skaidrai (arī Debugger::PRODUCTION)
// Debugger::enable('23.75.345.200'); // varat norādīt arī IP adreses masīvu
// Šeit tiks reģistrēti kļūdas un izņēmumi. Pārliecinieties, ka šis katalogs pastāv 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 Tracy josla ir redzama, tad Flight nevar iestatīt satura garumu
// Tas ir specifisks Tracy paplašinājumam Flight, ja jūs to esat iekļāvuši
// pretējā gadījumā komentējiet to.
new TracyExtensionLoader($app);
}
Noderīgi padomi
Kad jūs atkļūvojat savu kodu, ir dažas ļoti noderīgas funkcijas, lai izvadītu datus jums.
bdump($var)
- Tas izmetīs mainīgo uz Tracy joslas atsevišķajā panelī.dumpe($var)
- Tas izmetīs mainīgo un tad nekavējoties nomirs.
Awesome-plugins/active_record
Flight Aktīvais Ieraksts
Aktīvais ieraksts ir datubāzes entitātes kartēšana uz PHP objektu. Sakot vienkārši, ja jums ir lietotāju tabula jūsu datubāzē, jūs varat "tulkot" rindu šajā tabulā uz User
klasi un $user
objektu jūsu kodā. Skatiet pamatu piemēru.
Noklikšķiniet šeit uz noliktavas GitHub.
Pamatu Piemērs
Pieņemam, 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:
/**
* Aktīvā ieraksta klase parasti ir vienskaitļa formā
*
* 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 to varat iestatīt šādā veidā
parent::__construct($database_connection, 'users');
// vai šādā veidā
parent::__construct($database_connection, null, [ 'table' => 'users']);
}
}
Tagad skatiet, kā notiek burvība!
// sqlite gadījumā
$database_connection = new PDO('sqlite:test.db'); // tas ir tikai piemēram, jūs, iespējams, izmantotu reālu 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 bez objektu balstīta izveidošana
$database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db');
$user = new User($database_connection);
$user->name = 'Bobby Tables';
$user->password = password_hash('kāds foršs parole');
$user->insert();
// vai $user->save();
echo $user->id; // 1
$user->name = 'Joseph Mamma';
$user->password = password_hash('kāds foršs parole atkal!!!');
$user->insert();
// šeit nevar izmantot $user->save(), jo tas domās, ka tas ir atjauninājums!
echo $user->id; // 2
Un bija tik viegli pievienot jaunu lietotāju! Tagad, kad datubāzē ir lietotāja rinda, kā to izvilkt?
$user->find(1); // atrast id = 1 datubāzē un atgriezt to.
echo $user->name; // 'Bobby Tables'
Un kas notiks, ja vēlaties atrast visus lietotājus?
$users = $user->findAll();
Ko teikt par noteiktu nosacījumu?
$users = $user->like('name', '%mamma%')->findAll();
Redzat, cik tas ir aizraujoši? Instalēsim to un sāksim!
Instalācija
Vienkārši instalējiet ar Composer
composer require flightphp/active-record
Izmantošana
To var izmantot kā patstāvīgu bibliotēku vai kopā ar Flight PHP rāmci. Pilnīgi atkarīgs no jums.
Patstāvīgi
Vienkārši pārliecinieties, ka nododat PDO savienojumu konstruktoram.
$pdo_connection = new PDO('sqlite:test.db'); // tas ir tikai piemēram, jūs, iespējams, izmantotu reālu datubāzes savienojumu
$User = new User($pdo_connection);
Negribiet katru reizi iestatīt savu datubāzes savienojumu konstruktorā? Skatiet Datubāzes Savienojuma Pārvaldība citām idejām!
Reģistrēt kā metodi Flight
Ja jūs izmantojat Flight PHP rāmi, varat reģistrēt aktīvā ieraksta klasi kā pakalpojumu, bet jums to patiesībā nav jāizdara.
Flight::register('user', 'User', [ $pdo_connection ]);
// tad jūs varat to izmantot šādi kontrolierī, funkcijā utt.
Flight::user()->find(1);
runway
Metodes
runway ir CLI rīks Flight, kas ir izstrādāts ar īpašu komandu šai bibliotēkai.
# Izmantošana
php runway make:record database_table_name [class_name]
# Piemērs
php runway make:record users
Tas izveidos jaunu klasi mapē app/records/
kā UserRecord.php
ar sekojošo saturu:
<?php
declare(strict_types=1);
namespace app\records;
/**
* Aktīvā ieraksta 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 attiecības modelim
* https://docs.flightphp.com/awesome-plugins/active-record#relationships
*/
protected array $relations = [
// 'relation_name' => [ self::HAS_MANY, 'RelatedClass', 'foreign_key' ],
];
/**
* Konstruktor
* @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 jūs nododat $id
kādu vērtību, tas veiks meklēšanu pēc primārā atslēga ar šo vērtību. Ja nekas netiek nodots, tas vienkārši atradīs pirmo ierakstu tabulā.
Turklāt jūs varat nodot tam citas palīgmetodes, lai vaicātu jūsu tabulu.
// atrast ierakstu ar dažiem nosacījumiem iepriekš
$user->notNull('password')->orderBy('id DESC')->find();
// atrast ierakstu pēc noteikta id
$id = 123;
$user->find($id);
findAll(): array<int,ActiveRecord>
Atrast visus ierakstus tabulā, kuru jūs norādāt.
$user->findAll();
isHydrated(): boolean
(v0.4.0)
Atgriež true
, ja pašreizējais ieraksts ir bijis hidrogenizēts (iegūts no datubāzes).
$user->find(1);
// ja ir atrasts ieraksts 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 balstītas primārās atslēgas
Ja jums ir teksta balstīta primārā atslēga (piemēram, UUID), jūs varat iestatīt primārās atslēgas vērtību pirms ievietošanas vienā no diviem veidiem.
$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 tikt ģenerētai jūsu vietā.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]);
// jūs varat arī iestatīt primāro atslēgu šādā veidā, nevis augstāk norādītajā masīvā.
$this->primaryKey = 'uuid';
}
protected function beforeInsert(self $self) {
$self->uuid = uniqid(); // vai kā citādi nepieciešams ģenerēt jūsu unikālos 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, taču tā neuzturēsies, jo šis lauks var nepastāvēt jūsu tabulā. Tāpēc ieteicams izmantot notikumu, lai automātiski to apstrādātu.
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 tas ievietos.
$user = new User($pdo_connection);
$user->name = 'demo';
$user->password = md5('demo');
$user->save();
Piezīme: Ja jums ir attiecības, kas definētas klasē, tās tiek rekurzīvi saglabātas, ja tās ir bijušas definētas, instancētas un ir netīri dati, ko atjaunināt. (v0.4.0 un augstāks)
delete(): boolean
Dzēš pašreizējo ierakstu no datubāzes.
$user->gt('id', 0)->orderBy('id desc')->find();
$user->delete();
Jūs arī varat dzēst vairākus ierakstus, veicot 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();
// šajā brīdī nav "netīru" datu.
$user->email = 'test@example.com'; // tagad e-pasts tiek uzskatīts par "netīru", jo tas ir mainījies.
$user->update();
// tagad nav nevienu datu, kas ir netīri, jo tie ir atjaunināti un uzglabāti datubāzē
$user->password = password_hash('jaunā parole'); // tagad šis ir netīrs
$user->dirty(); // neko nenododot, tiks notīrīti visi netīrie ieraksti.
$user->update(); // nekas netiks atjaunināts, jo nekas netika sagūstīts kā netīrs.
$user->dirty([ 'name' => 'kaut kas', 'password' => password_hash('cita parole') ]);
$user->update(); // gan vārds, gan parole tiek atjaunināti.
copyFrom(array $data): ActiveRecord
(v0.4.0)
Tas ir alias dirty()
metodei. Tas ir nedaudz vairāk skaidrāks par to, ko jūs darāt.
$user->copyFrom([ 'name' => 'kaut kas', 'password' => password_hash('cita parole') ]);
$user->update(); // abi vārds un parole tiek 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
Atjauno pašreizējo ierakstu tā sākotnējā stāvoklī. Tas ir ļoti labi izmantot ciklu tipa uzvedībā.
Ja nododat true
, tas arī atiestatīs vaicājuma datus, kas tika izmantoti, lai atrastu pašreizējo objektu (pamatuzvedība).
$users = $user->greaterThan('id', 0)->orderBy('id desc')->find();
$user_company = new UserCompany($pdo_connection);
foreach($users as $user) {
$user_company->reset(); // sāk 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 esat izpildījis find()
, findAll()
, insert()
, update()
, vai save()
metodi, jūs varat iegūt SQL, kas tika izveidots un izmantot to problēmu risināšanai.
SQL Vaicājumu Metodes
select(string $field1 [, string $field2 ... ])
Jūs varat atlasīt tikai dažus no kolonnām tabulā, ja vēlaties (tas ir efektīvāk tiešām plašām tabulām ar daudzām kolonnām)
$user->select('id', 'name')->find();
from(string $table)
Tehniski jūs 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 pievienot citu tabulu 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 - Iespējams, ka jūs sadarbojas ar kaut ko līdzīgu $user->where("id = '{$id}' AND name = '{$name}'")->find();
. Lūdzu, NEDARĪT TO!!! Tas var būt pakļauts tam, ko sauc par SQL injekcijas uzbrukumiem. Ir daudz rakstu tiešsaistē, lūdzu, Google "sql injekcijas uzbrukumi php" un jūs atradīsiet daudz rakstu par šo tēmu. Pareizā metode, kā to apstrādāt ar šo bibliotēku, ir tā, ka, nevis šo where()
metodi, jūs to darītu vairāk līdzīgi $user->eq('id', $id)->eq('name', $name)->find();
. Ja jums ir absolūti jādara tā, PDO
bibliotēkai ir $pdo->quote($var)
, lai to izdzēstu priekš jums. Tikai pēc tam, kad esat izmantojuši quote()
, varat to izmantot where()
paziņojumā.
group(string $group_by_statement)/groupBy(string $group_by_statement)
Grupējiet savus 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žojiet atgriezto ierakstu skaitu. Ja tiek norādīta otrā int, tā būs offset, limits tieši tāpat 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 savus nosacījumus ietīt OR paziņojumā. To var izdarīt, izmantojot startWrap()
un endWrap()
metodi vai norādīt 3. parametru nosacījumam 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 novērtēs `id = 1 AND (name = 'demo' OR name = 'test')`
// Metode 2
$user->eq('id', 1)->eq('name', 'demo', 'OR')->find();
// Tas novērtēs `id = 1 OR name = 'demo'`
Attiecības
Jūs varat iestatīt vairākus veidus attiecības, izmantojot šo bibliotēku. Jūs varat iestatīt vienu->daudz un vienu->vienu attiecības starp tabulām. Tas prasa mazliet papildus sagatavošanu klasē iepriekš.
Iestatīt $relations
masīvu nav grūti, bet pareizā sintakse var būt mulsinoša.
protected array $relations = [
// jūs varat nosaukt atslēgu kā vēlaties. Aktīvā ieraksta nosaukums, iespējams, ir labs. Piemērs: lietotājs, kontakts, klients
'user' => [
// obligāti
// self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO
self::HAS_ONE, // šis ir attiecību veids
// obligāti
'Some_Class', // šī ir 'otra' Aktīvā ieraksta klase, uz kuru atsaucas
// obligāti
// atkarībā no attiecību veida
// self::HAS_ONE = ārējā atslēga, kas atsaucas uz pievienošanu
// self::HAS_MANY = ārējā atslēga, kas atsaucas uz pievienošanu
// self::BELONGS_TO = lokālā atslēga, kas atsaucas uz pievienošanu
'local_or_foreign_key',
// tikai FYI, tas arī pievienojas tikai uz "otras" modeļa primāro atslēgu
// izvēles
[ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // papildu nosacījumi, kurus vēlaties, pievienojot attiecību
// $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5))
// izvēles
'back_reference_name' // ja vēlaties atsaukt šo attiecību atpakaļ uz sevi, piemēram, `$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 tās izmantot ļ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 doties otrā virzienā.
$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
Ļoti jauki, vai ne?
Iestatīt Pielāgotus Datus
Reizēm jums var būt nepieciešams pievienot kaut ko unikālu savam Aktīvam Ierakstam, piemēram, pielāgotu aprēķinu, kas varētu būt vieglāk pievienot objektam, kas pēc tam būtu nodots, piemēram, š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
Vēl viena super jauka funkcija šajā bibliotēkā ir notikumi. Notikumi tiek aktivizēti noteiktos brīžos, pamatojoties uz noteiktām metodēm, ko jūs izsaucat. Tie ir ļoti noderīgi, lai automātiski izveidotu datus jums.
onConstruct(ActiveRecord $ActiveRecord, array &config)
Tas ir ļoti noderīgi, ja nepieciešams iestatīt noklusējuma savienojumu vai kaut ko tamlīdzīgu.
// 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 par & atsauci
// jūs varētu to izdarīt, lai automātiski iestatītu savienojumu
$config['connection'] = Flight::db();
// vai arī šo
$self->transformAndPersistConnection(Flight::db());
// jūs varat arī šādi iestatīt tabulas nosaukumu.
$config['table'] = 'users';
}
}
beforeFind(ActiveRecord $ActiveRecord)
Šis visticamāk ir noderīgs, ja jums nepieciešams 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 palaist id >= 0, ja tā jums patīk
$self->gte('id', 0);
}
}
afterFind(ActiveRecord $ActiveRecord)
Šis visticamāk ir noderīgāks, ja jums katru reizi ir jāpalaista kāda loģika, kad šis ieraksts tiek iegūts. Vai jums jādešifrē kaut kas? Vai jums katru reizi jāveic pielāgots skaitīšanas vaicājums (neefektīvs, bet, nu...).
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterFind(self $self) {
// kaut ko dešifrējot
$self->secret = yourDecryptFunction($self->secret, $some_key);
// varbūt glabājot kaut ko pielāgotu, piemēram, vaicājumu???
$self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count'];
}
}
beforeFindAll(ActiveRecord $ActiveRecord)
Šis varētu būt tikai noderīgs, ja jums 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 palaist id >= 0, ja tā jums patīk
$self->gte('id', 0);
}
}
afterFindAll(array<int,ActiveRecord> $results)
Līdzīgi afterFind()
, bet jūs varat to izdarī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) {
// darīt kaut ko foršu līdzīgi kā afterFind()
}
}
}
beforeInsert(ActiveRecord $ActiveRecord)
Ļoti noderīgi, ja 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 lietotāja scenārijs, lai mainītu 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) {
// jūs darāt sevi
Flight::cache()->set('most_recent_insert_id', $self->id);
// vai jebkas cits...
}
}
beforeUpdate(ActiveRecord $ActiveRecord)
Ļoti noderīgi, ja jums vajag dažas noklusējuma vērtības katru reizi atjaunināšanai.
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 lietotāja gadījums, lai mainītu 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) {
// jūs darāt sevi
Flight::cache()->set('most_recently_updated_user_id', $self->id);
// vai jebkas cits....
}
}
beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)
Tas ir noderīgi, ja vēlaties, lai notikumi notiktu gan ievietošanas, gan atjaunināšanas laikā. Es ietaupīšu jums garu skaidrojumu, 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)
Nezinu, ko jūs šeit vēlētos darīt, bet šeit nav spriedumu! Iet uz priekšu!
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
Kad jūs izmantojat šo bibliotēku, jūs varat iestatīt datubāzes savienojumu dažādos veidos. Jūs varat iestatīt savienojumu konstruktorā, jūs varat iestatīt to caur konfigurācijas mainīgo $config['connection']
vai jūs 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 katra reizes $database_connection
iestatīšanas, ir veidi, kā to izdarīt!
// index.php vai bootstrap.php
// Iestatiet šo 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 vienību testēšanu, to izdarot, var rasties grūtības, bet kopumā, jo jūs varat injicēt savu savienojumu ar
setDatabaseConnection()
vai$config['connection']
, tas nav pārāk slikti.
Ja jums nepieciešams atsvaidzināt datubāzes savienojumu, piemēram, ja jūs veicat garu CLI skriptu un periodiski nepieciešams atsvaidzināt savienojumu, jūs varat atkārtoti iestatīt savienojumu ar $your_record->setDatabaseConnection($pdo_connection)
.
Ieteikums
Lūdzu, dariet to. :D
Iestatīšana
Kad jūs piedalāties, pārliecinieties, ka izpildāt composer test-coverage
, lai uzturētu 100% testēšanas pārklājumu (šis nav patiesais vienību testēšanas pārklājums, drīzāk integrācijas testēšana).
Tāpat pārliecinieties, ka izpildāt composer beautify
un composer phpcs
, lai novērstu 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
Lieliski spraudņi
Flight ir neticami paplašināms. Ir vairāki spraudņi, ko var izmantot, lai pievienotu funkcionalitāti jūsu Flight aplikācijai. Daži no tiem oficiāli atbalsta Flight komanda, bet citi ir mikro/lite bibliotēkas, lai palīdzētu jums sākt.
API dokumentācija
API dokumentācija ir izšķiroša jebkurai API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem.
- FlightPHP OpenAPI Generator - Bloga ieraksts, ko uzrakstījis Daniels Šreibers, par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu jūsu API, izmantojot API pirmo pieeju.
- SwaggerUI - Swagger UI ir lielisks rīks, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. To ir ļoti viegli izmantot un to var pielāgot jūsu vajadzībām. Šī ir PHP bibliotēka, lai palīdzētu ģenerēt Swagger dokumentāciju.
Aplikācijas veiktspējas uzraudzība (APM)
Aplikācijas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai aplikācijai. Tā palīdz saprast, kā jūsu aplikācija darbojas un kur ir pudeles kakli. Ir vairāki APM rīki, ko var izmantot ar Flight.
- oficiāls flightphp/apm - Flight APM ir vienkārša APM bibliotēka, ko var izmantot, lai uzraudzītu jūsu Flight aplikācijas. To var izmantot, lai uzraudzītu jūsu aplikācijas veiktspēju un palīdzētu identificēt pudeles kaklus.
Async
Flight jau ir ātrs ietvars, bet pievienojot tam turbo dzinēju, viss kļūst jautrāks (un izaicinošāks)!
- flightphp/async - Oficiālā Flight Async bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot asinhrono apstrādi jūsu aplikācijai. Tā izmanto Swoole/Openswoole zem kapota, lai nodrošinātu vienkāršu un efektīvu veidu, kā palaist uzdevumus asinhroni.
Autorizācija/Atļaujas
Autorizācija un atļaujas ir izšķirošas jebkurai aplikācijai, kas prasa kontroli par to, kam ir piekļuve kam.
- oficiāls flightphp/permissions - Oficiālā Flight Permissions bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot lietotāja un aplikācijas līmeņa atļaujas jūsu aplikācijai.
Kešošana
Kešošana ir lielisks veids, kā paātrināt jūsu aplikāciju. Ir vairāki kešošanas bibliotēkas, ko var izmantot ar Flight.
- oficiāls flightphp/cache - Gaisīga, vienkārša un neatkarīga PHP failā kešošanas klase
CLI
CLI aplikācijas ir lielisks veids, kā mijiedarboties ar jūsu aplikāciju. Jūs varat izmantot tās, lai ģenerētu kontrolierus, parādītu visas maršrutus un vairāk.
- oficiāls flightphp/runway - Runway ir CLI aplikācija, kas palīdz jums pārvaldīt jūsu Flight aplikācijas.
Sīkfaili
Sīkfaili ir lielisks veids, kā uzglabāt mazus datu gabalus klientu pusē. Tos var izmantot, lai uzglabātu lietotāja preferences, aplikācijas 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īkfailus.
Kļūdu labošana
Kļūdu labošana ir izšķiroša, kad jūs attīstāt savā lokālajā vidē. Ir daži spraudņi, kas var uzlabot jūsu kļūdu laboš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 var palīdzēt jums labot kļūdas jūsu aplikācijā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus.
- oficiāls flightphp/tracy-extensions - Izmantojot ar Tracy kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu labošanu specifiski Flight projektiem.
Datubāzes
Datubāzes ir kodols lielākajai daļai aplikāciju. Tā ir veids, kā uzglabāt un izgūt datus. Dažas datubāzu bibliotēkas ir vienkārši apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM.
- oficiāls flightphp/core PdoWrapper - Oficiālais Flight PDO apvalks, kas ir daļa no kodola. Šis ir vienkāršs apvalks, lai palīdzētu vienkāršot vaicājumu rakstīšanas un izpildes procesu. Tas nav ORM.
- oficiāls flightphp/active-record - Oficiālā Flight ActiveRecord ORM/Mapper. Lieliska maza bibliotēka, lai viegli izgūtu un uzglabātu datus jūsu datubāzē.
- byjg/php-migration - Spraudnis, lai sekotu visām datubāzes izmaiņām jūsu projektā.
Šifrēšana
Šifrēšana ir izšķiroša jebkurai aplikācijai, kas uzglabā sensitīvus datus. Datu šifrēšana un dešifrēšana nav pārāk grūti, bet pareiza šifrēšanas atslēgas uzglabāšana var būt grūti. Visnozīmīgākais ir nekad neuzglabāt jūsu šifrēšanas atslēgu publiskā direktorijā vai neiekļaut to jūsu koda repozitorijā.
- defuse/php-encryption - Šī ir bibliotēka, ko var izmantot, lai šifrētu un dešifrētu datus. Sākšana un palaišana ir diezgan vienkārša, lai sāktu šifrēt un dešifrēt datus.
Darbu rinda
Darbu rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas var būt e-pastu sūtīšana, attēlu apstrāde vai jebkas, kam nav jābūt reāllaika.
- n0nag0n/simple-job-queue - Simple Job Queue ir bibliotēka, ko var izmantot, lai apstrādātu darbus asinhroni. To var izmantot ar beanstalkd, MySQL/MariaDB, SQLite un PostgreSQL.
Sesijas
Sesijas nav īsti noderīgas API, bet veidojot tīmekļa aplikāciju, sesijas var būt izšķirošas, lai uzturētu stāvokli un pieteikšanās informāciju.
- oficiāls flightphp/session - Oficiālā Flight Session bibliotēka. Šī ir vienkārša sesijas bibliotēka, ko var izmantot, lai uzglabātu un izgūtu sesijas datus. Tā izmanto PHP iebūvēto sesijas apstrādi.
- Ghostff/Session - PHP Session pārvaldnieks (nebloķējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl opcionālai sesijas datu šifrēšanai/dešifrēšanai.
Veidnes
Veidnes ir kodols jebkurai tīmekļa aplikācijai ar UI. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight.
- novecojis flightphp/core View - Šis ir ļoti pamata veidņu dzinējs, kas ir daļa no kodola. Nav ieteicams izmantot, ja jūsu 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ūtas tuvāk PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas.
WordPress integrācija
Vai vēlaties izmantot Flight jūsu WordPress projektā? Ir ērts spraudnis tam!
- n0nag0n/wordpress-integration-for-flight-framework - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāls, lai pievienotu pielāgotas API, mikroservisus vai pat pilnas aplikācijas jūsu WordPress vietnē, izmantojot Flight ietvaru. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm!
Iesaiste
Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet pull request, lai pievienotu to 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 jaunu Flight projektu:
- Pilna skeletu sagatave: Pilnīgāks piemērs ar kontrolieriem un skatiem.
- Vienkārša faila skeletu sagatave: Viens fails, kas ietver visu nepieciešamo, lai palaistu jūsu lietotni vienā vienkāršā failā.
Kopienas sniegti 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 aizmuguri.
Vai vajag iedvesmu?
Lai gan šie nav oficiāli atbalstīti no Flight komandas puses, tie var sniegt idejas, kā strukturēt savus paša projektus, kas izveidoti ar Flight!
- Ivox Car Rental - Ivox Car Rental ir vienlapa, mobilajām ierīcēm draudzīga auto nomas tīmekļa lietotne, kas 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. Lietotnē ir REST API, JWT autentifikācija un responsīvs dizains modernai nomas pieredzei.
- Decay - Flight v3 ar HTMX un SleekDB, viss par zombijiem! (Demo)
- Flight Example Blog - Flight v3 ar starprogrammatūru, 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 izveidotu PHP lietotni 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 School Management System - Flight v3
- Paste Bin with Comments - Flight v3
- Basic Skeleton App
- Example Wiki
- The IT-Innovator PHP Framework Application
- LittleEducationalCMS (Spanish)
- Italian Yellow Pages API
- Generic Content Management System (with....very little documentation)
- A tiny php framework based on Flight and medoo.
- Example MVC Application
- Production ready Flight Boilerplate - Ražošanai gatavs autentifikācijas ietvars, kas ietaupa nedēļām ilgu izstrādi. Funkcijas ietver uzņēmuma līmeņa drošību: 2FA/TOTP, LDAP integrācija, Azure SSO, inteliģenta ātruma ierobežošana, sesijas pirkstu nospieduma atpazīšana, aizsardzība pret brutālu spēku, drošības analītikas panelis, visaptveroša audita žurnālošana un granulāra lomām balstīta piekļuves kontrole.
Vai vēlaties dalīties ar savu paša 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
Ir daži pamatpriekšnoteikumi, pirms varat instalēt Flight. Galvenokārt jums būs jā:
- Instalē PHP sistēmā
- Instalē Composer labākai izstrādātāju pieredzei.
Pamatinstalēšana
Ja izmantojat Composer, varat izpildīt šādu komandu:
composer require flightphp/core
Tas tikai ievietos Flight kodola failus jūsu sistēmā. Jums būs jādefinē projekta struktūra, izkārtojums, atkarības, konfigurācijas, automātiskā ielāde utt. Šī metode nodrošina, ka nav instalētas citas atkarības, izņemot Flight.
Varat arī lejupielādēt failus tieši un izvilkt tos savā tīmekļa direktorijā.
Ieteicamā instalēšana
Ir augsti ieteicams sākt ar flightphp/skeleton lietotni jebkuram jaunam projektam. Instalēšana ir viegla.
composer create-project flightphp/skeleton my-project/
Tas iestatīs jūsu projekta struktūru, konfigurēs automātisko ielādi ar vārdtelpām, iestatīs konfigurāciju un nodrošinās citas rīkus, piemēram, Tracy, Tracy Extensions un Runway.
Konfigurējiet savu tīmekļa serveri
Iebūvētais PHP izstrādes serveris
Šī ir vienkāršākā metode, lai sāktu darbu. Varat izmantot iebūvēto serveri, lai palaistu savu lietotni un pat izmantot SQLite datubāzei (tik ilgi, kamēr sqlite3 ir instalēts jūsu sistēmā), un neprasīt gandrīz neko! Vienreiz instalējot PHP, vienkārši izpildiet šādu komandu:
php -S localhost:8000
# vai ar skeleton lietotni
composer start
Pēc tam atveriet pārlūku un dodieties uz http://localhost:8000
.
Ja vēlaties padarīt sava projekta dokumenta saknes direktoriju citu direktoriju (Piem.: jūsu projekts ir ~/myproject
, bet jūsu dokumenta sakne ir ~/myproject/public/
), varat izpildīt šādu komandu, atrodoties ~/myproject
direktorijā:
php -S localhost:8000 -t public/
# ar skeleton lietotni tas jau ir konfigurēts
composer start
Pēc tam atveriet pārlūku un dodieties uz http://localhost:8000
.
Apache
Pārliecinieties, ka Apache jau ir instalēts jūsu sistēmā. Ja nē, meklējiet Google, kā instalēt Apache jūsu sistēmā.
Apache gadījumā rediģējiet savu .htaccess
failu ar šādu:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
Piezīme: Ja nepieciešams izmantot flight apakšdirektorijā, pievienojiet rindu
RewriteBase /subdir/
tieši pēcRewriteEngine On
.Piezīme: Ja vēlaties aizsargāt visus servera failus, piemēram, db vai env failu. Ievietojiet to savā
.htaccess
failā:
RewriteEngine On
RewriteRule ^(.*)$ index.php
Nginx
Pārliecinieties, ka Nginx jau ir instalēts jūsu sistēmā. Ja nē, meklējiet Google, kā instalēt Nginx jūsu sistēmā.
Nginx gadījumā pievienojiet šādu savai servera deklarācijai:
server {
location / {
try_files $uri $uri/ /index.php;
}
}
Izveidojiet savu index.php
failu
Ja veicat pamatinstalēšanu, jums būs nepieciešams kāds kods, lai sāktu.
<?php
// Ja izmantojat Composer, iekļaujiet autoloader.
require 'vendor/autoload.php';
// ja neizmantojat Composer, ielādējiet framework tieši
// require 'flight/Flight.php';
// Tad definējiet maršrutu un piešķiriet funkciju, lai apstrādātu pieprasījumu.
Flight::route('/', function () {
echo 'hello world!';
});
// Visbeidzot, palaidiet framework.
Flight::start();
Ar skeleton lietotni tas jau ir konfigurēts un apstrādāts jūsu app/config/routes.php
failā. Pakalpojumi ir konfigurēti app/config/services.php
.
PHP instalēšana
Ja jums jau ir instalēts php
jūsu sistēmā, 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 specifisku versiju, piemēram, PHP 8.1:
brew tap shivammathur/php brew install shivammathur/php/php@8.1
- Instalējiet jaunāko versiju:
-
Pārslēdzieties starp PHP versijām:
- Atvienojiet 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
- Atvienojiet pašreizējo versiju un saistiet vēlamo versiju:
Windows 10/11
PHP instalēšana manuāli
-
Lejupielādējiet PHP:
- Apmeklējiet PHP for Windows un lejupielādējiet jaunāko vai specifisku versiju (piem., 7.4, 8.0) kā ne-vītu drošu 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 īpašībām > Vides mainīgajiem.
- Sadaļā Sistēmas mainīgie, atrast Path un noklikšķiniet Rediģēt.
- Pievienojiet ceļu
C:\php
(vai kur izvelcāt PHP). - Noklikšķiniet Labi, lai aizvērtu visus logus.
-
Konfigurējiet PHP:
- Kopējiet
php.ini-development
uzphp.ini
. - Rediģējiet
php.ini
, lai konfigurētu PHP pēc vajadzības (piem., iestatietextension_dir
, iespējiet paplašinājumus).
- Kopējiet
-
Pārbaudiet PHP instalēšanu:
- Atveriet Komandu uzvedni un izpildiet:
php -v
- Atveriet Komandu uzvedni un izpildiet:
Vairāku PHP versiju instalēšana
-
Atkārtojiet iepriekšējos soļus katrai versijai, izvietojot katru atsevišķā direktorijā (piem.,
C:\php7
,C:\php8
). -
Pārslēdzieties starp versijām, pielāgojot sistēmas PATH mainīgo, lai norādītu uz vēlamo versijas direktoriju.
Ubuntu (20.04, 22.04 utt.)
PHP instalēšana, izmantojot apt
-
Atjauniniet paketes 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 specifisku versiju, piemēram, PHP 8.1:
sudo apt install php8.1
- Instalējiet jaunāko PHP versiju:
-
Instalējiet papildu moduļus (pēc izvēles):
- Piemēram, lai instalētu MySQL atbalstu:
sudo apt install php8.1-mysql
- Piemēram, lai instalētu MySQL atbalstu:
-
Pārslēdzieties 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 repozitoriju:
- Atveriet Termināli un izpildiet:
sudo dnf install epel-release
- Atveriet Termināli un izpildiet:
-
Instalējiet Remi's repozitoriju:
- 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ēto versiju:
sudo dnf install php
- Lai instalētu specifisku versiju, piemēram, PHP 7.4:
sudo dnf module install php:remi-7.4
- Lai instalētu noklusēto versiju:
-
Pārslēdzieties starp PHP versijām:
- Izmantojiet
dnf
moduļ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 saskaņā ar jūsu projekta prasībām.
- Pārslēdzoties uz PHP versijām, pārliecinieties, ka visas attiecīgās PHP paplašinājumi ir instalēti specifiskajai versijai, ko plānojat izmantot.
- Pārsāciet savu tīmekļa serveri (Apache, Nginx utt.) pēc PHP versiju pārslēgšanas vai konfigurāciju atjaunināšanas, lai piemērotu izmaiņas.
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ā.