Undefined variable $results

mimacala
Člen | 113
+
0
-

Ahojte, prosím jakou věc dělám špatně ?
Odešlu form z home do search a hláška o neznámé proměnné $results, ale proměnnou definuji a i nastavuji v Searchrenderu :/

<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette;
use Nette\Utils\Finder;
use Nette\Application\UI\Form;
use Nette\Application\Responses\FileResponse;
use Nette\Database\Explorer;


final class HomePresenter extends Nette\Application\UI\Presenter
{
    public function __construct(
    private Explorer $db,
    )
    {

    }

    public function renderHome()
    {


    }

    protected function createComponentUpload(): Form // form na upload souborů
    {
        $form = new Form;
        $form->addMultiUpload('files', 'Soubory:');
        $form->addSubmit('send', 'Upload');
        $form->onSuccess[] = [$this, 'formSucceeded'];
        return $form;
    }

    public function formSucceeded(Form $form, $data): void // zpracování uploadu souboru
    {
        $buffer = [];
        $c = "http://localhost/ecufiles/files/";
        foreach ($data->files as $file)   //přesune všechyn soubory do files a uloží do db
        {
            $name = $file->getSanitizedName();
            $cesta = $c.$name;
            $file->move('../files/'.$name);
            array_push($buffer, $name);
            $this->db->table("files")->insert([
                "location" => $cesta,
                "name" => $name
            ]);

        }
        $this->flashMessage($name); // kontrola vypis
        $this->flashMessage($cesta);// kontrola vypis
        $this->redirect('Home:');
    }

    protected function createComponentFind(): Form // formulář k vyhledávání
    {
        $form = new Form;
        $form->addText('text', 'Ecu number');
        $form->addSubmit('send', 'Find');
        $form->onSuccess[] = [$this, 'formOk'];
        return $form;
    }

    public function formOk(Form $form, $data): void // zpracování vyhledávání
    {
        $files = $this->db->table("files")->where("name LIKE ? ", "%".$data->text."%")->fetchAll(); // vytáhne fulltext z db
        $this->redirect("Search:",$files); // přesměruje na stránku výpisu a odešle vyhledané věci do SearchPresenteru
    }

}

<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette;
use Nette\Utils\Finder;
use Nette\Application\UI\Form;
use Nette\Application\Responses\FileResponse;
use Nette\Database\Explorer;


final class SearchPresenter extends Nette\Application\UI\Presenter
{
    public function __construct(
    private Explorer $db,


    )
    {

    }

    public function renderSearch($search)   //tady někde se děje chyba mělo by převezmout data přeposlané z Home"
    {
        $this->template->results = $search; // proměnnou results hlásí v .latte jako nedefinovanou
    }

    protected function createComponentFind(): Form
    {
        $form = new Form;
        $form->addText('text', 'Ecu number');
        $form->addSubmit('send', 'Find');
        $form->onSuccess[] = [$this, 'formOk'];
        return $form;
    }

    public function formOk(Form $form, $data): void
    {
        $files = $this->db->table("files")->where("name LIKE ? ", "%".$data->text."%")->fetchAll();
        $this->redirect("Search:",$files);


    }

}

{block content}
{control find}
{foreach $results as $result}
{$result->name}
<a href="{$result->id}">Show</a><br>
{/foreach}
nightfish
Člen | 463
+
+2
-

@mimacala Přesměrováváš pomocí $this->redirect("Search:",$files);, takže na renderDefault(). Šablona zřejmě taky bude k SearchPresenter::renderDefault() (default.latte?), zatímco proměnnou $results do šablony nastavuješ v SearchPresenter::renderSearch(), což je metoda, která se ve tvém případě nevolá.

Editoval nightfish (12. 2. 21:25)

mimacala
Člen | 113
+
0
-

Ale jistě to je ono.
Pak tedy bych chtěl ještě poprosit, zjednodušil jsem to na jeden presenter.
Pokud není dole redirect ale pouze se nastaví proměnná, tak vše funguje, ale jak nastavím redirect a proměnnou až v renderu, tak nic nezobrazí, jako by se data při redirectu někde ztratila :/

<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette;
use Nette\Utils\Finder;
use Nette\Application\UI\Form;
use Nette\Application\Responses\FileResponse;
use Nette\Database\Explorer;


final class HomePresenter extends Nette\Application\UI\Presenter
{
    public function __construct(
    private Explorer $db,
    )
    {

    }

    public function renderDefault($files = array())
    {

        $this->template->results = $files;
    }

    protected function createComponentUpload(): Form // form na upload souborů
    {
        $form = new Form;
        $form->addMultiUpload('files', 'Soubory:');
        $form->addSubmit('send', 'Upload');
        $form->onSuccess[] = [$this, 'formSucceeded'];
        return $form;
    }

    public function formSucceeded(Form $form, $data): void // zpracování uploadu souboru
    {
        $buffer = [];
        $c = "http://localhost/ecufiles/files/";
        foreach ($data->files as $file)   //přesune všechyn soubory do files a uloží do db
        {
            $name = $file->getSanitizedName();
            $cesta = $c.$name;
            $file->move('../files/'.$name);
            array_push($buffer, $name);
            $this->db->table("files")->insert([
                "location" => $cesta,
                "name" => $name
            ]);

        }
        $this->flashMessage($name); // kontrola vypis
        $this->flashMessage($cesta);// kontrola vypis
        $this->redirect('Home:');
    }

    protected function createComponentFind(): Form // formulář k vyhledávání
    {
        $form = new Form;
        $form->addText('text', 'Ecu number');
        $form->addSubmit('send', 'Find');
        $form->onSuccess[] = [$this, 'formOk'];
        return $form;
    }

    public function formOk(Form $form, $data): void // zpracování vyhledávání
    {
        $files = $this->db->table("files")->where("name LIKE ? ", "%".$data->text."%")->fetchAll(); // vytáhne fulltext z db
        $this->template->results = $files; // toto zobrazí vyhledaný obsah v pořádku
       // $this->redirect("Home:",$files); // refreshne a přepošle data, ale nic se neukáže
    }

}

m.brecher
Generous Backer | 698
+
+1
-

@mimacala

refreshne a přepošle data, ale nic se neukáže

Pátrej po datech $files, kde končí jejich stopa. Použij bdump($files), třeba takto:

public function renderDefault($files = array())
    {
		bdump($files);		// zobrazí se dump nebo ne a jsou ve $files date nebo ne??
        $this->template->results = $files;
    }

Ověříš, jestli se akce default spustí nebo ne a jestli do akce data doputovaly nebo ne. Aby Ti někdo poradil, je potřeba dodat další informace – šablona, kde se formulář vykresluje a jméno šablony atd…

Pepino
Člen | 239
+
+1
-

@mimacala

public function formOk(Form $form, $data): void
{
	$this->redirect('default', $data->text);
}

public function renderDefault(?string $text = null): void
{
	if ($text !== null) {
		$files = $this->db->table("files")->where("name LIKE ? ", "%".$text."%")->fetchAll(); // vytáhne fulltext z db
		$this->template->results = $files; // toto zobrazí vyhledaný obsah v pořádku
	} else {
		$this->template->results = [];
	}
}
mimacala
Člen | 113
+
0
-

Moc se mi líbí řešení zpracovávat to až v renderu, tato verze funguje, moc bych chtěl za to poděkovat.
Ať se také něco přiučím, prosím můžeme nějak rozebrat toto ?
?string $text = null // vytvořím proměnnou s hodnotou null, definuji tedy, že bude string což moc nechápu proč, když php je dynamicky typovaný ? a co znamená ten “?”.

Další věc je proč se za funkcí píše :void, když to funguje i bez :)

 public function renderDefault(?string $text = null): void
    {
        if ($text !== null) {
            $files = $this->db->table("files")->where("name LIKE ? ", "%".$text."%")->fetchAll(); // vytáhne fulltext z db
            $this->template->results = $files; // toto zobrazí vyhledaný obsah v pořádku
        } else {
            $this->template->results = [];
        }
    }

Tady u result->id mi vyhazuje chybu, že must be of type Stringable|string, int given, zkusil jsem tedy smazat definování proměnné jako string, ale chyba nezmizela. Nechápu tedy, proč rozlišuje jestli vypisuji string nebo int :/

Opět moc děkuji za velmi poučné rady.

{block content}
{control upload}
{control find}
{foreach $results as $result}
{$result->name}
<a href="{$result->id}">Show</a><br>
{/foreach}
Infanticide0
Člen | 54
+
+1
-

@mimacala
Dynamický typování je nemoc PHP (kapavka nakažená HIV). Tvoje dotazy ukazují, že jsi zůstal v PHP 4. Projdi si nějaký PHP 8 tutoriály, jeden dobrej je přímo na nette.org

https://doc.nette.org/…-programming

Editoval Infanticide0 (13. 2. 11:54)

m.brecher
Generous Backer | 698
+
+1
-

@mimacala

?string $text = null // vytvořím proměnnou s hodnotou null, definuji tedy, že bude string což moc nechápu proč, když php je dynamicky typovaný ? a co znamená ten “?”.

Dynamické typování PHP má řadu nevýhod a proto bylo v PHP cca 2015 zavedeno alternativní silné typování, které je nepovinné, ale důrazně doporučované. Zapne se takto:

<?php

declare(strict_types=1);

Po jeho zapnutí PHP kontroluje typy na vstupu a výstupu funkcí/metod a v propertách objektů.

public function renderDefault(?string $text = null): void
{
   // ...
}

tento zápis znamená:

a) proměnná $text je string nebo null (otazník) a má defaultní hodnotu null
b) : void znamená, že metoda nevrací žádný výstup

V PHP není typování povinné, takže funguje i zápis bez typů (i když zapneš declare(strict_types=1)), ale každý, kdo v PHP pracuje alespoň trochu profesionálně typování používá.

Na obecné dotazy okolo PHP když něčemu nerozumíš je naprosto skvělá nějaká umělá inteligence, stačí položit vhodně formulovaný dotaz třeba „význam znaku ? v php kódu public function renderDefault(?string $text = null): void“ a umělá inteligence Ti obvykle odpoví lépe než komunita zde na fóru.

Editoval m.brecher (13. 2. 18:10)

mimacala
Člen | 113
+
0
-

Aha, to jsou velmi zajímavé informace, moc děkuji za osvětu.

mimacala
Člen | 113
+
0
-

Kažodpádně, odstranil jsem
declare(strict_types=1);
a ted to vypadá takto

  public function renderDefault($text = null): void
    {
        if ($text !== null) {
            $files = $this->db->table("files")->where("name LIKE ? ", "%".$text."%")->fetchAll(); // vytáhne fulltext z db
            $this->template->results = $files; // toto zobrazí vyhledaný obsah v pořádku
        } else {
            $this->template->results = [];
        }
    }
{block content}
{control upload}
{control find}
{foreach $results as $result}
{$result->name}
<a href="{$result->id}">Show</a><br>   //tady chyba
{/foreach}

a řeším problém stále i po odstranění definování typů proměnných chybu.
TypeError
Latte\Runtime\Filters::safeUrl(): Argument #1 ($s) must be of type Stringable|string, int given, called in

označuje řádek <a href=„{$result->id}“>Show</a><br>

Nechápu tedy, když jsem mu řekl, ať neřeší typ proměnné co mu vadí :D, moc děkuji za osvětu.

Pokud vypisuji něco jiného než int ID, tak text normálně funguje.

Infanticide0
Člen | 54
+
0
-

Problém ti to píše, jenom si neuvědomuješ jednu magii, která je na pozadí a kterou snadno zjistíš přečtením error hlášky.
Když Latte vypisuje <a> tag, tak proměnnou v atributu href vypíše přes funkci:

// Sanitizes string for use inside href attribute.
public static function safeUrl(string|\Stringable $s): string;

A ta striktně (protože tak je to správně, ááno) vyžaduje string nebo Stringable objekt.
Takže pokud potřebuješ vypsat do hrefu číslo a nechceš použít n:href pro vygenerování URL podle Routeru aplikace, přetypuj to číslo na string.

tohle vygeneruje PHP chybu

<a href="{1}">test int</a>
echo LR\Filters::escapeHtmlAttr(LR\Filters::safeUrl(1))

a tohle vygeneruje validní PHP

<a href="{(string)1}">test string</a>
echo LR\Filters::escapeHtmlAttr(LR\Filters::safeUrl((string) 1))

Editoval Infanticide0 (21. 2. 0:56)

m.brecher
Generous Backer | 698
+
0
-

@mimacala

a) nikdy nepoužívej:

<a href="{$result->id}">Show</a>

V Nette frameworku je potřeba odkazovat na presentery a akce, k tomu slouží latte atribut n:href, takže správně to má být takto:

<a n:href="Presenter:action $result->id">Show</a>

b) nikdy nevypínej declare(strict_types=1)

c) používej typehinty všude, kde to jde

Tím, že nebudeš typovat nic nevyřešíš a naopak se dostaneš do problémů. Typování Ti bude pomáhat a pokud narazíš na problém, bude v něčem jiném než v typování.