Výpis z databáze v komponentě

Lebow
Člen | 9
+
0
-

Ahoj,
jsem v Nette úplný začátečník a rád bych si vytvořil něco jako „blog“. Začal jsem tím, že bych si z DB rád vypsal kategorie. Pokud to spravne chapu, tak bych si je mel nacitat v MenuControl, problem je v tom, ze nevim, jak pristoupit k DB v MenuControler(jak si do MenuControler přenést aktuální připojení z BaseManager, kdyz z něj nedědí). Na netu je hodně příkladů na Nette, ale na komponenty jich je pár :(

Neporadil by někdo?

Díky

v /app/components/MenuControl/MenuControl.php

<?php

use Nette\Application\UI;


class MenuControl extends UI\Control
{
    public function render(){
        $this->template->setFile(__DIR__ . '/menu.latte');
        $this->template->render();
    }

    public function GetCategories(){
        //tady jsem si z db chtel nacist kategorie
		//neco jako 'Select * name from category'
    }
}

\app\presenters\MenuPresenter.php

<?php

namespace App\Presenters;

class MenuPresenter extends \Nette\Application\UI\Presenter {

    protected function createComponentMenu() {
        $control = new \MenuControl();
        return $control;
    }

    public function render(){
        $control = $this->getComponent('Menu');
    }
}

\app\BasePresenter.php

<?php

namespace App\Presenters;

use Nette;
use App\Model;


abstract class BasePresenter extends Nette\Application\UI\Presenter
{
    public function createComponentMenuControl($name) {
        $menu = new \MenuControl($this, $name);
        return $menu;
    }
}

\app\model\BaseManager.php

<?php
namespace App\Model;

use Nette\Database\Context;
use Nette\Object;

class BaseManager extends Object {

    protected $database;

    public function __construct(Context $database) {
        $this->database = $database;
    }

}
Jan Mikeš
Člen | 771
+
+4
-

@igor.pocta @Lebow MenuControl určitě jako service neregistruj, je to blbost!

Vytvoř si továrničku, tak jak psal @CZechBoY https://doc.nette.org/…n/components#….

Máš 2 možnosti, a) generovaná továrnička, b) vytvoříš si vlastní

Komponenta vyžaduje závislost v constructoru (nestaráš se o to jak ji dostane, to je kouzlo DI), pokud ji vytváříš přes create: (tento kód je společný pro ab)

class MenuControl {
	__construct(BaseManager $manager) {
		$this->manager = $manager;
	}
}

Mohl by jsi také využít injectu ale to ti nedoporučuji pokud nevíš ještě co děláš.

a) generovaná továrnička
Samotná factory

interface IMenuControlFactory {
	/** @return MenuControl */
	public function create();
}

Tu zaregistruješ do configu

services:
	- IMenuControlFactory

b) vlastní továrnička, postup je vlastně úplně stejný, jen vyměníš interface IMenuControlFactory za implementaci (je to víc psaní, v tomto případě pokud k tomu nemáš speciální důvod doporučuji a):

class MenuControlFactory {
	private $baseManager;

	public function __construct(BaseManager $baseManager)
	{
		$this->baseManager = $baseManager;
	}

	public function create()
	{
		return new MenuControl($baseManager);
	}
}
services:
	- MenuControlFactory

Potom v presenteru komponentu vytvoříš takto:

class MyPresenter extends BasePresenter {
	// PRO a)
	/** @var IMenuControlFactory @inject */
	public $menuFactory;

	// PRO b)
	/** @var MenuControlFactory @inject */
	public $menuFactory;


	protected function createComponentMenuControl()
	{
		return $this->menuFactory->create();
	}
}

Vlastně jsem přepsal celý článek v kostce sem :D, prosím pročti si to a spíše se ptej na konkrétní věci které ti nejsou jasné

filsedla
Člen | 101
+
-5
-

A nebo použij možnost c), kterou používám já, protože hrozně nerad píšu cokoliv navíc.

// stejně jako výše:
class MenuControl {
    __construct(BaseManager $manager) {
        $this->manager = $manager;
    }
}
class MyPresenter extends BasePresenter {
    // nic

    protected function createComponentMenuControl()
    {
        return $this->context->createInstance(MenuControl::class);
    }
}

A nic dalšího není potřeba.

CZechBoY
Člen | 3608
+
+1
-

@filsedla no fuj, používej aspoň prototypovací @inject anotaci když už se ti nechce psát.

filsedla
Člen | 101
+
0
-

CZechBoY napsal(a):

@filsedla no fuj, používej aspoň prototypovací @inject anotaci když už se ti nechce psát.

Jakou myslíš, uvedeš příklad?

CZechBoY
Člen | 3608
+
0
-

přes inject anotaci

class MujPresenter extends Presenter
{
	/** @inject @var Tovarna*/
	public $tovarna;

	protected function createComponentKomponenta()
	{
		return $this->tovarna->create();
	}
}

Nebo Kdyby/Autowired, to dělá možná o trošku míň magie než tvůj kod.

class MujPresenter extends Presenter
{
	use Kdyby\Autowired\AutowireComponentFactories;

	protected function createComponentKomponenta(Tovarna $t)
	{
		return $t->create();
	}
}

Editoval CZechBoY (25. 5. 2017 17:38)

filsedla
Člen | 101
+
0
-

@CZechBoY To je pořád použití třídy továrny. Ríkám, že nemusí být potřeba.

V jakých případech je použití tovární třídy nezbytně potřeba?

Napadá mě akorát případ, kdy by bylo potřeba továrnu ještě před vytvořením komponenty nějak konfigurovat a řídit, co pak vytvoří. Obvykle se to ale nedělá.

CZechBoY
Člen | 3608
+
0
-

@filsedla no ty máš createInstance, což taky vždy vytváří instanci. Nebo mi něco uniká?

filsedla
Člen | 101
+
0
-

Nene, je to přesně tak. To moje je dokonce asi 2× pomalejší, ale nemusí se psát, registrovat ani předávat na místo použití ta továrna.

iNviNho
Člen | 352
+
0
-

@CZechBoY možno offtopic, ale ja som si stále myslel, že poradie anotácií je important.. :DD

<?php
/** @var MyComponent @inject */
public $myComponent;

/** @inject @var MyComponent */
public $myComponent;
?>

sú ekvivalentné zápisy?

Editoval iNviNho (25. 5. 2017 22:47)

CZechBoY
Člen | 3608
+
+1
-

@iNviNho je to jedno, je to jen komentář, kterej může mít klidně 500 zavináčů…
kod k inject property https://api.nette.org/…ion.php.html#…

Editoval CZechBoY (25. 5. 2017 22:58)