Problem s beforeRender() .. fatal error

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
matus.krchnik
Člen | 6
+
0
-

Zdravim mam tento problem … chcem vyrenderovat stranky z databazy do @layout pomocou beforeRender lenze nech robim co robim stale mi pise fatal error .. viz:

Fatal Error

Call to a member function table() on a non-object
<?php

namespace App\Presenters;

use Nette,
	App\Model,
	Nette\Application\UI\Presenter;


/**
 * Base presenter for all application presenters.
 */
class BasePresenter extends Presenter
{
	private $database;

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

	function beforeRender()
	{
		$this->template->pages = $this->database->table('pages');
	}

}
David Matějka
Moderator | 6445
+
+1
-

Jelikoz v konkretnim presenteru prekryvas konstruktor a nevolas rodicovsky konstruktor. Do base presenteru injectuj radeji zavislost inject metodou nebo @inject anotaci: https://doc.nette.org/…dependencies

ChocoTUx
Člen | 31
+
0
-

No tam je důležité, jak voláš ten BasePresenter. Tipuji, že tím rozšiřuješ presentery a i tam musíš mít constructor.

class HomepagePresenter extend BasePresenter{

	public function __construct(Nette\Database\Context $database)
    {
        parent::__construct($database);
    }

}

A nechci kecat, ale myslím že presenter někde hluboko má instanci databáze a myslím že přímo $this->database.

David Matějka
Moderator | 6445
+
0
-

@ChocoTUx kecas, nema :P

ChocoTUx
Člen | 31
+
0
-

Ale jednou jsem ho tam zahlédnul :D…
Děkuji za vyjasnění :)

David Matějka napsal(a):

@ChocoTUx kecas, nema :P

matus.krchnik
Člen | 6
+
0
-

dal som to takto a stale pise to co pisalo :/ …

function injectBeforeRender()
	{
		$this->template->pages = $this->database->table('pages');
	}

constructor volam takto

class HomepagePresenter extends BasePresenter
{
	private $database;

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

	public function renderDefault()
	{
		$this->template->posts = $this->database->table('posts')
			->order('created_at DESC')
			->limit(5);

	}

}
dyamon
Člen | 11
+
+1
-

Četl si tu kapitolu o DI?

Jinak to má být takto

<?php

namespace App\Presenters;

use Nette,
    App\Model,
    Nette\Application\UI\Presenter;


/**
 * Base presenter for all application presenters.
 */
class BasePresenter extends Presenter
{
	/**
	* @var Nette\Database\Context $database
	* @inject
	*/
    public $database;

    protected function beforeRender()
    {
        $this->template->pages = $this->database->table('pages');
    }

}
?>

Hláška ti říká, že se snažíš volat metodu table() na prvku který není objekt a to je pro to, že v té proměnné $database nemáš správně předanou referenci.
Jde o to, že pokud si budeš databázi injektovat pomocí konstruktoru v BasePresenteru, budeš muset tuto závislost uvádět v každém potomkovi, který bude přepisovat konstruktor a přidávat další závislosti.

Ten tvůj druhý příklad je úplný nesmysl, zaprvé injectBeforeRender není to co beforeRender a za druhé tam předáváš databázi v potomkovi do private proměnné, kterou deklaruješ právě až v potomkovi, takže bázová třída ve které chceš mít implementovaný beforeRender na tu proměnnou nevidí.

Editoval dyamon (26. 5. 2015 12:48)