quickStart tutor. – Objekt nelze pretypovat na array

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

Zdravím, dělám si první aplikačku pomocí quickstartutoše a tutoše na ACL. Mám presenter NotesPresenter (v tutoriálu je pojmenován jako TodoPresenter) a v něm metodu pro zpracování formuláře

Presenter NotesPresenter má metodu:

public function processAddnoteForm(AppForm $form)
{
	    ....
        $values = $form->getValues();

        $notes = new Notes(); // v tutoši $todo = new Todo;
        $notes->name = $values['name'];
        $notes->text = $values['text'];
        $notes->publish = $values['publish'];

        $this->model->createNote($notes); // v tutoši $this->model->createTodo($todo)
    }
}

Zde je model NotesManager a jeho metoda createNote:

public function createNote(Notes $notes)
{
    print_r($notes);
    Debug::dump($notes);
    exit;
    return dibi::query('INSERT INTO [notes]', (array) $notes );
}

V druhé metodě vidíte, že se snažím dumpnout obsah objektu $notes dvěma způsoby.

  • První dump pomocí print_r vypíše správně „obsah“ objektu, jsou v něm vidět hodnoty, jaké byly poslány z formuláře.
  • Ten druhý (Debug::dump) ale říká, že objekt je prázdný (object(Notes) (0) {})

Což mi nějak neleze do hlavy. Něco s tím objektem je asi opravdu v nepořádku, protože následující řádek pro uložení do databáze mě vyřve, že se snažím vložit NULL (nedokáže $notes přetypovat na array, resp jen na prázdný array). Co je s tím objektem v nepořádku? Zdá se mi, že mám vše podle tutoriálu. Pro jistotu přikládám i definici classy Notes, z které se tento objekt vytváří. Třeba někoho něco praští do oka.

Definice třídy Notes:

Class Notes extends DibiRow
{

    public $name;
    public $text;
    public $publish;

    public function __construct($arr = array())
    {
        parent::__construct($arr);
    }

    public function delete()
    {
        return dibi::query("
            DELETE
            FROM [notes]
            WHERE [id] = %i
        ", $this->id);
    }

    public function save()
    {
        return dibi::query(
            "UPDATE [notes] SET",
            (array) $this,
            "WHERE [id] = %i",
            $this->id
        );
    }
}
Dtx
Člen | 17
+
0
-

No tak to je sranda, přišel jsem na řešení hnedka po odeslání tohoto postu :) V classe Notes nesmí být definovány její vlastnosti. Tedy musel jsem smazat následující

public $name;
public $text;
public $publish;

Poté už vše pracuje správně. Může mi někdo vysvětlit, proč to tak je? Jsem zvyklý vlastnosti objektu takto definovat a mám obavy, že nejsem sám.

Šaman
Člen | 2666
+
0
-

Třída DibiRow slouží jako přepravka pro data, ale nedoporučuji od ní dědit. Já jí používám jako náhradu za ArrayObjekt (dá se s ní pracovat jako s objektem i jako s polem).

Aby ti DibiRow fungovala jako pole, tak nesmí obsahovat žádné protected nebo private proměnné.

⇒ model (třídu Notes) neděď od DibiRow (je notes specializací nějaké DibiRow?!?) ale jen od Object a DibiRow použij jako přepravku na data, která ti ulehčí práci s databází (když to máš dobře navržené, tak proměnnou $data která je typu DibiRow můžeš předávat dibi dotazu a zároveň ji můžeš plnit rovnou výsledkem dibi::query("SELECT...")->fetch())

// edit. Ulehčí ti to i práci s formuláři, když je dobře navrhneš (úplně na začátku tvého příspěvku plníš data hodnotama z $values. To bys udělal jednoduše $this->data = $values).

Editoval Šaman (10. 12. 2010 10:52)

Dtx
Člen | 17
+
0
-

Popravdě ti moc nerozumím. Konrétně té druhé části (⇒ model (třídu Notes) neděď od DibiRow …)

Jak mam DibiRow v tomto případě použít jako „přepravku“ na data?

Pak je tu ještě jeden problém, který je trochu mimo:
$this->redirect(‚Notes‘); v metodě pro zpracování formuláře vyhodí výjimku, že http headers allready sent. Přesto jsem v několika příkladech našel, že lidé opravdu používají $this->redirect bez problémů. Asi jsem nějakej prašivej :|

Editoval Dtx (10. 12. 2010 10:53)

Šaman
Člen | 2666
+
0
-
<?php
Class Notes extends Object
{
    public $data = NULL; // bude typu DibiRow.
    //ale doporučil bych ti udělat $data protected a napsat si settery a gettery

    public function __construct($data = NULL)
    // konstruktor akceptuje pole, objekt DibiRow nebo nic
    {
        if ( isset($data) && $data instanceof DibiRow )
        {
            $this->data = $data;
        }
        elseif ( isset($data) && is_array($data) )
        {
            $this->data = new DibiRow($data);
        }
        else
        {
	    $this->data = new DibiRow(array());
        }
    }

    public function delete()
    {
        return dibi::query("
            DELETE
            FROM [notes]
            WHERE [id] = %i
        ", $this->data->id);
    }

    public function save()
    {
        return dibi::query(
            "UPDATE [notes] SET",
            $this->data,
            "WHERE [id] = %i",
            $this->data->id
        );
    }

    // pokud budeš mít getter $this->getId() tak ho používej místo $this->data->id.
    // a bude ti to našeptávat i editor (např. NetBeans)

    // bez setterů a getterů teď budeš zvenku přistupovat do dat přes proměnnou:
    // $notes->data->cosi
    // nebo $notes->data['cosi']
    // ale s použitím setterů a getterů budeš mít plně zdokumentované a našeptávatelné
    // $notes->setCosi(..)
    // resp. (protože dědíš od Nette Object) tak můžeš psát i $notes->cosi = ...
?>

Editoval Šaman (10. 12. 2010 11:13)

Dtx
Člen | 17
+
0
-

Díky, juknu na to a použiju jako studijní matroš.