Nette Documentation Preview

syntax
Nette Coding Standard
*********************

.[perex]
Chcete, aby váš PHP kód dodržoval [Nette coding standard |contributing:coding-standard], a přitom sami nehlídat tabulátory, závorky a prázdné řádky? [DressCode |https://dresscode.run] za vás projde každý soubor a co najde, opraví jediným příkazem.

DressCode je nová generace původního balíčku `nette/coding-standard`. Nette coding standard v něm najdete vestavěný pod jménem `nette`. Mění jen to, co standard porušuje, a zbytek souboru nechá přesně tak, jak byl, takže v diffu po opravě najdete opravy a nic jiného.


Instalace
=========

DressCode nainstalujte globálně pomocí Composeru:

```shell
composer global require dresscode/dresscode
```

a ujistěte se, že váš globální adresář `vendor/bin` je v [proměnné prostředí $PATH |https://getcomposer.org/doc/03-cli.md#global].

Samotný DressCode běží na PHP 8.4 až 8.6. To je ale PHP nástroje, ne PHP, pro které píšete kód: váš projekt může cílit na kteroukoliv verzi od PHP 8.0. DressCode ji vyčte z položky `php` v sekci `require` souboru `composer.json` vašeho projektu a nikdy nenapíše syntaxi, kterou tahle verze nezná.


Konfigurace
===========

DressCode nemá žádný vlastní styl, takže mu nejdřív řeknete, jaký standard váš projekt dodržuje. Do kořene projektu vložte soubor `dresscode.neon`:

```neon
use:
	- nette

paths:
	- app
	- tests
```

Klíč `use` vybírá standard, `paths` vyjmenovává adresáře ke kontrole. Soubor commitněte, ať kód kontroluje stejně celý tým i vaše CI.


Použití
=======

Vyzkoušíme to na třídě napsané ve spěchu, `app/Model/CartService.php`, odsazené mezerami a se závorkami na špatných řádcích:

```php
<?php

declare(strict_types=1);

namespace App\Model;

class CartService {
    public function getTotal(array $items): float {
        $total = 0;
        foreach ($items as $item) {
            $total = $total + $item['price'] * $item['quantity'];
        }
        return $total;
    }
}
```

Příkaz `check` vypíše, co standard porušuje, a nic nemění:

```shell
dresscode check
```

/--pre .[terminal]
app/Model/CartService.php
  error      1  `declare(strict_types=1)` must be on the line of the opening tag.                          file.strictTypes.position
  error      2  Expected 1 blank line before the namespace, 2 found.                                       blankLines.beforeNamespace
  error      6  Expected 2 blank lines before the class, 1 found.                                          blankLines.beforeDeclaration
  error   7:19  Expected a line break before the opening brace.                                            braces.position.class
  error      8  Expected the member indented by 1 tab, 4 spaces found.                                     indentation.unit
                Then also, on lines 9, 10, 13: Expected the statement indented by 2 tabs, 8 spaces found.  indentation.unit
                Then also, on line 11: Expected the statement indented by 3 tabs, 12 spaces found.         indentation.unit
                Then also, on line 12: Expected the closing brace indented by 2 tabs, 8 spaces found.      indentation.unit
                Then also, on line 14: Expected the closing brace indented by 1 tab, 4 spaces found.       indentation.unit
  error   8:51  Expected a line break before the opening brace.                                            braces.position.function
  error  11:13  The assignment must be written `+=` instead of repeating its target.                       expressions.assignment.targetInValue

FOUND  13 violations, 6 of them following from others, a fix leaves none in 1 file
\--

U každého nálezu je řádek (a sloupec), popis chyby a na konci jméno nastavení, které porušuje, třeba `braces.position.class`. To jméno budete potřebovat, až budete chtít standard upravit. Řádky začínající `Then also` patří k nálezu nad nimi, jsou to jeho důsledky. Příkaz `fix` pak opraví všechno, co jde:

```shell
dresscode fix
```

A třída teď vypadá takhle:

```php
<?php declare(strict_types=1);

namespace App\Model;


class CartService
{
	public function getTotal(array $items): float
	{
		$total = 0;
		foreach ($items as $item) {
			$total += $item['price'] * $item['quantity'];
		}
		return $total;
	}
}
```

Než poprvé spustíte `fix`, zazálohujte si soubory, nebo ho pusťte nad čistým pracovním stromem, ať můžete změny potom projít přes `git diff`.


Úprava standardu
================

Každé nastavení standardu je klíčem konfigurace a poslední slovo u každého z nich má váš `dresscode.neon`. Řekněme, že váš projekt chce mezi metodami jeden prázdný řádek místo dvou a nechce, aby se `==` přepisovalo na `===`:

```neon
blankLines:
	aroundMethods: 1

expressions:
	comparison:
		loose: keep
```

Hodnota `keep` znamená "nech to tak, jak to má kód". K čemu klíč slouží a jakou hodnotu má ve vašem projektu, vypíše `dresscode explain blankLines.aroundMethods`. A když má jeden řádek dobrý důvod standard porušit, připište k němu komentář `// dresscode:ignore`.


Novější PHP a Nette
===================

DressCode umí víc než formátovat. Přidejte vedle standardu sadu `modernizations` a přepíše kód na to, co nabízí novější PHP, třeba `$user === null ? null : $user->getName()` na `$user?->getName()`. Jde přitom jen tak daleko, jak dovolí váš `composer.json`:

```neon
use:
	- nette
	- modernizations
```

Když aktualizujete knihovny Nette, balíček `dresscode/upgrade-nette` přepíše váš kód na jejich nové API, viz [Upgrade Nette |https://dresscode.run/cs/upgrading-nette].


Continuous Integration
======================

V CI nainstalujte DressCode jako samostatný projekt, ať máte pod kontrolou, která verze poběží:

```yaml
- run: composer create-project dresscode/dresscode temp/dresscode ^1
- run: php temp/dresscode/bin/dresscode check
```

Když `check` najde prohřešek, skončí s kódem `1` a build selže. V GitHub Actions se nálezy zobrazí jako anotace přímo v pull requestu.


Přechod z verze 3
=================

Původní balíček `nette/coding-standard` kontroloval standard pomocí PHP CS Fixeru a PHP CodeSnifferu, přes příkaz `ecs` a soubory `ncs.php` a `ncs.xml`. Jeho vývoj skončil, nahradil ho DressCode, a verze 3 je poslední. Při přechodu vytvořte `dresscode.neon` podle návodu výše, úpravy, které jste měli v `ncs.php` a `ncs.xml`, zapište jako jeho klíče a oba soubory smažte. Všechny klíče i s hodnotami, které mají ve vašem projektu, vypíše `dresscode config`.

První `dresscode fix` nejspíš sáhne na víc souborů, než čekáte, protože DressCode opravuje i některá místa, která verze 3 nechávala být. Udělejte z něj samostatný commit bez dalších změn.

Všechno ostatní, od všech nastavení až po spouštění DressCode v editoru nebo po každé úpravě, kterou udělá AI agent, najdete v [manuálu DressCode |https://dresscode.run/cs/].

{{maintitle: Nette Coding Standard: kontrola a oprava PHP kódu s DressCode}}
{{description: Nechte DressCode hlídat, aby váš PHP kód dodržoval Nette coding standard: zkontroluje každý soubor a jedním příkazem opraví, co najde, lokálně i v CI.}}

Nette Coding Standard

Chcete, aby váš PHP kód dodržoval Nette coding standard, a přitom sami nehlídat tabulátory, závorky a prázdné řádky? DressCode za vás projde každý soubor a co najde, opraví jediným příkazem.

DressCode je nová generace původního balíčku nette/coding-standard. Nette coding standard v něm najdete vestavěný pod jménem nette. Mění jen to, co standard porušuje, a zbytek souboru nechá přesně tak, jak byl, takže v diffu po opravě najdete opravy a nic jiného.

Instalace

DressCode nainstalujte globálně pomocí Composeru:

composer global require dresscode/dresscode

a ujistěte se, že váš globální adresář vendor/bin je v proměnné prostředí $PATH.

Samotný DressCode běží na PHP 8.4 až 8.6. To je ale PHP nástroje, ne PHP, pro které píšete kód: váš projekt může cílit na kteroukoliv verzi od PHP 8.0. DressCode ji vyčte z položky php v sekci require souboru composer.json vašeho projektu a nikdy nenapíše syntaxi, kterou tahle verze nezná.

Konfigurace

DressCode nemá žádný vlastní styl, takže mu nejdřív řeknete, jaký standard váš projekt dodržuje. Do kořene projektu vložte soubor dresscode.neon:

use:
	- nette

paths:
	- app
	- tests

Klíč use vybírá standard, paths vyjmenovává adresáře ke kontrole. Soubor commitněte, ať kód kontroluje stejně celý tým i vaše CI.

Použití

Vyzkoušíme to na třídě napsané ve spěchu, app/Model/CartService.php, odsazené mezerami a se závorkami na špatných řádcích:

<?php

declare(strict_types=1);

namespace App\Model;

class CartService {
    public function getTotal(array $items): float {
        $total = 0;
        foreach ($items as $item) {
            $total = $total + $item['price'] * $item['quantity'];
        }
        return $total;
    }
}

Příkaz check vypíše, co standard porušuje, a nic nemění:

dresscode check
app/Model/CartService.php
  error      1  `declare(strict_types=1)` must be on the line of the opening tag.                          file.strictTypes.position
  error      2  Expected 1 blank line before the namespace, 2 found.                                       blankLines.beforeNamespace
  error      6  Expected 2 blank lines before the class, 1 found.                                          blankLines.beforeDeclaration
  error   7:19  Expected a line break before the opening brace.                                            braces.position.class
  error      8  Expected the member indented by 1 tab, 4 spaces found.                                     indentation.unit
                Then also, on lines 9, 10, 13: Expected the statement indented by 2 tabs, 8 spaces found.  indentation.unit
                Then also, on line 11: Expected the statement indented by 3 tabs, 12 spaces found.         indentation.unit
                Then also, on line 12: Expected the closing brace indented by 2 tabs, 8 spaces found.      indentation.unit
                Then also, on line 14: Expected the closing brace indented by 1 tab, 4 spaces found.       indentation.unit
  error   8:51  Expected a line break before the opening brace.                                            braces.position.function
  error  11:13  The assignment must be written `+=` instead of repeating its target.                       expressions.assignment.targetInValue

FOUND  13 violations, 6 of them following from others, a fix leaves none in 1 file

U každého nálezu je řádek (a sloupec), popis chyby a na konci jméno nastavení, které porušuje, třeba braces.position.class. To jméno budete potřebovat, až budete chtít standard upravit. Řádky začínající Then also patří k nálezu nad nimi, jsou to jeho důsledky. Příkaz fix pak opraví všechno, co jde:

dresscode fix

A třída teď vypadá takhle:

<?php declare(strict_types=1);

namespace App\Model;


class CartService
{
	public function getTotal(array $items): float
	{
		$total = 0;
		foreach ($items as $item) {
			$total += $item['price'] * $item['quantity'];
		}
		return $total;
	}
}

Než poprvé spustíte fix, zazálohujte si soubory, nebo ho pusťte nad čistým pracovním stromem, ať můžete změny potom projít přes git diff.

Úprava standardu

Každé nastavení standardu je klíčem konfigurace a poslední slovo u každého z nich má váš dresscode.neon. Řekněme, že váš projekt chce mezi metodami jeden prázdný řádek místo dvou a nechce, aby se == přepisovalo na ===:

blankLines:
	aroundMethods: 1

expressions:
	comparison:
		loose: keep

Hodnota keep znamená „nech to tak, jak to má kód“. K čemu klíč slouží a jakou hodnotu má ve vašem projektu, vypíše dresscode explain blankLines.aroundMethods. A když má jeden řádek dobrý důvod standard porušit, připište k němu komentář // dresscode:ignore.

Novější PHP a Nette

DressCode umí víc než formátovat. Přidejte vedle standardu sadu modernizations a přepíše kód na to, co nabízí novější PHP, třeba $user === null ? null : $user->getName() na $user?->getName(). Jde přitom jen tak daleko, jak dovolí váš composer.json:

use:
	- nette
	- modernizations

Když aktualizujete knihovny Nette, balíček dresscode/upgrade-nette přepíše váš kód na jejich nové API, viz Upgrade Nette.

Continuous Integration

V CI nainstalujte DressCode jako samostatný projekt, ať máte pod kontrolou, která verze poběží:

- run: composer create-project dresscode/dresscode temp/dresscode ^1
- run: php temp/dresscode/bin/dresscode check

Když check najde prohřešek, skončí s kódem 1 a build selže. V GitHub Actions se nálezy zobrazí jako anotace přímo v pull requestu.

Přechod z verze 3

Původní balíček nette/coding-standard kontroloval standard pomocí PHP CS Fixeru a PHP CodeSnifferu, přes příkaz ecs a soubory ncs.php a ncs.xml. Jeho vývoj skončil, nahradil ho DressCode, a verze 3 je poslední. Při přechodu vytvořte dresscode.neon podle návodu výše, úpravy, které jste měli v ncs.php a ncs.xml, zapište jako jeho klíče a oba soubory smažte. Všechny klíče i s hodnotami, které mají ve vašem projektu, vypíše dresscode config.

První dresscode fix nejspíš sáhne na víc souborů, než čekáte, protože DressCode opravuje i některá místa, která verze 3 nechávala být. Udělejte z něj samostatný commit bez dalších změn.

Všechno ostatní, od všech nastavení až po spouštění DressCode v editoru nebo po každé úpravě, kterou udělá AI agent, najdete v manuálu DressCode.