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
Używamy przede wszystkim standardu kodowania PSR-2, zatem wszystko, co dotyczy PSR-2 dotyczy również naszego stylu kodowania.
- Pliki MUSZĄ używać tagów
<?php
albo<?=
. - Na końcu pliku powinna znajdować się pusta linia.
- Pliki MUSZĄ używać kodowania UTF-8 bez znacznika BOM dla kodu PHP.
- Kod MUSI używać 4 spacji do wcięć, a nie tabulatorów.
- Nazwy klas MUSZĄ być zadeklarowane w formacie
StudlyCaps
. - Stałe w klasach MUSZĄ być zadeklarowane wyłącznie wielimi literami z łącznikiem w postaci podkreślnika.
- Nazwy metod klasy MUSZĄ być zadeklarowane w formacie
camelCase
. - Nazwy właściwości klasy MUSZĄ być zadeklarowane w formacie
camelCase
. - Nazwy właściwości klasy MUSZĄ zaczynać się podkreślnikiem, jeśli są prywatne.
- Należy używać
elseif
zamiastelse if
.
- Kod PHP MUSI używać tagów
<?php ?>
lub<?=
; NIE MOŻE używać innych tagów takich jak<?
. - W przypadku, gdy plik zawiera tylko kod PHP, nie powinien kończyć się tagiem
?>
. - Nie należy dodawać spacji na końcach linii.
- Nazwa każdego pliku zawierającego kod PHP powinna kończyć się rozszerzeniem
.php
.
Kod PHP MUSI używać wyłącznie UTF-8 bez znacznika BOM.
Nazwy klas MUSZĄ być zadeklarowane w formacie StudlyCaps
. Przykładowo Controller
, Model
.
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.
/**
* Dokumentacja
*/
class MyClass extends \yii\base\BaseObject implements MyInterface
{
// kod
}
Stałe klasy MUSZĄ być zadeklarowane wyłącznie wielkimi literami z łącznikiem w postaci podkreślnika. Dla przykładu:
<?php
class Foo
{
const VERSION = '1.0';
const DATE_APPROVED = '2012-06-01';
}
- Deklarując publiczne elementy klasy należy używać wprost słowa kluczowego
public
. - Publiczne i chronione zmienne powinny być zadeklarowane na początku klasy, przed deklaracjami metod. Prywatne zmienne również powinny być zadeklarowane na początku klasy, ale mogą być również dodane zaraz przed metodami, które ich używają w przypadku, gdy są stosowane tylko w kilku z nich.
- Kolejność deklaracji właściwości w klasie powinna być rosnąca według ich widoczności: od publicznych, przez chronione, do prywatnych.
- Nie ma ścisłych zasad dotyczących kolejności właściwości o tej samej widoczności.
- Dla zapewnienia lepszej czytelności kodu, nie powinno być żadnych pustych linii pomiędzy deklaracjami właściwości, a sekcje deklaracji właściwości i metod klasy powinny być rozdzielona dwoma pustymi liniami. Pojedyncza pusta linia powinna być dodana pomiędzy grupami o różnej widoczności.
- Prywatne zmienne powinny być nazwane w formacie
$_varName
. - Publiczne elementy klasy i niezależne zmienne powinny być nazwane w formacie
$camelCase
z pierwszą literą małą. - Należy używać opisowych nazw. Należy unikać używania zmiennych takich jak
$i
i$j
.
Przykładowo:
<?php
class Foo
{
public $publicProp1;
public $publicProp2;
protected $protectedProp;
private $_privateProp;
public function someMethod()
{
// ...
}
}
- Funkcje i metody klasy powinny być nazwane w formacie
camelCase
z pierwszą literą małą. - Nazwy powinny być opisowe i wskazywać cel istnienia funkcji.
- Metody klasy powinny zawsze deklarować widoczność używając modyfikatorów
private
,protected
ipublic
.var
nie jest dozwolony. - Otwierający nawias klamrowy funkcji powinien znajdować się w linii pod jej deklaracją.
/**
* Dokumentacja
*/
class Foo
{
/**
* Dokumentacja
*/
public function bar()
{
// code
return $value;
}
}
@param
,@var
,@property
i@return
muszą deklarować użyte typybool
,int
,string
,array
lubnull
. Można również używać nazw klas jakModel
lubActiveRecord
.- Dla typowanych tablic należy używać
ClassName[]
. - Pierwsza linia bloku PHPDoc musi opisywać cel istnienia metody.
- Jeśli metoda sprawdza cokolwiek (
isActive
,hasClass
, itp.) pierwsza linia powinna zaczynać się odChecks whether
. @return
powinien wyraźnie opisywać co jest zwracane.
/**
* Checks whether the IP is in subnet range
*
* @param string $ip an IPv4 or IPv6 address
* @param int $cidr the CIDR lendth
* @param string $range subnet in CIDR format e.g. `10.0.0.0/8` or `2001:af::/64`
* @return bool whether the IP is in subnet range
*/
private function inRange($ip, $cidr, $range)
{
// ...
}
- Należy używać
__construct
zamiast konstruktorów w stylu PHP 4.
- Wszystkie typy i wartości PHP powinny być zapisywane małymi literami, łącznie z
true
,false
,null
iarray
.
Zmiana typu istniejącej zmiennej jest uznawana za złą praktykę. Należy unikać pisania kodu w ten sposób, chyba że jest to naprawdę konieczne.
public function save(Transaction $transaction, $argument2 = 100)
{
$transaction = new Connection; // źle
$argument2 = 200; // dobrze
}
- Jeśli łańcuch znaków nie zawiera zmiennych lub pojedynczych cudzysłowów, należy używać pojedynczych cudzysłowów.
$str = 'Like this.';
- Jeśli łańcuch znaków zawiera pojedyncze cudzysłowy, można użyć podwójnych cudzysłowów, aby uniknąć dodatkowego pomijania (znaku ucieczki).
$str1 = "Hello $username!";
$str2 = "Hello {$username}!";
Poniższy zapis jest niedozwolony:
$str3 = "Hello ${username}!";
Należy dodać spacje przed i po kropce podczas łączenia łańcuchów:
$name = 'Yii' . ' Framework';
W przypadku długich łańcuchów format jest następujący:
$sql = "SELECT *"
. "FROM `post` "
. "WHERE `id` = 121 ";
W przypadku tablic używamy krótkiej składni PHP 5.4.
- Nie należy używać ujemnych liczb jako indeksów tablicy.
Należy używać następującego formatu podczas deklarowania tablicy:
$arr = [3, 14, 15, 'Yii', 'Framework'];
W przypadku, gdy ilość elementów jest zbyt duża dla pojedynczej linii:
$arr = [
3, 14, 15,
92, 6, $test,
'Yii', 'Framework',
];
Należy używać następującego formatu podczas deklarowania tablicy asocjacyjnej:
$config = [
'name' => 'Yii',
'options' => ['usePHP' => true],
];
- 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.
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.
$result = $this->getResult();
if (empty($result)) {
return true;
} else {
// przetwarzanie wyniku
}
wygląda lepiej w postaci
$result = $this->getResult();
if (empty($result)) {
return true;
}
// przetwarzanie wyniku
Należy używać następującego formatu dla instrukcji switch:
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;
}
doIt(2, 3);
doIt(['a' => 'b']);
doIt('a', [
'a' => 'b',
'c' => 'd',
]);
Należy zwrócić uwagę na spację pomiędzy słowem function
/use
a otwierającym nawiasem:
// 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;
});
-
Należy stosować dokumentację zgodnie ze składnią phpDoc.
-
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 /** * Returns the errors for all attribute or a single attribute. * @param string $attribute attribute name. Use `null` to retrieve errors for all attributes. * @property array An array of errors for all attributes. Empty array is returned if no error. * The result is a two-dimensional array. See [[getErrors()]] for detailed description. * @return array errors for all attributes or the specified attribute. Empty array is returned if no error. * Note that when returning errors for all attributes, the result is a two-dimensional array, like the following: * ... */ public function getErrors($attribute = null)
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
/**
* Component is the base class that provides the *property*, *event* and *behavior* features.
*
* @include @yii/docs/base-Component.md
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Component extends \yii\base\BaseObject
/**
* 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];
}
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ścicanSetProperty
w tej samej klasie.[[Component::canSetProperty]]
utworzy link do metodycanSetProperty
w klasieComponent
w tej samej przestrzeni nazw.[[yii\base\Component::canSetProperty]]
utworzy link do metodycanSetProperty
w klasieComponent
w przestrzeni nazwyii\base
.[[Component]]
utworzy link do klasyComponent
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:
[link to guide](guide:file-name.md)
[link to guide](guide:file-name.md#subsection)
- Komentarze jednolinijkowe powinny zaczynać się od
//
a nie od#
. - Komentarze jednolinijkowe powinny znajdować się w osobnej linii.
Należy używać empty()
, kiedy jest to możliwe.
Należy powracać (return) wcześnie, kiedy tylko instrukcje warunkowe zaczynają się zagnieżdżać. Nie ma to znaczenia w przypadku krótkich metod.
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.
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.
- 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