Autor Zpráva
piiiiiiiip
Profil
Dobrý den. Učím se nette a zasekl jsem se na komponentech. Nevíte o nějakém jednoduchém tutoriálu aby se to z něj dalo lechce pochopit (např vypsání dat z db)? Zkoušel jsem ten tutoriál na stránkách nette a jiných co jsem našel ale vždy to zkončilo chybou 500 apod . . .
Rfilip
Profil
No kromě dokumentace na stránkach nette třeba:
Komponenty pomocí Dependency InjectionOdkaz článek popisující spojení s db v komponentách
Vlastní komponenty v Nette článek popisují tvorbu komponenty a její šablony

Pokud jde o 500, to ti Latte nevrátila krásnou červenou stránku s přesnou chybou, včetně zvýrazněného řádku kde k ní došlo?

Pokud ne, tak se můžeš bud podívat do adresáře log, kde jsou všechny chybové hlášky uložené, nebo si povol debug mode na serveru pomocí najití řádku $configurator->setDebugMode('ip'); v souboru, app/bootstrap.php ten řádek odkomentuj a místo ip dosaď svoji ip adresu (zjisti treba na whatismyip.cz). Ty budeš mít přehlednou error hlášku, ostatní budou mít 500 jako jsi viděl do teď
piiiiiiiip
Profil
Ten první odkaz vypadá slibně ale než se do toho pustím tak jsem koukal že ten článek je 5 let starý, to nevadí?
CZechBoY
Profil
Nevadí.
Prvně si ale zapni ten vývojový režim jak píše Rfilip.
piiiiiiiip
Profil
Ok. Děkuji za radu, pustím se do toho :)
piiiiiiiip
Profil
Stále někde dělám zásadní chybu. Pomohl by mi ji někdo prosím najít když vám popíšu svůj myšlenkový pochod?
Nejdřív si vytvořím model, třeba pro ty články.
TestModel.php
<?php

namespace App\CoreModule\Model;

use App\Model\BaseManager;


class TestManager extends BaseManager
{
    const
        TABLE_NAME = 'article';
    public function getArticles()
    {
        return $this->database->table(self::TABLE_NAME);
    }
}
Jen vytáhnu články, nic víc pro tento pokus nepotřebuji.
Dále si vytvořím TestControl.php abych mohl renderovat články do šablony.
<?php 
namespace App\CoreModule\Components;
use App\CoreModule\Model\TestManager;
use Nette\Application\UI\Control;
class TestControl extends Control
    {
        /** @var TestManager */
        private $testManager;
        public function __construct(testManager $testManager)
        {
            parent::__construct();
            $this->testManager = $testManager;
        }
        public function render()
        {
            $this->template->article = $this->testManager->getArticles();
            $this->template->render();
        }
    }
Šablona pro články
        <h1>{$article->title}</h1>
a ještě tu komponentu vypíši do layoutu
                {control article $presenter}
V configu si komponentu zaregistruji:
    - App\CoreModule\Components\TestControl
A komponentu vytvořím v BasePresenter.php abych ji mohl vykreslit kdekoliv na webu.
protected function createComponentArticle()
    {
        return new TestControl($this->context->getService('TestManager'));
    }
}
Tet mi to ale nenajde tu službu: Service 'TestManager' not found.
Nevím jestly jsem úplně mimo, nebo jestly jsem jen něco přehlédl ale nemohu nato přijít.
CZechBoY
Profil
piiiiiiiip:
1) máš špatně velká/malá písmena u názvů tříd
2) komponenta se vykresluje pomocí {control article} případně následují parametry (ale to nedoporučuju)
3) presenter radši napíšu celý znova
<?php
class ArticlePresenter extends Nette\Application\UI\Presenter
{
  private $testManager;

  public function __construct(TestManager $testManager)
  {
    $this->testManager = $testManager;
  }
  
  protected function createComponentArticle()
  {
    return new TestControl($this->testManager);
  }
}

Ovšem lepší je udělat továrničku na komponentu a nemusíš vůbec řešit závislosti té komponenty.
<?php
namespace App\CoreModule\Components;

class TestControl extends Nette\Application\UI\Control
{
 // stejně jak máš
}

interface ITestControlFactory
{
  /**
   * @return TestControl  // zde v @return anotaci uvedeš jakou třídu má továrnička vytvořit
   */
  public function create(); // tuto metodu potom voláš v presenteru
}
zaregistruješ interface (příslušná třída se sama vygeneruje!)
services:
  - App\CoreModule\Components\ITestControlFactory
a v presenteru potom použiješ interface
<?php
use App\CoreModule\Components\ITestControlFactory;

class ArticlePresenter extends Nette\Application\UI\Presenter
{
  private $testControlFactory;

  public function __construct(ITestControlFactory $testControlFactory)
  {
    $this->testControlFactory = $testControlFactory;
  }
  
  protected function createComponentArticle()
  {
    return $this->testControlFactory->create(); // volá se metoda create z ITestControlFactory
  }
}
piiiiiiiip
Profil
CreateComponentArticle jsem upravil na CreateComponentTest a vrací mi to chybu :
Component with name 'test' does not exist.
CZechBoY
Profil
piiiiiiiip:
Pošli víc informací.
Šablona, ve které se snažíš použít tu komponentu je šablona toho presenteru, kde máš createComponentTest metodu?
piiiiiiiip
Profil
Dobře. Takže mám tedy ten model:
<?php
namespace App\CoreModule\Model;

class TestManager extends \App\Model\BaseManager
{
    const
        TABLE_NAME = 'article';
    public function getArticless()
    {
        return $this->database->table(self::TABLE_NAME);
    }
}
To by mělo být vpořádku.
Dále mám TestControl od tut už si nejsem jistý co je špatně.
<?php 
namespace App\CoreModule\Components;
use App\CoreModule\Model\TestManager;
use Nette\Application\UI\Control;

class TestControl extends Control
    {
        /** @var TestManager */
        private $testManager;
        public function __construct(TestManager $testManager)
        {
            parent::__construct();
            $this->testManager = $testManager;
        }
        public function render()
        {
            $this->template->test = $this->testManager->getArticless();
            $this->template->render();
           
        }
    }
    interface ITestControlFactory
{
  /**
   * @return TestControl  
   */
  public function create(); // tuto metodu potom voláš v presenteru
}
A presenter kde mám createComponentTest
<?php
namespace App\CoreModule\Presenters;
use App\CoreModule\Components\TestControl;
use App\CoreModule\Model\TestManager;
use App\CoreModule\Components\ITestControlFactory;

class TestPresenter extends \Nette\Application\UI\Presenter
{
   private $testControlFactory;
 
  public function __construct(ITestControlFactory $testControlFactory)
  {
      parent::__construct();
    $this->testControlFactory = $testControlFactory;
  }
  
  protected function createComponentTest()
  {
    return $this->testControlFactory->create(); // volá se metoda create z ITestControlFactory
   
  }
}
Od tut už jen hádám . . .
Šablona presenteru
App/CoreModule/presenters/test/default.latte (i test.latte pro případ že jsem zmotal názvy)
{* Latte template *}

{block content}
{$test->title}
Takže tet je v tom někde chyba, nebo to implementuju špatně. Chci {control test} vložit do @layout.latte (layout s dvěma sloupci - první sloupec: {include content} {* Vložení obsahu do šablony. *} a druhý sloupec: {control test})

Zkoušel jsem použít BasePresenter ale to mi vrátilo nějakou chybu o chybějícím parametru.
CZechBoY
Profil
Jo, vloz ten createComponentTest do BasePresenteru a predej zavislosti pres inject (metoda zacinajici na inject).

class BasePresenter extends Presenter
{
    private $testControlFactory;
    public function injectTestControlFactory(ITestControlFactory $f)
    {
        $this->testControlFactory = $f;
    }
    
    protected function createComponentTest()
    {
        return $this->testControlFactory->create();
    }
}
piiiiiiiip
Profil
Perfektní už vím jak na to :D. Mockrát děkuji za pomoc :)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: