Appite – je možné volať controllery z console?

Čamo
Člen | 747
+
0
-

Potreboval by som spustiť nejaký kód v Appite projekte cez konzolu ako cron, ale zdá sa že to nieje úplne jednoduché. Je to možné či nie? skúšal som

php index.php Filters:index

ale toto mi neprejde. Pričom Filters je controller a index je metoda. Píše mi „No matched route by given URL“.

Díky za radu.

Editoval Čamo (1. 2. 16:50)

dakur
Člen | 351
+
+7
-

Apitte neznám, na to odpovědět neumím. Zavání mi to ale anti-patternem. Pokud ten presenter obsahuje nějakou logiku, kterou potřebuješ provést, pak by ta logika neměla být v presenteru, ale v modelu, ne? Potom bys nemusel volat presenter, ale přímo service z modelu, s čímž není problém.

Editoval dakur (15. 12. 2021 16:47)

Felix
Nette Core | 1161
+
+3
-

Volat controllery z console jsem nikdy nepotreboval. Neslo by vyclenit logiku z controlleru do tridy, kterou by jsi pouzil i v consoli?

Čamo
Člen | 747
+
0
-

Zdravím, Prepáčte úplne som zabudol na toto vlákno.
Nejak nechápem ako by som vola tú logiku v tej modelovej triede. Ja neviem presne ako funguje inicializácia toho frameworku ale v routery by to tak či tak narazilo nie?

Pavel Janda
Člen | 969
+
0
-

Můžeš to zkusit přes CURL :)

Ale jinak souhlasím s @Felix a @dakur

Co přesně chceš, aby se stalo po tom, co zavoláš tu routu?

Editoval Pavel Janda (31. 1. 12:30)

dakur
Člen | 351
+
+7
-

@Čamo Řekněme, že chceš přidávat uživatele, a to dvojím způsobem – jednak normálně v UI na adrese /users/add, anebo zavoláním php skript.php users:add username

Presentery, resp. celé nette/application, pokrývají ten první přístup. Zjednodušeně řečeno to funguje takto:

  • vezmi request (tj. /users/add)
  • najdi, jestli k tomu v routeru něco sedí
  • pokud ano, přelož to na název presenter a metodu (např. Users:add)
  • spusť tuto action v daném presenteru
  • presenter pak zavolá něco v modelu, co reálně toho uživatele vytvoří (např. nějakou metodu UsersModel#add($username)

Při spuštění přes command line chceš z tohoto seznamu zachovat jen tu poslední odrážku, všeho ostatní je zbytečné, protože nemáme žádný request. Zato máme vstupní parametery – users:addusername

Tam tedy bude probíhat něco podobného:

  • najdi obsluhu pro users:add
  • spusť ji s danými parametry (username)
  • obsluha pak opět zavolá UsersModel#create($username)

Obsluze se říká command a s jejich registrací ti pomůže např. https://componette.org/…tte/console/ Je to takové nette/application pro CLI. Takže v execute() metodě daného commandu (viz docs) můžeš volat svůj model, který si předtím normálně vytáhneš z DI.

Editoval dakur (1. 2. 11:04)

Felix
Nette Core | 1161
+
0
-

@Čamo Amen 🙏

Čamo
Člen | 747
+
0
-

Dýky moc, ale ak teda budem volať nejakú modelovú triedu tak asi nemôžem čakať že mi to nainjektuje závislosti z configu že? Čiže budem musieť vytvoriť špeciálne model pre túto consolovú akciu ano?

jiri.pudil
Nette Blogger | 1008
+
+1
-

(…) tak asi nemôžem čakať že mi to nainjektuje závislosti z configu že?

Ale ano, zaregistruj si command jako kteroukoliv jinou službu, pak si všechny závislosti můžeš vyžádat standardně v konstruktoru.

dakur
Člen | 351
+
+2
-

Čiže budem musieť vytvoriť špeciálne model pre túto consolovú akciu ano?

@Čamo Ne, modelovou třídu máš jen jednu a používáš ji na více místech (presenter, command). Příkladná modelová třída:

namespace MyApp;

class UsersModel
{
	private DbHandler $db;
	public function __construct(DbHandler $db) // může být Nette\Database, Dibi, EntityManager, cokoliv
	{
		$this->db = $db;
	}

	public function add(string $username): void
	{
		// samotná logika přidávání, práce s DB, např.:
		$this->db->insert(...);
	}
}

Tu máš zaregistrovanou v services:

services:
- MyApp\UsersModel

Potom máš místa, kde tu modelovou třídu používáš. Presenter a command:

namespace MyApp;
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;

class UserPresenter extends Presenter
{
	private UsersModel $model;
	public function __construct(UsersModel $model)
	{
		$this->model = $model;
	}

	public function actionDefault(): void
	{}

	public function createComponentAddUserForm(): Form
	{
		$form = new Form();
		$form->addText('username');
		$form->onSuccess[] = function ($values) {
			$this->model->add($values['username']); // voláme model
		};
    }
}
class AddUserCommand extends Command
{
	private UsersModel $model;
	public function __construct(UsersModel $model)
	{
		$this->model = $model;
	}

	public function configure()
	{
		// ...
	}

	public function execute($input, $output): void
	{
		$username = $input->getArgument('username');
		$this->model->add($username); // voláme model
	}
}

Opět musíš mít obě zaregistrované v DI, jak píše Jirka. Ale presentery jsou (zjednodušeně) registrované automaticky, takže stačí registrovat command:

services:
- MyApp\AddUserCommand

O předání UsersModel už se postará DI container.

Editoval dakur (3. 2. 9:11)