Pomoc začátečníkovi: chyba Call to a member function getElements() on a non-object

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

Dobrý den,
začal jsem s Nette před pár dny a nevím si rady. Vyskakuje na mě chyba „Call to a member function getElements() on a non-object“. Mám verzi nette 0.9 s Namespace. Snažím se podle ní rozchodit variaci na řešení, které David Grudl uvedl na PHPFashion pod názvem MVC paradox a jak jej řešit. Mým cílem je vytáhnout z db obsah tabulky a předat ho šabloně jako pole, se kterým si pohraji s pomocí Foreach.
Byl by někdo tak laskav a našel mi chybu? Díky předem…

PrintScreen Chyby na imageshack

Dále přikládám mé zdrojové kódy:

models/Elements.php

<?php

class Elements
{
	function getElements()
	{
		return dibi::dataSource('Select * FROM [Elements]');
	}

}
?>

presenters/DiskuzePresenter.php

<?php
class DiskuzePresenter extends BasePresenter
{
	private $elements = NULL;

	Public function renderDefault($page)
	{
		$this->elements->getElements();
		$this->elements->where('Index=%b', True);
		$this->template->xelements = $elements;
	}
	Public Function showDefault()
	{

	}
	Public function getElements()
	{
		if (!isset($this->elements))
			$this->elements = new Elements();
			return $this->elements;
	}

}
?>

templates/Diskuze/default.phtml

{block content}
{foreach $xelements->select(array('Typ', 'Nazev', 'Hodnota', 'Top', 'Left', 'V', 'S', 'T_P)) as $element}
Tady to jsem ještě nedodělal, ale kdyby to pracovalo správně, tak by to mělo vypsat tento text x-krát pod sebe...
{/foreach}
CZechBoY
Člen | 3608
+
0
-

nechápu jak můžeš z proměnný, která je null něco dostat..
že by chyběl nějaký soubor k přiložení?

bostiko
Člen | 10
+
0
-

CZechBoY napsal(a):

nechápu jak můžeš z proměnný, která je null něco dostat..
že by chyběl nějaký soubor k přiložení?

  1. to jsem našel v podobném příkladu a má to nulový efekt. Tu samou chybu to hlásí ať je tam, nebo to zakomentuji.
  2. Nic by podle mého chybět nemělo, ale já odborník nejsem…
CZechBoY
Člen | 3608
+
0
-
<?php
                $this->elements->getElements();
                $this->elements->where('Index=%b', True);
                $this->template->xelements = $elements;
?>

zkus změnit na

<?php
                $this->elements->where('Index=%b', True);
                $this->template->xelements = $this->elements;
?>

Editoval CZechBoY (23. 6. 2011 21:41)

bostiko
Člen | 10
+
0
-

CZechBoY napsal(a):

<?php
                $this->elements->getElements();
                $this->elements->where('Index=%b', True);
                $this->template->xelements = $elements;
?>

zkus změnit na

<?php
                $this->elements->where('Index=%b', True);
                $this->template->xelements = $this->elements;
?>

V tomto případě to hlásí chybu Call to a member function where() on a non-object, což je ve výsledku to samé…

smasty
Člen | 90
+
0
-

Problém je v tom, že Nette\Object properties nefungujú z vnútra objektu. Nahraď volanie $this->elements za $this->getElements() a všetko bude v poriadku.

bostiko
Člen | 10
+
0
-

smasty napsal(a):

Problém je v tom, že Nette\Object properties nefungujú z vnútra objektu. Nahraď volanie $this->elements za $this->getElements() a všetko bude v poriadku.

Krapet jsem to nepochopil. Který řádek mám přepsat tímto? Zkoušel jsem všechno možné ale nefunguje to. Dokonce se mi to nádherně zacyklilo…

Aurielle
Člen | 1281
+
0
-

Jakýkoliv výskyt $this->elements nahraď za $this->getElements().

22
Člen | 1478
+
0
-

myslím, že mít metodu getElements() a proměnnou $this->elements je teda špatnej nápad, protože díky Nette\Object se při $this->elements volá getElements(). Jedno z toho bych přejmenoval.

bostiko
Člen | 10
+
0
-

22 napsal(a):

myslím, že mít metodu getElements() a proměnnou $this->elements je teda špatnej nápad, protože díky Nette\Object se při $this->elements volá getElements(). Jedno z toho bych přejmenoval.

Zkoušel jsem to, a nepomohlo to.

gmvasek napsal(a):

Jakýkoliv výskyt $this->elements nahraď za $this->getElements().

udělal jsem to, a hlásí to, že:
Can't use method return value in write context
a hlásí to řádek:
$this->getElements()->where(‚Index=%b‘, True);
případně, pokud to zakomentuji, tak to hlásí tento:
if (!isset($this->getElements()))

Pokud se vám už se mnou nechce otravovat, šlo by případně místo mého způsobu to udělat nějakým jiným způsobem? Nějakým jednodušším, ale abych zároveň využíval MVP?

bostiko
Člen | 10
+
0
-

Jinak řečeno, pokud mi řeknete, že na to jdu pro začátek moc složitě, tak to smažu a začnu od znova jinou metodou…

22
Člen | 1478
+
0
-
<?php
final class DiskuzePresenter extends BasePresenter
{
        private $element = NULL;

        public function renderDefault($page)
        {
                $data = $this->model->getElements();
                $data = $data->where('Index=%b', True);
                $this->template->xelements = $data;
        }
        public Function showDefault()
        {

        }
        public function getModel()
        {
                if (!isset($this->element)) {
                        $this->element = new Elements();
		}
		return $this->element;
        }
}
?>

Editoval 22 (23. 6. 2011 22:50)

uestla
Backer | 799
+
0
-

Ahoj!

Zkus nejprve přepsat

private $elements = NULL;

na

/** @var DibiDataSource */
private $elementsSource = NULL;

Hned potom uprav metodu getElements():

if ($this->elements === NULL) {
	$els = new Elements();
	$this->elements = $els->getElements();
}

return $this->elements;

Následně ještě uprav metodu renderDefault():

$this->elements->where('Index = %b', TRUE);
$this->template->xelements = $this->elements;

A nakonec se s námi poděl o tom, jak to dopadlo.

PS: Nepiš prosím počáteční písmenka u klíčových slov jazyka velká, působí to odpudivě ;-)

bostiko
Člen | 10
+
0
-

uestla napsal(a):

Ahoj!

Zkus nejprve přepsat

private $elements = NULL;

na

/** @var DibiDataSource */
private $elementsSource = NULL;

Hned potom uprav metodu getElements():

if ($this->elements === NULL) {
	$els = new Elements();
	$this->elements = $els->getElements();
}

return $this->elements;

Následně ještě uprav metodu renderDefault():

$this->elements->where('Index = %b', TRUE);
$this->template->xelements = $this->elements;

A nakonec se s námi poděl o tom, jak to dopadlo.

PS: Nepiš prosím počáteční písmenka u klíčových slov jazyka velká, působí to odpudivě ;-)

Tento způsob nefunguje.

22 napsal(a):

<?php
final class DiskuzePresenter extends BasePresenter
{
        private $element = NULL;

        public function renderDefault($page)
        {
                $data = $this->model->getElements();
                $data = $data->where('Index=%b', True);
                $this->template->xelements = $data;
        }
        public Function showDefault()
        {

        }
        public function getModel()
        {
                if (!isset($this->element)) {
                        $this->element = new Elements();
		}
		return $this->element;
        }
}
?>

Ale tento ano.

Děkuji všem za pomoc a trpělivost.

Poslední věc. Nevíte, proč mi poté nefunguje latte? Když se to spustí, stránka generuje:
{foreach $xelements->select(array(‚Typ‘, ‚Nazev‘, ‚Hodnota‘, ‚Top‘, ‚Left‘, ‚V‘, ‚S‘, 'T_P)) as $element} Text {/foreach}

22
Člen | 1478
+
0
-

vyfiltruj si to v presenteru a do šablony si pošli už hotové pole..

uestla
Backer | 799
+
0
-

Tento způsob nefunguje.

Máš pravdu, správně měla být metoda getElements() přepsána takto:

if ($this->elementsSource === NULL) {
        $model = new Elements();
        $this->elementsSource = $model->getElements();
}

return $this->elementsSource;

Pardon!

Proč ti nefunguje Latte netuším, chce to více detailů :-)

bostiko
Člen | 10
+
0
-

na to latte už jsem přišel, chybí mi tam na konci jednna uvozovka…

uestla
Backer | 799
+
0
-

Ajo :-D

Tak té jsem si nevšiml – to je tak, když tu lidé nezvýrazňují kód ;-)

Přitom na to je tlačítko :-(

Kdybys to udělal, přišel bys na to hned, koukej:

{foreach $xelements->select(array('Typ', 'Nazev', 'Hodnota', 'Top', 'Left', 'V', 'S', 'T_P)) as $element}
Text
{/foreach}
bostiko
Člen | 10
+
0
-

Měl bych ještě jeden poslední dotaz:
Celou aplikace jsem překopal do verze 2.O Beta. Použil jsem ve výsledku ten samý kus kódu pro celý proces zisku elementů na stránce. Nyní mi laděnka píše, že vykonává následující SQL dotaz dvakrát.
Oproti původnímu návrhu jsem jen trochu změnil strukturu tabulek v modelu, abych mohl tahat elementy do různých prezenterů stejným modelem (změnou sql v modelu). To by ale nemělo mít vliv.

SELECT `Typ`, `Nazev`, `Hodnota`, `Top`, `Left`, `V`, `S`
FROM (
select *
from `position` natural join `elements`) t
WHERE (`location`='index')
bostiko
Člen | 10
+
0
-

Vše vyřešeno…
měl jsem chybu v latte. 2krát jsem prováděl to latte z původního pžíspěvku…

Díky všem…