Rusové v základním týmu PHP: "Jazyk roste jako korál." Nastavení php-fpm Jak jste se dostali do základního týmu PHP, jakou cestou jste se tam dostali?

16.09.2016

Pokusme se zjistit, jak zvýšit výkon aplikačního serveru založeného na php-fpm, a také vytvořit kontrolní seznam pro kontrolu konfigurace procesu fpm.

Nejprve byste měli určit umístění konfiguračního souboru fondu. Pokud jste nainstalovali php-fpm ze systémového úložiště, pak konfigurace fondu www bude umístěn přibližně zde /etc/php5/fpm/pool.d/www.conf . Pokud používáte vlastní sestavení nebo jiný OS (ne debian), měli byste hledat umístění souboru v dokumentaci nebo jej zadat ručně.

Zkusme se na konfiguraci podívat podrobněji.

Přechod na UNIX sockety

Pravděpodobně první věc, kterou byste měli věnovat pozornost, je to, jak data proudí z webového serveru do vašich PHP procesů. To se odráží v direktivě listen:

poslech = 127.0.0.1:9000

Pokud je nastavena adresa:port, pak data procházejí zásobníkem TCP a to pravděpodobně není příliš dobré. Pokud existuje cesta k soketu, například:

listen = /var/run/php5-fpm.sock

pak data procházejí unixovým socketem a tuto sekci můžete přeskočit.

Proč se stále vyplatí přejít na unixovou patici? UDS (unix domain socket), na rozdíl od komunikace přes TCP stack, má významné výhody:

  • nevyžadují přepínání kontextu, UDS používá netisr)
  • Datagram UDS je zapsán přímo do cílového soketu
  • odeslání datagramu UDS vyžaduje méně operací (žádné kontrolní součty, žádné hlavičky TCP, žádné směrování)

Průměrná latence TCP: 6 us UDS průměrná latence: 2 us Průměrná latence PIPE: 2 us Průměrná propustnost TCP: 253702 msg/s Průměrná propustnost UDS: 1733874 msg/s Průměrná propustnost PIPE: 1682796 msg/s

UDS má tedy zpoždění ~66% méně a propustnost v 7krát více TCP. Proto se s největší pravděpodobností vyplatí přejít na UDS. V mém případě bude soket umístěn na /var/run/php5-fpm.sock.

; Pojďme to okomentovat – listen = 127.0.0.1:9000 listen = /var/run/php5-fpm.sock

Měli byste se také ujistit, že webový server (nebo jakýkoli jiný proces, který potřebuje komunikovat) má přístup pro čtení/zápis do vašeho soketu. K tomu existují nastavení poslouchat.skupina A režim poslechu Nejjednodušší způsob je spustit oba procesy od stejného uživatele nebo skupiny, v našem případě php-fpm a webový server se spustí se skupinou www-data:

listen.owner = www-data listen.group = www-data listen.mode = 0660

Kontrola vybraného mechanismu zpracování událostí

Pro efektivní práci s I/O (vstup/výstup, soubor/zařízení/socket deskriptory) se vyplatí zkontrolovat, zda je nastavení zadáno správně události.mechanismus. Pokud je php-fpm nainstalováno ze systémového úložiště, s největší pravděpodobností je tam vše v pořádku - buď není zadáno (nainstalováno automaticky), nebo zadáno správně.

Jeho význam závisí na OS, pro který je v dokumentaci nápověda:

; - epoll (linux >= 2.5.44); - kqueue (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0) ; - /dev/poll (Solaris >= 7) ; - port (Solaris >= 10)

Pokud například pracujeme na moderní distribuci Linuxu, potřebujeme epool:

události.mechanismus = epoll

Výběr typu fondu - dynamický / statický / na vyžádání

Rovněž stojí za to věnovat pozornost nastavení správce procesů (pm). V podstatě se jedná o hlavní proces, který bude spravovat všechny své potomky (které spouštějí kód aplikace) podle určité logiky, která je ve skutečnosti popsána v konfiguračním souboru.

K dispozici jsou celkem 3 schémata řízení procesů:

  • dynamický
  • statický
  • na požádání

Nejjednodušší je statický. Funguje to následovně: spusťte pevný počet podřízených procesů a udržujte je v provozuschopném stavu. Toto operační schéma není příliš efektivní, protože počet požadavků a jejich zatížení se může čas od času měnit, ale počet podřízených procesů nikoli - vždy zabírají určité množství paměti RAM a nemohou zpracovat špičkové zatížení ve frontě.

dynamický tento problém vyřeší fond, který reguluje počet podřízených procesů na základě hodnot konfiguračního souboru a mění je nahoru nebo dolů v závislosti na zatížení. Tento fond je nejvhodnější pro aplikační server, který vyžaduje rychlou reakci na požadavky, práci se špičkovým zatížením a vyžaduje úsporu prostředků (snížením počtu podřízených procesů při nečinnosti).

na požádání bazén je velmi podobný statický, ale při spuštění hlavního procesu nespustí podřízené procesy. Teprve když přijde první požadavek, vytvoří se první podřízený proces a po určité době čekání (zadané v konfiguraci) bude zničen. Proto je relevantní pro servery s omezenými prostředky nebo pro logiku, která nevyžaduje rychlou odezvu.

Úniky paměti a zabiják OOM

Měli byste věnovat pozornost kvalitě aplikací, které budou spouštěny podřízenými procesy. Pokud kvalita aplikace není příliš vysoká nebo se používá mnoho knihoven třetích stran, musíte přemýšlet o možných únikech paměti a nastavit hodnoty těchto proměnných:

  • pm.max_requests
  • request_terminate_timeout

pm.max_requests toto je maximální počet požadavků, které podřízený proces zpracuje, než bude zabit. Vynucená destrukce procesu vám umožní vyhnout se situaci, kdy paměť podřízeného procesu „nabobtná“ kvůli únikům (protože proces pokračuje v práci po vyžádání po vyžádání). Na druhou stranu příliš malá hodnota bude mít za následek časté restarty, což povede ke ztrátám výkonu. Vyplatí se začít s hodnotou 1000 a poté tuto hodnotu snížit nebo zvýšit.

request_terminate_timeout nastavuje maximální dobu, po kterou může podřízený proces běžet, než bude zabit. To vám umožní vyhnout se dlouhým dotazům, pokud byla z nějakého důvodu změněna hodnota max_execution_time v nastavení interpretu. Hodnota by měla být nastavena na základě logiky zpracovávaných aplikací, řekněme 60. léta(1 minuta).

Nastavení dynamického fondu

Pro hlavní aplikační server se kvůli zjevným výhodám často volí dynamický fond. Jeho činnost je popsána následujícími nastaveními:

  • pm.max_children- maximální počet podřízených procesů
  • pm.start_servers- počet procesů při spuštění
  • pm.min_spare_servers- minimální počet procesů čekajících na připojení (požadavek na zpracování)
  • pm.max_spare_servers- maximální počet procesů čekajících na připojení (požadavky ke zpracování)

Pro správné nastavení těchto hodnot je nutné zvážit:

  • kolik paměti průměrně spotřebuje dětský proces?
  • množství dostupné paměti RAM

Průměrnou hodnotu paměti na jeden proces php-fpm na již běžící aplikaci můžete zjistit pomocí plánovače:

# ps -ylC php-fpm --sort:rss S UID PID PPID C PRI NI RSS SZ WCHAN TTY TIME CMD S 0 1445 1 0 80 0 9552 42588 ep_pol ? 00:00:00 php5-fpm

Potřebujeme průměrnou hodnotu ve sloupci RSS (velikost rezidentní paměti v kilobajtech). V mém případě je to ~ 20 MB. Pokud nedochází k žádnému zatížení aplikací, můžete použít Apache Benchmark k vytvoření jednoduchého zatížení php-fpm.

Množství celkové / dostupné / použité paměti lze zobrazit pomocí volný, uvolnit:

# free -m celkem využito zdarma ... Paměť: 4096 600 3496

Celkový maximální počet procesů = (celkem RAM - (použitá RAM + vyrovnávací paměť)) / (paměť na proces php) Celková RAM: 4 GB Použitá RAM: 1000 MB Bezpečnostní vyrovnávací paměť: 400 MB Paměť na podřízený proces php-fpm (v průměru): 30 MB Maximální možný počet procesů = (4096 - (1000 + 400)) / 30 = 89 Sudé číslo: 89 zaokrouhleno dolů na 80

Hodnotu zbývajících direktiv lze nastavit na základě očekávaného zatížení aplikace a také vzít v úvahu, co dalšího server dělá kromě běhu php-fpm (například DBMS také vyžaduje zdroje). Pokud je na serveru mnoho úloh, vyplatí se snížit počet počátečních / maximálních procesů.

Vezměme například v úvahu, že na serveru jsou 2 fondy www1 a www2 (například 2 webové zdroje), konfigurace každého z nich pak může vypadat takto:

pm.max_children = 40 ; 80 / 14 pm.start_servers = 15 pm.min_spare_servers = 15 pm.max_spare_servers = 25

Pokud jste vyvíjeli PHP posledních pár let, pravděpodobně si uvědomujete problémy tohoto jazyka. Často uslyšíte, že jde o roztříštěný jazyk, hackerský nástroj, že nemá žádnou skutečnou specifikaci atd. Realita je taková, že PHP se v poslední době hodně rozrostlo. PHP 5.4 jej přiblížilo plně objektovému modelu a představilo spoustu nových funkcí.

A to všechno je samozřejmě dobré, ale co frameworky? V PHP jich je obrovské množství. Jakmile začnete hledat, uvědomíte si, že nebudete mít dost času je všechny prostudovat, protože se neustále objevují nové frameworky a v každém se vymýšlí něco jiného. Jak to tedy proměnit v něco, co neodcizuje vývojáře a umožňuje snadné přenesení funkcí z jednoho frameworku do druhého?

Co je PHP-FIG

PHP-FIG (PHP Framework Interop Group) je organizovaná skupina vývojářů, jejímž cílem je najít způsoby, jak spolupracovat více frameworků.

Jen si to představte: aktuálně podporujete projekt Zend Framework, který potřebuje modul nákupního košíku. Už jste takový modul napsali pro předchozí projekt, který byl na Symphony. Proč to neudělat znovu? Naštěstí ZendF i Symphony jsou součástí PHP-FIG, takže je možné importovat modul z jednoho frameworku do druhého. Není to skvělé?

Pojďme zjistit, které rámce jsou součástí PHP-FIG

Členové PHP-FIG

Každý vývojář může přidat svůj framework do seznamu účastníků PHP-FIG. Za to však budete muset zaplatit nějaké peníze, takže pokud nemáte podporu komunity, pravděpodobně s tím nebudete souhlasit. To se provádí proto, aby se zabránilo registraci milionů mikrorámců bez reputace.

Současní členové:

Co je PSR?

PSR (PHP Standards Recommendations) - standardní doporučení, výsledek práce PHP-FIG. Někteří členové skupiny navrhují pravidla pro každý PSR, zatímco jiní hlasují pro podporu nebo zrušení pravidel. Diskuze probíhá ve Skupinách Google a sady PSR jsou dostupné na oficiálních stránkách PHP-FIG.

Podívejme se na některé PSR:

Prvním krokem ke sjednocení rámců je mít společnou adresářovou strukturu, a proto byl přijat společný startovací standard.

  1. Jmenný prostor a třída musí mít strukturu \\(\)*.
  2. Každý jmenný prostor musí obsahovat mezeru nejvyšší úrovně ("Název dodavatele").
  3. Každý jmenný prostor může mít libovolný počet úrovní.
  4. Každý oddělovač jmenného prostoru je při načtení převeden na DIRECTORY_SEPARATOR.
  5. Každý znak „_“ v CLASS NAME je převeden na DIRECTORY_SEPARATOR.
  6. Plně kvalifikovaný jmenný prostor a třída jsou při načtení připojeny s ".php".

Příklad funkce automatického načítání:

PSR-1 - Základní kódovací standard

Tyto PSR regulují základní standardy, jejichž hlavní myšlenkou je, že pokud všichni vývojáři používají stejné standardy, pak lze kód bez problémů přenést.

  1. Soubory musí používat pouze značky
  2. Soubory musí používat pouze kódování UTF-8 bez kusovníku.
  3. Názvy prostorů a třídy musí následovat PSR-0.
  4. Názvy tříd musí být deklarovány v notaci StudlyCaps.
  5. Konstanty třídy musí být deklarovány velkými písmeny oddělenými podtržítky.
  6. Metody musí být deklarovány v notaci camelCase.

PSR-2 - Průvodce stylem kódování

Toto jsou rozšířené instrukce pro PSR-1, které popisují pravidla formátování kódu.

  1. Kód musí odpovídat PSR-1.
  2. Místo tabulátorů by měly být použity 4 mezery.
  3. Délka řádku by neměla být striktně omezena, doporučená délka je do 80 znaků.
  4. Za deklarací jmenného prostoru by měl být jeden prázdný řádek.
  5. Závorky pro třídy by se měly otevírat na dalším řádku za deklarací a zavírat za tělem třídy (stejné pro metody).
  6. Musí být definována viditelnost metod a vlastností (veřejné, soukromé).
  7. Otevírací konzoly pro řídicí konstrukce musí být na stejné linii, uzavírací konzoly musí být na další řadě za tělesem konstrukce.
  8. Mezery se neumisťují za úvodní závorky metod řídicí struktury a před uzavírací závorky.

PCR-3 - Logger Interface

PCR-3 reguluje protokolování, zejména devět hlavních metod.

  1. LoggerInterface poskytuje 8 metod pro protokolování osmi úrovní RFC 5424 (ladění, upozornění, varování, chyba, kritická, výstraha, nouzový stav).
  2. Devátá metoda log() bere jako svůj první parametr úroveň varování. Volání metody s parametrem úrovně výstrahy musí vrátit stejný výsledek jako volání metody na určité úrovni protokolu (log(ALERT) == alert()). Volání metody s nedefinovanou úrovní varování musí vyvolat výjimku Psr\Log\InvalidArgumentException.

Stejně jako PSR-0 poskytuje PSR-4 vylepšené metody automatického načítání

  1. Termín "třída" odkazuje na třídy, rozhraní, vlastnosti a další podobné struktury
  2. Plně kvalifikovaný název třídy má následující tvar: \ (\)*\
  3. Při načítání souboru, který odpovídá plně kvalifikovanému názvu třídy:
  • Souvislá řada jednoho nebo více úvodních jmenných prostorů, nepočítaje úvodní oddělovač jmenného prostoru, v plně kvalifikovaném názvu třídy odpovídá alespoň jednomu "kořenovému adresáři".
  • Názvy adresářů a podadresářů musí odpovídat velikosti písmen v oboru názvů.
  • Konec celého názvu třídy odpovídá názvu souboru končícímu na .php. Velikost písmen v názvu souboru se musí shodovat s malými a velkými písmeny na konci celého názvu třídy.
  • Implementace autoloaderu nesmí vyvolávat výjimky, generovat chyby jakékoli úrovně a nemusí vracet hodnotu.

Závěr

PHP-FIG mění způsob, jakým jsou frameworky psány, ale ne jak fungují. Klienti často vyžadují, abyste pracovali s existujícím kódem v rámci nebo určili, se kterým rámcem byste měli na projektu pracovat. Doporučení PSR v tomto ohledu vývojářům výrazně usnadňují život a to je skvělé!

1. GROUP BY one key

Tato funkce funguje jako GROUP BY pro pole, ale s jedním důležitým omezením: Je možný pouze jeden seskupovací "sloupec" ($identifikátor) ​​.

Funkce arrayUniqueByIdentifier(pole $pole, řetězec $identifikátor) ​​( $ids = pole_column($pole, $identifikátor); $ids = pole_unique($ids); $array = pole_filter($pole, funkce ($klíč, $hodnota ) use ($ids) ( return in_array($value, array_keys($ids)); ), ARRAY_FILTER_USE_BOTH); return $array; )

2. Detekce jedinečných řádků pro tabulku (dvourozměrné pole)

Tato funkce slouží k filtrování „řádků“. Řekneme-li, že dvourozměrné pole je tabulka, pak každý jeho prvek je řádek. Pomocí této funkce tedy můžeme odstranit duplicitní řádky. Dva řádky (prvky prvního rozměru) jsou stejné, pokud jsou všechny jejich sloupce (prvky druhého rozměru) stejné. Pro porovnávání hodnot "sloupců" platí: Pokud je hodnota jednoduchého typu, použije se při porovnávání samotná hodnota; jinak bude použit jeho typ (pole , objekt , zdroj , neznámý typ).

Strategie je jednoduchá: Vytvořte z původního pole mělké pole, kde prvky jsou implodovány do "sloupců" původního pole; pak na něj aplikujte array_unique(...); a jako poslední použít zjištěná ID pro filtrování původního pole.

Funkce arrayUniqueByRow(pole $table = , řetězec $implodeSeparator) ( $elementStrings = ; foreach ($table as $row) ( // Chcete-li se vyhnout upozorněním jako "Převod pole na řetězec". $elementPreparedForImplode = array_map(funkce ($pole) ( $valueType = gettype($field); $simpleTypes = ["boolean", "integer", "double", "float", "string", "NULL"]; $field = in_array($valueType, $simpleTypes) ? $field: $valueType; return $field; ), $row); return $table; )

Je také možné zlepšit porovnávání, detekovat třídu hodnoty "sloupce", pokud je jejím typem objekt.

$implodeSeparator by měl být víceméně komplexní, z.B. spl_object_hash($this) .

3. Detekce řádků se sloupci s jedinečným identifikátorem pro tabulku (dvourozměrné pole)

Toto řešení se opírá o 2. Nyní nemusí být celý „řádek“ jedinečný. Dva „řádky“ (prvky první dimenze) jsou nyní stejné, pokud všechny relevantní"pole" (prvky druhé dimenze) jednoho "řádku" se rovnají odpovídajícím "polím" (prvkům se stejným klíčem).

"Relevantní" "pole" jsou "pole" (prvky druhé dimenze), které mají klíč, který se rovná jednomu z prvků předávaných "identifikátorů".

Funkce arrayUniqueByMultipleIdentifiers(pole $tabulka, pole $identifikátory, řetězec $implodeSeparator = null) ( $arrayForMakingUniqueByRow = $removeArrayColumns($table, $identifiers, true); $arrayUniqueByRow = $arrayUniqueByarrayRowRowSeparow($); ByMultipleI identifiers = array_intersect_key ($table, $arrayUniqueByRow); return $arrayUniqueByMultipleIdentifiers; ) funkce removeArrayColumns(pole $table, pole $columnNames, bool $isWhitelist = false) (foreach ($table jako $rowKey => $array) ( if (is row )) ( if ($isWhitelist) ( foreach ($row as $fieldName => $fieldValue) (neif (!in_array($fieldName, $columnNames)) ( unset($table[$rowKey][$fieldName] ); ) ) ) else ( foreach ($row as $fieldName => $fieldValue) ( ​​​if (in_array($fieldName, $columnNames)) ( unset($table[$rowKey][$fieldName]); ) ) ) ) vrátit $ tabulku; )

Vzhledem k tomu, že vývoj technologií vedl k tomu, že každý programátor má nyní svůj vlastní počítač, jako vedlejší efekt máme tisíce různých knihoven, frameworků, služeb, API atd. pro všechny příležitosti. Ale když přijde tento případ života, vyvstává problém - co použít a co dělat, když to úplně nesedí - přepište to, napište vlastní od začátku nebo připojte několik řešení pro různé případy použití.

Myslím, že mnoho lidí si všimlo, že vytváření projektu často nespočívá ani tak v programování, jako spíše v psaní kódu pro integraci několika hotových řešení. Někdy se takové kombinace promění v nová řešení, která lze opakovaně použít v následných problémech.

Přejděme ke konkrétní „běžící“ úloze – objektové vrstvě pro práci s databázemi v PHP. Existuje velké množství různých řešení, od PDO po víceúrovňové (a podle mého názoru ne zcela vhodné v PHP) ORM motory.

Většina těchto řešení migrovala na PHP z jiných platforem. Často ale autoři neberou v úvahu vlastnosti PHP, což by značně zjednodušilo jak psaní, tak používání portovaných konstrukcí.
Jednou z běžných architektur pro tuto třídu úloh je vzor Active Record. Tato šablona se používá zejména k vytváření takzvaných entit, které se v té či oné podobě používají na řadě platforem, od perzistentních beanů v EJB3 po EF v .NET.

Vytvořme tedy podobnou konstrukci pro PHP. Spojme dvě super věci – hotovou knihovnu ADODB a slabě typované a dynamické vlastnosti objektů jazyka PHP.
Jednou z mnoha funkcí ADODB je tzv. automatické generování SQL dotazů pro vkládání (INSERT) a aktualizaci (UPDATE) záznamů na základě asociativních polí s daty.
Ve skutečnosti není nic vojenského, co by si vzalo pole, kde klíče jsou názvy polí a hodnoty jsou data a generují řetězec dotazu SQL. Ale ADODB to dělá chytřeji. Dotaz je založen na struktuře tabulky, která je předtím načtena z databázového schématu. Výsledkem je, že za prvé jsou v sql zahrnuta pouze existující pole a ne vše v řadě, za druhé je zohledněn typ pole - u řetězců jsou přidány uvozovky, formáty data mohou být tvořeny na základě časového razítka, pokud jej ADODB vidí místo řetězec v přenášené hodnotě atd. .

Nyní pojďme ze strany PHP.
Představme si takovou třídu (zjednodušeně).

Entita třídy( chráněné $pole = pole(); veřejná konečná funkce __set($jméno, $hodnota) ( ​​$this->pole[$jméno] = $hodnota; ) veřejná konečná funkce __get($jméno) ( return $ this- >fields[$name]; ) )

Předáním interního pole do knihovny ADODB můžeme automaticky generovat SQL dotazy pro aktualizaci záznamu v databázi s daným objektem.Zároveň odpadá těžkopádné návrhy mapování polí databázových tabulek na entitu založenou na XML objektová pole a podobně. Je pouze nutné, aby název pole odpovídal vlastnosti objektu. Protože na tom, jak jsou pole v databázi a pole objektu pojmenována, nezáleží na počítači, není důvod, aby se neshodovaly.

Pojďme si ukázat, jak to funguje ve finální verzi.
Kód pro dokončenou třídu se nachází na Gist. Jedná se o abstraktní třídu obsahující minimum nutné pro práci s databází. Podotýkám, že tato třída je zjednodušenou verzí řešení, které bylo testováno na několika desítkách projektů.

Představme si, že máme takové znamení:

CREATE TABLE `users` (`username` varchar(255) , `created` date , `user_id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`user_id`))
Na typu databáze nezáleží - ADODB poskytuje přenositelnost na všechny běžné databázové servery.

Vytvořme třídu entity User na základě třídy Entity

/** * @table=users * @keyfield=user_id */ class User extends Entity()

To je vše.
Snadné použití:

$user = nový uživatel(); $user->username="Vasya Pupkin"; $user->created=time(); $user->save(); //uložit do úložiště //načíst znovu $thesameuser = User::load($user->user_id); echo $thesameuser ->uživatelské jméno;

Tabulku a pole klíče označujeme v pseudoanotacích.
Můžeme také určit pohled (například view =usersview), pokud, jak je tomu často, je entita vybrána na základě její tabulky s připojenými nebo vypočítanými poli. V tomto případě budou data vybrána z pohledu a tabulka bude aktualizována. Ti, kterým se takové poznámky nelíbí, mohou přepsat metodu getMetatada() a zadat parametry tabulky ve vráceném poli.

Co dalšího je užitečné na třídě Entity v této implementaci?

Můžeme například přepsat metodu init(), která se volá po vytvoření instance entity, a inicializovat výchozí datum vytvoření.
Nebo přetížit metodu afterLoad(), která je automaticky volána po načtení entity z databáze, a převést tak datum na časové razítko pro další pohodlnější použití.
Ve výsledku tak získáme ne o moc složitější strukturu.

/** * @table=users * @view=usersview * @keyfield=user_id */ class Uživatel rozšiřuje Entitu( chráněná funkce init() ( $this->created = time(); ) chráněná funkce afterLoad() ( $this ->created = strtotime($this->created); ) )

Můžete také přetížit metody beforeSave a beforeDelete a další události životního cyklu, kde můžete například provést ověření před uložením nebo některé další akce - například odstranit obrázky z nahrávání při mazání uživatele.

Načteme seznam entit podle kritéria (v podstatě podmínka pro WHERE).
$users = User::load("uživatelské jméno jako "Pupkin" ");
Třída Entity vám také umožňuje provádět libovolný, „nativní“ SQL dotaz, abych tak řekl. Chceme například vrátit seznam uživatelů s některými seskupeními na základě statistik. Nezáleží na tom, která konkrétní pole budou vrácena (hlavní je, že by tam mělo být user_id, pokud je potřeba s entitou dále manipulovat), stačí znát jejich jména, abyste měli přístup k vybraným polím. Při ukládání entity, jak je z výše uvedeného zřejmé, také nemusíte vyplňovat všechna pole, která budou v objektu entity přítomna, ta půjdou do databáze. To znamená, že nepotřebujeme vytvářet další třídy pro náhodné vzorky. Podobně jako anonymní struktury při načítání v EF, pouze zde se jedná o stejnou třídu entity se všemi metodami obchodní logiky.

Přísně vzato, výše uvedené metody získávání seznamů jsou poněkud mimo vzor AR. V podstatě se jedná o tovární metody. Ale jak Occamův starý muž odkázal, nevytvářejme entity nad rámec toho, co je nutné, a vytvářejme samostatného Správce entit nebo něco podobného.

Všimněte si, že výše uvedené jsou pouze třídy PHP a lze je rozšířit a upravit podle potřeby přidáním vlastností a metod obchodní logiky do entity (nebo do základní třídy Entity). To znamená, že obdržíme nejen kopii řádku databázové tabulky, ale obchodní entitu jako součást objektové architektury aplikace.

Kdo by z toho mohl mít prospěch? Samozřejmě ne pro ostřílené vývojáře, kteří věří, že používat něco jednoduššího, než je doktrína, není úctyhodné, a ani pro perfekcionisty, kteří jsou přesvědčeni, že pokud řešení nevytáhne miliardu volání do databáze za sekundu, pak to řešení není. . Soudě podle fór, mnoho běžných vývojářů pracujících na běžných (99,9 %) projektech dříve či později čelí problému najít jednoduchý a pohodlný objektový způsob přístupu k databázi. Potýkají se ale s tím, že většina řešení je buď nepřiměřeně sofistikovaná, nebo je součástí nějakého rámce.

P.S. Řešení z frameworku bylo vytvořeno jako samostatný projekt

PHP programovací jazyk ušel dlouhou cestu od nástroje pro vytváření osobních stránek k univerzálnímu jazyku. Dnes je nainstalován na milionech serverů po celém světě a používají jej miliony vývojářů, kteří vytvářejí širokou škálu projektů.

Je snadné se naučit a velmi populární, zejména mezi začátečníky. Proto byl vývoj jazyka následován silným rozvojem komunity kolem něj. Obrovské množství skriptů, pro všechny příležitosti, různé knihovny, frameworky. Neexistence jednotných standardů pro návrh a psaní kódu vedla ke vzniku obrovské vrstvy informačních produktů postavených na vlastních principech vývojáře tohoto produktu. To bylo zvláště patrné při práci s různými PHP frameworky, který dlouhou dobu představoval uzavřený ekosystém, nekompatibilní s jinými frameworky, a to přesto, že úkoly, které řeší, jsou často podobné.

V roce 2009 se vývojáři několika frameworků dohodli na vytvoření komunity PHP Framework Interop Group (PHP-FIG), který by vypracoval doporučení pro vývojáře. Je důležité zdůraznit, že to není o normy ISO, správnější je mluvit o doporučeních. Ale od těch, kteří tvořili PHP-obr Protože vývojářská komunita představuje velké rámce, jejich doporučení mají vážnou váhu. Podpěra, podpora standardy PSR (standardní doporučení PHP). umožňuje kompatibilitu, což usnadňuje a urychluje vývoj konečného produktu.

Celkem je v době psaní tohoto článku 17 norem, 9 z nich je schváleno, 8 je ve fázi návrhu, aktivně se diskutuje, 1 norma není doporučena k použití.

Nyní přejdeme přímo k popisu každého standardu. Vezměte prosím na vědomí, že se zde nebudu rozepisovat o každém standardu, spíše se jedná o krátký úvod. Kromě toho se článek bude zabývat pouze těmi PSR standardy, které jsou oficiálně přijímány, tzn. jsou ve stavu Přijato.

PSR-1. Základní kódovací standard

Představuje nejobecnější pravidla, jako je používání PHP tagy, kódování souborů, oddělení místa deklarace funkce, třídy a místa jejich použití, pojmenování tříd a metod.

PSR-2. Průvodce stylem kódu

Navazuje na první standard a upravuje používání tabulátorů a zalomení řádků v kódu, maximální délku řádků kódu, pravidla pro navrhování řídicích struktur atd.

PSR-3. Rozhraní protokolování.

Tento standard je navržen tak, aby umožňoval (logování) přihlašování do aplikací napsaných v PHP.

PSR-4. Startovací standard

Toto je pravděpodobně nejdůležitější a nezbytný standard, o kterém bude pojednáno v samostatném podrobném článku. Třídy, které implementují PSR-4, lze načíst pomocí jediného automatického zavaděče, což umožňuje použití dílů a komponent z jednoho rámce nebo knihovny v jiných projektech.

PSR-6. Rozhraní mezipaměti

Ukládání do mezipaměti se používá ke zlepšení výkonu systému. A PSR-6 umožňuje standardně ukládat a načítat data z cache pomocí jednotného rozhraní.

PSR-7. Rozhraní zpráv HTTP

Při psaní více či méně složitém webové stránky v PHP, se kterým musíte téměř vždy pracovat HTTP hlavičky. Rozhodně, jazyk PHP nám poskytuje hotové možnosti práce s nimi, jako je kupř superglobální pole $_SERVER, funkce záhlaví(), setcookie() atd., jejich ruční analýza je však plná chyb a ne vždy je možné vzít v úvahu všechny nuance práce s nimi. A tak, aby se usnadnila práce vývojářů a aby se vytvořilo rozhraní pro interakci HTTP protokol tato norma byla přijata. Podrobněji o tomto standardu pohovořím v některém z následujících článků.

PSR-11. Rozhraní kontejneru

Při psaní PHP programyČasto musíte používat komponenty třetích stran. A abychom se v tomto lese závislostí neztratili, byly vynalezeny různé metody správy závislostí kódu, často vzájemně nekompatibilní, což tento standard přináší do společného jmenovatele.

PSR-13. Hypermediální odkazy

Toto rozhraní je navrženo tak, aby usnadnilo vývoj a používání rozhraní pro programování aplikací ( API).

PSR-14. Jednoduché rozhraní pro ukládání do mezipaměti

Je pokračováním a vylepšením standardu PSR-6

Tak jsme se dnes podívali PSR standardy. Pro aktuální informace o stavu norem prosím kontaktujte: