Styl kodowania bazowych plików frameworka Yii 2 =============================================== Poniższy styl kodowania jest stosowany w kodzie frameworka Yii 2.x i oficjalnych rozszerzeniach. Jeśli planujesz wysłać prośbę o dołączenie kodu do bazowego frameworka, powinieneś rozważyć stosowanie takiego samego stylu. Nie zmuszamy jednak nikogo do stosowania go we własnych aplikacjach. Wybierz styl, który najbardziej odpowiada Twoim potrzebom. Możesz pobrać gotową konfigurację dla CodeSniffera pod adresem: https://github.com/yiisoft/yii2-coding-standards ## 1. Omówienie Używamy przede wszystkim standardu kodowania [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md), zatem wszystko, co dotyczy [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) dotyczy również naszego stylu kodowania. - Pliki MUSZĄ używać tagów `` lub ``. - Nie należy dodawać spacji na końcach linii. - Nazwa każdego pliku zawierającego kod PHP powinna kończyć się rozszerzeniem `.php`. ### 2.2. Kodowanie znaków Kod PHP MUSI używać wyłącznie UTF-8 bez znacznika BOM. ## 3. Nazwy klas Nazwy klas MUSZĄ być zadeklarowane w formacie `StudlyCaps`. Przykładowo `Controller`, `Model`. ## 4. Klasy Termin "klasa" odnosi się tutaj do wszystkich klas i interfejsów. - Klasy powinny być nazwane w formacie `CamelCase`. - Otwierający nawias klamrowy powinien zawsze pojawić się w linii pod nazwą klasy. - Każda klasa musi posiadać blok dokumentacji dostosowany do składni PHPDoc. - Kod klasy musi być wcięty za pomocą 4 spacji. - W pojedynczym pliku PHP powinna znajdować się tylko jedna klasa. - Wszystkie klasy powinny być zadeklarowane w przestrzeni nazw. - Nazwa klasy powinna odpowiadać nazwie pliku. Przestrzeń nazw klasy powinna odpowiadać strukturze folderów. ```php /** * Dokumentacja */ class MyClass extends \yii\base\BaseObject implements MyInterface { // kod } ``` ### 4.1. Stałe Stałe klasy MUSZĄ być zadeklarowane wyłącznie wielkimi literami z łącznikiem w postaci podkreślnika. Dla przykładu: ```php 'Yii', 'options' => ['usePHP' => true], ]; ``` ### 5.4 Instrukcje kontrolne - Warunkowe instrukcje kontrolne muszą mieć pojedynczą spację przed i po nawiasie. - Operatory wewnątrz nawiasów powinny być oddzielone spacjami. - Otwierający nawias klamrowy powinien znajdować się w tej samej linii. - Zamykający nawias klamrowy powinien znajdować się w nowej linii. - Należy zawsze używać nawiasów klamrowych, nawet dla pojedynczych instrukcji. ```php if ($event === null) { return new Event(); } if ($event instanceof CoolEvent) { return $event->instance(); } return null; // poniższy zapis jest NIEDOZWOLONY: if (!$model && null === $event) throw new Exception('test'); ``` Należy unikać stosowania `else` po `return`, kiedy ma to sens. Należy używać [guard conditions](http://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html). ```php $result = $this->getResult(); if (empty($result)) { return true; } else { // przetwarzanie wyniku } ``` wygląda lepiej w postaci ```php $result = $this->getResult(); if (empty($result)) { return true; } // przetwarzanie wyniku ``` #### Instrukcja switch Należy używać następującego formatu dla instrukcji switch: ```php switch ($this->phpType) { case 'string': $a = (string) $value; break; case 'integer': case 'int': $a = (int) $value; break; case 'boolean': $a = (bool) $value; break; default: $a = null; } ``` ### 5.5 Wywołania funkcji ```php doIt(2, 3); doIt(['a' => 'b']); doIt('a', [ 'a' => 'b', 'c' => 'd', ]); ``` ### 5.6 Deklaracje funkcji anonimowych (lambdy) Należy zwrócić uwagę na spację pomiędzy słowem `function`/`use` a otwierającym nawiasem: ```php // dobrze $n = 100; $sum = array_reduce($numbers, function ($r, $x) use ($n) { $this->doMagic(); $r += $x * $n; return $r; }); // źle $n = 100; $mul = array_reduce($numbers, function($r, $x) use($n) { $this->doMagic(); $r *= $x * $n; return $r; }); ``` Dokumentacja ------------ - Należy stosować dokumentację zgodnie ze składnią [phpDoc](http://phpdoc.org/). - Kod bez dokumentacji jest niedozwolony. - Każdy plik klasy musi zawierać blok dokumentacji "poziomu pliku" na początku pliku i blok dokumentacji "poziomu klasy" zaraz nad klasą. - Nie ma konieczności używania `@return`, jeśli metoda niczego nie zwraca. - Wszystkie wirtualne właściwości w klasach, które rozszerzają `yii\base\BaseObject` są udokumentowane za pomocą tagu `@property` w bloku dokumentacji klasy. Adnotacje te są automatycznie generowane z tagów `@return` lub `@param` w odpowiednich getterach lub setterach przez uruchomienie `./build php-doc` w folderze build. Można dodać tag `@property` do gettera lub settera, aby wprost określić informację dla dokumentacji właściwości zadeklarowanej w tych metodach, kiedy opis różni się od tego, co znajduje się w `@return`. Poniżej znajduje się przykład: ```php * @since 2.0 */ class Component extends \yii\base\BaseObject ``` #### Poziom funkcji / metody ```php /** * Returns the list of attached event handlers for an event. * You may manipulate the returned [[Vector]] object by adding or removing handlers. * For example, * * ``` * $component->getEventHandlers($eventName)->insertAt(0, $eventHandler); * ``` * * @param string $name the event name * @return Vector list of attached event handlers for the event * @throws Exception if the event is not defined */ public function getEventHandlers($name) { if (!isset($this->_e[$name])) { $this->_e[$name] = new Vector; } $this->ensureBehaviors(); return $this->_e[$name]; } ``` #### Markdown Jak widać w powyższych przykładach, używamy składni markdown do formatowania komentarzy phpDoc. W dokumentacji stosowana jest dodatkowa składnia do linkowania klas, metod i właściwości: - `[[canSetProperty]]` utworzy link do metody lub właściwości `canSetProperty` w tej samej klasie. - `[[Component::canSetProperty]]` utworzy link do metody `canSetProperty` w klasie `Component` w tej samej przestrzeni nazw. - `[[yii\base\Component::canSetProperty]]` utworzy link do metody `canSetProperty` w klasie `Component` w przestrzeni nazw `yii\base`. - `[[Component]]` utworzy link do klasy `Component` w tej samej przestrzeni nazw. Można tutaj również dodać przestrzeń nazw. Aby nadać powyższym linkom inną etykietę niż nazwa klasy lub metody, można użyć składni pokazanej w poniższym przykładzie: ``` ... as displayed in the [[header|header cell]]. ``` Część przed | jest linkowaną metodą, właściwością lub klasą, a część po | jest etykietą linku. Możliwe jest też linkowanie do Przewodnika używając następującej składni: ```markdown [link to guide](guide:file-name.md) [link to guide](guide:file-name.md#subsection) ``` #### Komentarze - Komentarze jednolinijkowe powinny zaczynać się od `//` a nie od `#`. - Komentarze jednolinijkowe powinny znajdować się w osobnej linii. Dodatkowe zasady ---------------- ### `=== []` vs `empty()` Należy używać `empty()`, kiedy jest to możliwe. ### Wielokrotne punkty powrotu Należy powracać (return) wcześnie, kiedy tylko instrukcje warunkowe zaczynają się zagnieżdżać. Nie ma to znaczenia w przypadku krótkich metod. ### `self` vs. `static` Należy zawsze używać `static` z wyjątkiem poniższych przypadków: - odwołania do stałych MUSZĄ odbywać się za pomocą `self`: `self::MY_CONSTANT` - odwołania do prywatnych statycznych właściwości MUSZĄ odbywać się za pomocą `self`: `self::$_events` - można używać `self` do wywołania metod, kiedy ma to sens, jak w przypadku wywołań rekurencyjnych aktualnej implementacji zamiast rozszerzania implementacji klas. ### Wartość dla "nie rób czegoś" Właściwości pozwalające na skonfigurowanie komponentu, tak, aby nie robił czegoś, powinny przyjmować wartość `false`. `null`, `''` lub `[]` nie powinny być traktowane w ten sposób. ### Nazwy folderów/przestrzeni nazw - należy używać małych liter - należy używać liczby mnogiej rzeczowników, które reprezentują obiekty (np. validators) - należy używać liczby pojedynczej dla nazw reprezentujących funkcjonalności (np. web) - preferowane są przestrzenie nazw będące pojedynczym słowem - w przypadku, gdy pojedyncze słowo nie jest wystarczające, należy użyć formatu camelCase