Nette Documentation Preview

syntax
Latte 2'den Latte 3'e geçiş
***************************

.[perex]
Latte 3, tamamen yeniden yazılmış bir derleyiciye ve biçimsel olarak iyi tanımlanmış bir gramere sahiptir. Bunun Latte 2 ile olabildiğince örtüşmesi gerekir, ama küçük düzeltmeler isteyen bazı yapılar vardır.

Pratikte şablonların büyük çoğunluğunun hiçbir değişiklik gerektirmediği ve Latte 3'te de Latte 2'deki gibi çalıştığı ortaya çıkıyor. Peki uyumsuzluklar nasıl saptanır?

**Önce geçiş sürümü Latte 2.11'i kurun.**

Bu sürüm yeni bir özellik getirmez, yalnızca yeni Latte'nin desteklemeyeceğini bildiği durumlar için E_USER_DEPRECATED ile uyarı verir ve daha da önemlisi onları nasıl düzelteceğinizi söyler. Tüm şablonları gözden geçirip uyumlu olup olmadıklarını sınamak için konsoldan çalıştırdığınız [Linter |/develop#Linter] aracını kullanabilirsiniz:

```shell
vendor/bin/latte-lint <path>
```

Olası uyumsuzlukları giderdikten sonra Latte 3.0'a yükseltin. **Ve yeni katı ayrıştırıcının gerçekten tüm şablonları anladığından emin olmak için Linter'ı yeniden çalıştırın.**


API değişiklikleri
==================

API değişiklikleri yalnızca özel etiket eklemeyi ilgilendirir. API'nin geri kalanı 2. sürümdeki gibi kalır; yani şablonları render etme, parametre aktarma, filtre kaydetme aynı şekildedir.

İstisna, artık `addFilter()` metodu kullanılarak [bir sınıf aracılığıyla kaydedilen filtrelerin |/custom-filters#Filters Using the Class] üstlendiği dinamik filtre `Engine::addFilter(null, ...)`'dır. Özgün `Engine::addFilterLoader()` metodu geçici bir çözüm olarak hâlâ vardır, ama kullanımdan kaldırılmıştır.

Özel etiket eklemenin API'si tamamen farklıdır, bu yüzden Latte 2 için tasarlanmış eklentiler onunla çalışmaz. Ayrıca bkz. [#Eklentilerin güncellenmesi].


Sözdizimi değişiklikleri
========================

Değişiklikler şunlardır:

- filtreler parametre ayırıcı olarak virgül kullanır; önceden `|filter: arg : arg` olan artık `|filter: arg, arg`
- `{label foo}...{/label}` etiketi her zaman çifttir, tek olan `{label /}` diye yazılmalıdır
- buna karşılık `{_'text'}` etiketi her zaman tektir, çift olan `{_}...{/}`'nin yerini yeni `{translate}...{/translate}` almıştır
- `{block foo-$var}` gibi sözde dizeler tırnak içinde `{block "foo-$var"}` yazılmalı ya da bileşik parantez eklenmelidir `{block foo-{$var}}`
- bu, nitelikler için de geçerlidir; yani `n:block="foo-$var"` yerine `n:block="foo-{$var}"` kullanın.
- Latte 3'te filtrelerde büyük-küçük harfe duyarlı olmak gerekir
- `{do ...}` veya `{php ...}` etiketi yalnızca ifade içerebilir; herhangi bir PHP kullanmak için [RawPhpExtension |/develop#RawPhpExtension] kaydedin.

Ve birkaç uç durum daha:

- `n:inner-xxx`, `n:tag-xxx` ve `n:ifcontent` nitelikleri void HTML elemanlarında kullanılamaz
- `n:inner-snippet` niteliği inner- olmadan yazılmalıdır
- `</script>` ve `</style>` etiketleri kapatılmalıdır
- sihirli `$iterations` değişkeni kaldırıldı (`$iterator` ile karıştırmayın!)
- `{includeblock file.latte}` etiketini [`{include file.latte with blocks}` |/tags#include] veya [`{import}` |/template-inheritance#Horizontal Reuse] ile değiştirin
- `{include "abc"}`, `"abc"` bir nokta içermedikçe ve bunun bir dosya olduğu açık olmadıkça `{include file "abc"}` diye yazılmalıdır


Eklentilerin güncellenmesi
==========================

Ayrıştırıcının tamamen yeniden yazılmasıyla özel etiket yazma biçimi de tamamen değişti. Latte için oluşturulmuş özel etiketleriniz varsa, onları 3. sürüm için yeniden yazmanız gerekecek; bkz. [dokümantasyon|/custom-tags].

Etiket ekleyen yabancı bir eklenti kullanıyorsanız, yazarın Latte 3 için bir sürüm yayımlamasını beklemeniz gerekecek. `nette/application`, `nette/caching` ve `nette/forms` kütüphaneleri 3.1 sürümünde, ayrıca Texy da güncellendi ve hem Latte 2 hem Latte 3 ile çalışıyor.


nette/application
-----------------

.[note]
Nette'i olağan şekilde kullanırken bu uzantı otomatik ayarlanır ve bir şey değiştirmeye gerek yoktur.

Latte 2 için eski kod:

```php
$latte->onCompile[] = function ($latte) {
	Nette\Bridges\ApplicationLatte\UIMacros::install($latte->getCompiler());
};

$latte->addProvider('uiControl', $control);
$latte->addProvider('uiPresenter', $control->getPresenter());
```

Latte 3 için yeni kod:

```php
$latte->addExtension(new Nette\Bridges\ApplicationLatte\UIExtension($control));
```

UIExtension; `n:href`, `{link}`, `{control}`, `{snippet}` vb. ekler. Snippet etiketleri böylece Latte'nin kendisinden `nette/application` kütüphanesine taşınmış olur. Latte 3'te presenter'ın `templatePrepareFilters()` metodu artık çağrılmaz.


nette/forms
-----------

.[note]
Nette'i olağan şekilde kullanırken bu uzantı otomatik ayarlanır ve bir şey değiştirmeye gerek yoktur.

Latte 2 için eski kod:

```php
$latte->onCompile[] = function ($latte) {
	Nette\Bridges\FormsLatte\FormMacros::install($latte->getCompiler());
};
```

Latte 3 için yeni kod:

```php
$latte->addExtension(new Nette\Bridges\FormsLatte\FormsExtension);
```


nette/caching
-------------

.[note]
Nette'i olağan şekilde kullanırken bu uzantı otomatik ayarlanır ve bir şey değiştirmeye gerek yoktur.

Latte 2 için eski kod:

```php
$latte->onCompile[] = function ($latte) {
	$latte->getCompiler()->addMacro('cache', new Nette\Bridges\CacheLatte\CacheMacro);
};

$latte->addProvider('cacheStorage', $cacheStorage);
```

Latte 3 için yeni kod:

```php
$latte->addExtension(new Nette\Bridges\CacheLatte\CacheExtension($cacheStorage));
```


Tracy
-----

Tracy paneli de artık bir uzantı olarak etkinleştirilir.

Latte 2 için eski kod:

```php
$latte = new Latte\Engine;
Latte\Bridges\Tracy\LattePanel::initialize($latte);
```

Latte 3 için yeni kod:

```php
$latte = new Latte\Engine;
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
```


Çeviriler
---------

TranslatorExtension; `{_'text'}` çeviri etiketlerini, yeni çift `{translate}...{/translate}` etiketini ve `|translate` filtresini ekler.

Latte 2 için eski kod:

```php
$latte->addFilter('translate', [$translator, 'translate']);
```

Latte 3 için yeni kod:

```php
$latte->addExtension(new Latte\Essential\TranslatorExtension($translator));
```

Presenter'larda, `$template->setTranslator($translator)` metoduyla şablona çevirmen ayarlanarak otomatik etkinleştirilir. Bu olmadan çeviri etiketleri erişilebilir olmaz ve uzantıyı elle ya da bir yapılandırma dosyasıyla kaydetmeniz gerekir.


Yapılandırma dosyası
====================

Latte 2'de yeni etiketler [yapılandırma dosyasıyla |application:configuration#Latte şablonları] `latte › macros` bölümünde kaydedilebiliyordu. 3. sürümde bu yolla uzantıların tamamı eklenir:

```neon
latte:
	extensions:
		- App\Templating\LatteExtension
		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
```


Latte için eklenti mi geliştiriyorsunuz?
========================================

Kütüphanenizde Latte'nin her iki sürümü için desteği aynı anda bulundurabilirsiniz. Sürümü saptamak için, `onCompile[]` ve `addMacro()` kullanımını yeni `addExtension()`'dan ayırmak üzere `Latte\Engine::VERSION` sabitini kullanmak en iyisidir:

```php
if (version_compare(Latte\Engine::VERSION, '3', '<')) {
	// Latte 2 hazırlığı
	$this->latte->onCompile[] = function ($latte) {
		$latte->addMacro(/* ... */);
	};
} else {
	// Latte 3 hazırlığı
	$this->latte->addExtension(/* ... */);
}
```

Örnek olarak, Latte 2 için tasarlanmış şu kodu Latte 3 biçimine yeniden yazmayı deneyelim:

```php
// Latte 2 için eski kod
$this->latte->onCompile[] = function (Latte\Engine $latte) {
	$set = new Latte\Macros\MacroSet($latte->getCompiler());
	$set->addMacro('foo', 'echo %escape(MyClass:myFunc(%node.word, %node.array))');
};
```

Latte 3, [uzantılarla|/extending-latte] genişletilir. `foo` etiketini ekleyen önemsiz bir uzantı şöyle görünürdü:

```php
// Latte 3 için yeni kod
class FooExtension extends Latte\Extension
{
	public function getTags(): array
	{
		return [
			'foo' => [FooNode::class, 'create'], // FooNode sınıfını birazdan ekleyeceğiz
		];
	}
}

// kayıt
$this->latte->addExtension(new FooExtension);
```

Yeni derleyici daha sağlamdır, önceki kısayolları içermez, bu yüzden bir makro yazmak biraz daha fazla satır kod ister. Örneğin Latte 2'deki gibi doğrudan bir PHP kodu dizesi aktaramayız, onun yerine bir fonksiyon oluştururuz. Latte 2'de fonksiyonun aşağı yukarı şöyle görüneceğini hatırlayın:

```php
// Latte 2
$set->addMacro('foo', function (Latte\MacroNode $node, Latte\PhpWriter $writer) {
	return $writer->write('echo %escape(MyClass:myFunc(%node.word, %node.array))');
});
```

Yine de Latte 3 buna büyük ölçüde aynı şekilde yaklaşır; yalnızca `MacroNode`'un adı `Latte\Compiler\Tag`, `PhpWriter`'ın adı ise `Latte\Compiler\PrintContext`'tir. Ama en önemlisi, fazladan bir ara adım vardır: fonksiyon doğrudan PHP kodu döndürmez, bir düğüm, yani sonradan AST ağacının parçası olan bir `StatementNode` çocuğu döndürür. Ve bu düğümün, PHP kodunu döndüren bir `print(Latte\Compiler\PrintContext $context): string` metodu vardır:

```php
// Latte 3
class FooNode extends Latte\Compiler\Nodes\StatementNode
{
	public static function create(Latte\Compiler\Tag $tag): self
	{
		$node = new self;
		return $node;
	}

	public function print(Latte\Compiler\PrintContext $context): string
	{
		return $context->format('echo ...'); // PHP kodu döndürür
	}
}
```

Ayrıca `$context->format()` içindeki maskede artık `%node.***` kısaltmaları yoktur; önce [etiketin içeriğini ayrıştırdığınız |/custom-tags#Etiket Ayrıştırma Fonksiyonu] varsayılır. Yani içeriği değişkenlere (alt düğümlere) ayrıştırmak için ayrıştırıcıyı kullanır, sonra da yazdırırız:

```php
use Latte\Compiler\Nodes\Php\Expression\ArrayNode;
use Latte\Compiler\Nodes\Php\ExpressionNode;

class FooNode extends Latte\Compiler\Nodes\StatementNode
{
	public ExpressionNode $subject;
	public ArrayNode $args;

	public static function create(Latte\Compiler\Tag $tag): self
	{
		$node = new self;
		// etiketin içeriğinin ayrıştırılması
		$node->subject = $tag->parser->parseUnquotedStringOrExpression();
		$tag->parser->stream->tryConsume(',');
		$node->args = $tag->parser->parseArguments();
		return $node;
	}

	public function print(Latte\Compiler\PrintContext $context): string
	{
		return $context->format(
			'echo %escape(MyClass:myFunc(%node, %node));',
			$this->subject,
			$this->args,
		);
	}
}
```

Son olarak, [dolaşma |/custom-tags#Alt Node'lar İçin getIterator() Uygulaması] sırasında alt düğümlerin dolaşılabilmesi için `getIterator()` metodunu ekleyeceğiz:

```php
class FooNode extends Latte\Compiler\Nodes\StatementNode
{
	...

	public function &getIterator(): \Generator
	{
		yield $this->subject;
		yield $this->args;
	}
}
```

{{priority: -1}}

Latte 2'den Latte 3'e geçiş

Latte 3, tamamen yeniden yazılmış bir derleyiciye ve biçimsel olarak iyi tanımlanmış bir gramere sahiptir. Bunun Latte 2 ile olabildiğince örtüşmesi gerekir, ama küçük düzeltmeler isteyen bazı yapılar vardır.

Pratikte şablonların büyük çoğunluğunun hiçbir değişiklik gerektirmediği ve Latte 3'te de Latte 2'deki gibi çalıştığı ortaya çıkıyor. Peki uyumsuzluklar nasıl saptanır?

Önce geçiş sürümü Latte 2.11'i kurun.

Bu sürüm yeni bir özellik getirmez, yalnızca yeni Latte'nin desteklemeyeceğini bildiği durumlar için E_USER_DEPRECATED ile uyarı verir ve daha da önemlisi onları nasıl düzelteceğinizi söyler. Tüm şablonları gözden geçirip uyumlu olup olmadıklarını sınamak için konsoldan çalıştırdığınız Linter aracını kullanabilirsiniz:

vendor/bin/latte-lint <path>

Olası uyumsuzlukları giderdikten sonra Latte 3.0'a yükseltin. Ve yeni katı ayrıştırıcının gerçekten tüm şablonları anladığından emin olmak için Linter'ı yeniden çalıştırın.

API değişiklikleri

API değişiklikleri yalnızca özel etiket eklemeyi ilgilendirir. API'nin geri kalanı 2. sürümdeki gibi kalır; yani şablonları render etme, parametre aktarma, filtre kaydetme aynı şekildedir.

İstisna, artık addFilter() metodu kullanılarak bir sınıf aracılığıyla kaydedilen filtrelerin üstlendiği dinamik filtre Engine::addFilter(null, ...)'dır. Özgün Engine::addFilterLoader() metodu geçici bir çözüm olarak hâlâ vardır, ama kullanımdan kaldırılmıştır.

Özel etiket eklemenin API'si tamamen farklıdır, bu yüzden Latte 2 için tasarlanmış eklentiler onunla çalışmaz. Ayrıca bkz. Eklentilerin güncellenmesi.

Sözdizimi değişiklikleri

Değişiklikler şunlardır:

  • filtreler parametre ayırıcı olarak virgül kullanır; önceden |filter: arg : arg olan artık |filter: arg, arg
  • {label foo}...{/label} etiketi her zaman çifttir, tek olan {label /} diye yazılmalıdır
  • buna karşılık {_'text'} etiketi her zaman tektir, çift olan {_}...{/}'nin yerini yeni {translate}...{/translate} almıştır
  • {block foo-$var} gibi sözde dizeler tırnak içinde {block "foo-$var"} yazılmalı ya da bileşik parantez eklenmelidir {block foo-{$var}}
  • bu, nitelikler için de geçerlidir; yani n:block="foo-$var" yerine n:block="foo-{$var}" kullanın.
  • Latte 3'te filtrelerde büyük-küçük harfe duyarlı olmak gerekir
  • {do ...} veya {php ...} etiketi yalnızca ifade içerebilir; herhangi bir PHP kullanmak için RawPhpExtension kaydedin.

Ve birkaç uç durum daha:

  • n:inner-xxx, n:tag-xxx ve n:ifcontent nitelikleri void HTML elemanlarında kullanılamaz
  • n:inner-snippet niteliği inner- olmadan yazılmalıdır
  • </script> ve </style> etiketleri kapatılmalıdır
  • sihirli $iterations değişkeni kaldırıldı ($iterator ile karıştırmayın!)
  • {includeblock file.latte} etiketini {include file.latte with blocks} veya {import} ile değiştirin
  • {include "abc"}, "abc" bir nokta içermedikçe ve bunun bir dosya olduğu açık olmadıkça {include file "abc"} diye yazılmalıdır

Eklentilerin güncellenmesi

Ayrıştırıcının tamamen yeniden yazılmasıyla özel etiket yazma biçimi de tamamen değişti. Latte için oluşturulmuş özel etiketleriniz varsa, onları 3. sürüm için yeniden yazmanız gerekecek; bkz. dokümantasyon.

Etiket ekleyen yabancı bir eklenti kullanıyorsanız, yazarın Latte 3 için bir sürüm yayımlamasını beklemeniz gerekecek. nette/application, nette/caching ve nette/forms kütüphaneleri 3.1 sürümünde, ayrıca Texy da güncellendi ve hem Latte 2 hem Latte 3 ile çalışıyor.

nette/application

Nette'i olağan şekilde kullanırken bu uzantı otomatik ayarlanır ve bir şey değiştirmeye gerek yoktur.

Latte 2 için eski kod:

$latte->onCompile[] = function ($latte) {
	Nette\Bridges\ApplicationLatte\UIMacros::install($latte->getCompiler());
};

$latte->addProvider('uiControl', $control);
$latte->addProvider('uiPresenter', $control->getPresenter());

Latte 3 için yeni kod:

$latte->addExtension(new Nette\Bridges\ApplicationLatte\UIExtension($control));

UIExtension; n:href, {link}, {control}, {snippet} vb. ekler. Snippet etiketleri böylece Latte'nin kendisinden nette/application kütüphanesine taşınmış olur. Latte 3'te presenter'ın templatePrepareFilters() metodu artık çağrılmaz.

nette/forms

Nette'i olağan şekilde kullanırken bu uzantı otomatik ayarlanır ve bir şey değiştirmeye gerek yoktur.

Latte 2 için eski kod:

$latte->onCompile[] = function ($latte) {
	Nette\Bridges\FormsLatte\FormMacros::install($latte->getCompiler());
};

Latte 3 için yeni kod:

$latte->addExtension(new Nette\Bridges\FormsLatte\FormsExtension);

nette/caching

Nette'i olağan şekilde kullanırken bu uzantı otomatik ayarlanır ve bir şey değiştirmeye gerek yoktur.

Latte 2 için eski kod:

$latte->onCompile[] = function ($latte) {
	$latte->getCompiler()->addMacro('cache', new Nette\Bridges\CacheLatte\CacheMacro);
};

$latte->addProvider('cacheStorage', $cacheStorage);

Latte 3 için yeni kod:

$latte->addExtension(new Nette\Bridges\CacheLatte\CacheExtension($cacheStorage));

Tracy

Tracy paneli de artık bir uzantı olarak etkinleştirilir.

Latte 2 için eski kod:

$latte = new Latte\Engine;
Latte\Bridges\Tracy\LattePanel::initialize($latte);

Latte 3 için yeni kod:

$latte = new Latte\Engine;
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);

Çeviriler

TranslatorExtension; {_'text'} çeviri etiketlerini, yeni çift {translate}...{/translate} etiketini ve |translate filtresini ekler.

Latte 2 için eski kod:

$latte->addFilter('translate', [$translator, 'translate']);

Latte 3 için yeni kod:

$latte->addExtension(new Latte\Essential\TranslatorExtension($translator));

Presenter'larda, $template->setTranslator($translator) metoduyla şablona çevirmen ayarlanarak otomatik etkinleştirilir. Bu olmadan çeviri etiketleri erişilebilir olmaz ve uzantıyı elle ya da bir yapılandırma dosyasıyla kaydetmeniz gerekir.

Yapılandırma dosyası

Latte 2'de yeni etiketler yapılandırma dosyasıyla latte › macros bölümünde kaydedilebiliyordu. 3. sürümde bu yolla uzantıların tamamı eklenir:

latte:
	extensions:
		- App\Templating\LatteExtension
		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)

Latte için eklenti mi geliştiriyorsunuz?

Kütüphanenizde Latte'nin her iki sürümü için desteği aynı anda bulundurabilirsiniz. Sürümü saptamak için, onCompile[] ve addMacro() kullanımını yeni addExtension()'dan ayırmak üzere Latte\Engine::VERSION sabitini kullanmak en iyisidir:

if (version_compare(Latte\Engine::VERSION, '3', '<')) {
	// Latte 2 hazırlığı
	$this->latte->onCompile[] = function ($latte) {
		$latte->addMacro(/* ... */);
	};
} else {
	// Latte 3 hazırlığı
	$this->latte->addExtension(/* ... */);
}

Örnek olarak, Latte 2 için tasarlanmış şu kodu Latte 3 biçimine yeniden yazmayı deneyelim:

// Latte 2 için eski kod
$this->latte->onCompile[] = function (Latte\Engine $latte) {
	$set = new Latte\Macros\MacroSet($latte->getCompiler());
	$set->addMacro('foo', 'echo %escape(MyClass:myFunc(%node.word, %node.array))');
};

Latte 3, uzantılarla genişletilir. foo etiketini ekleyen önemsiz bir uzantı şöyle görünürdü:

// Latte 3 için yeni kod
class FooExtension extends Latte\Extension
{
	public function getTags(): array
	{
		return [
			'foo' => [FooNode::class, 'create'], // FooNode sınıfını birazdan ekleyeceğiz
		];
	}
}

// kayıt
$this->latte->addExtension(new FooExtension);

Yeni derleyici daha sağlamdır, önceki kısayolları içermez, bu yüzden bir makro yazmak biraz daha fazla satır kod ister. Örneğin Latte 2'deki gibi doğrudan bir PHP kodu dizesi aktaramayız, onun yerine bir fonksiyon oluştururuz. Latte 2'de fonksiyonun aşağı yukarı şöyle görüneceğini hatırlayın:

// Latte 2
$set->addMacro('foo', function (Latte\MacroNode $node, Latte\PhpWriter $writer) {
	return $writer->write('echo %escape(MyClass:myFunc(%node.word, %node.array))');
});

Yine de Latte 3 buna büyük ölçüde aynı şekilde yaklaşır; yalnızca MacroNode'un adı Latte\Compiler\Tag, PhpWriter'ın adı ise Latte\Compiler\PrintContext'tir. Ama en önemlisi, fazladan bir ara adım vardır: fonksiyon doğrudan PHP kodu döndürmez, bir düğüm, yani sonradan AST ağacının parçası olan bir StatementNode çocuğu döndürür. Ve bu düğümün, PHP kodunu döndüren bir print(Latte\Compiler\PrintContext $context): string metodu vardır:

// Latte 3
class FooNode extends Latte\Compiler\Nodes\StatementNode
{
	public static function create(Latte\Compiler\Tag $tag): self
	{
		$node = new self;
		return $node;
	}

	public function print(Latte\Compiler\PrintContext $context): string
	{
		return $context->format('echo ...'); // PHP kodu döndürür
	}
}

Ayrıca $context->format() içindeki maskede artık %node.*** kısaltmaları yoktur; önce etiketin içeriğini ayrıştırdığınız varsayılır. Yani içeriği değişkenlere (alt düğümlere) ayrıştırmak için ayrıştırıcıyı kullanır, sonra da yazdırırız:

use Latte\Compiler\Nodes\Php\Expression\ArrayNode;
use Latte\Compiler\Nodes\Php\ExpressionNode;

class FooNode extends Latte\Compiler\Nodes\StatementNode
{
	public ExpressionNode $subject;
	public ArrayNode $args;

	public static function create(Latte\Compiler\Tag $tag): self
	{
		$node = new self;
		// etiketin içeriğinin ayrıştırılması
		$node->subject = $tag->parser->parseUnquotedStringOrExpression();
		$tag->parser->stream->tryConsume(',');
		$node->args = $tag->parser->parseArguments();
		return $node;
	}

	public function print(Latte\Compiler\PrintContext $context): string
	{
		return $context->format(
			'echo %escape(MyClass:myFunc(%node, %node));',
			$this->subject,
			$this->args,
		);
	}
}

Son olarak, dolaşma sırasında alt düğümlerin dolaşılabilmesi için getIterator() metodunu ekleyeceğiz:

class FooNode extends Latte\Compiler\Nodes\StatementNode
{
	...

	public function &getIterator(): \Generator
	{
		yield $this->subject;
		yield $this->args;
	}
}