Quickstart – potíže v počátcích
- Dismember
- Člen | 50
ahoj,
jsem u Nette teprve krátce a zkouším si dělat
Quickstart.
Sekl jsem se ale a některé věci mi nejsou vůbec jasné.
V TaskPresenter se volá funkce find(), která není nikde definovaná. Při
vytvoření menu a kliknutí na odkaz www/task/default/2 mi Laděnka
háže chybu
Call to undefined method Todo\ListRepository::find()
<?php
public function actionDefault($id){
// TaskPresenter má za úkol zobrazit jeden konkrétní sezman úkolů
// Identifikace se předá v adrese
$this->list = $this->listRepository->find($id);
}
?>
A dále mám problém s výpisem z databáze. Při výpisu úkolů mi
hlásí chybu u řádku $task->list->title .
Cannot read an undeclared column „list“.
<?php
{foreach $tasks as $task}
<tr>
<td>{$task->created|date:'j. n. Y'}</td>
<td>{$task->list->title}</td>
<td><b>{$task->text}</b></td>
<td>{$task->user->name}</td>
</tr>
{/foreach}
?>
Když ho odstraním, tak řádek $task->user->name
zobrazí.
Při kontrole dotazů však lze vidět, že byl podát dotaz SELECT
„id“, „title“ FROM „list“ ORDER BY „title“ ASC, takže moc
dobře nechápu, v čem může být problém. Cizí klíče u tabulky task
natavené mám.
Používám:
PHP 5.3.8 | Server Apache/2.2.21 (Win32) PHP/5.3.8 | Nette Framework 2.0.8
Postgresql 9.1
Jsem tady poprvé, tak nevím, jak moc detailně mám vše popisovat. předpokládám však, že Quickstart bude často diskutované téma.
Díky za jakoukoli pomoc!
Editoval Dismember (26. 2. 2013 23:01)
- enumag
- Člen | 2118
Všechna repository si musíš napsat sám, pro začátek bych ti doporučil CD collection, kde nějaké základní repository je k dispozici.
S tím undeclared column list si nejsem jistý, těch důvodů může být víc… Kdyžtak prosím strukturu těch dvou tabulek.
- Dismember
- Člen | 50
Díky za reakci!
S těmi repository návod pro začátečníka nepočítá? :-)
Hodil jsem cely můj quickstart do archivu na google drive a přiložil k tomu strukturu tabulek.
Pokud se mi na to někdo podívá, tak budu moc rád.
Přijímám facky za blbé chyby :-D
- Re4DeR
- Člen | 71
https://doc.nette.org/cs/quickstart vsak tady máš o repository
aby ti fungovalo to find tak pridej do ListRepository (nebo do hlavniho pokud od nej dedis) neco takoveho
public function find($by){
return $this->getTable()->get($by);
}
- Šaman
- Člen | 2666
Podívám se na to – QS musí být kompletní a nenechávat nic na
dodělání, protože kdo jede podle QS, ten ještě netuší, co je jeho chyba,
co je speciálka Nette a co si prostě má dopsat.
Kdyžtak si zatím můžeš stáhnou z QS zdrojáky, tam abstraktní repository
s touto funkcí určitě je (zdrojáky jsou funkční, až na hesla). Ale
v textu by o tom mohla být zmínka.
- Dismember
- Člen | 50
nějakým způsobem jsem pokročil, ale menu jsem stále nerozjel.
V menu mam odkaz vytvořen správně: /quickstart-elias/www/task/default/1
Laděnka mi ale vyhodí vyjímku:
PDOException
No reference found for $list->
Mé zdrojáky:
<?php
class TaskPresenter extends BasePresenter {
private $listRepository;
/** @var Todo\TaskRepository */
private $taskRepository;
/** @var Todo\UserRepository */
private $userRepository;
/** @var Nette\Database\Table\ActiveRow */
private $list;
/**
* V configu máme třídu Todo\ListRepository zaregistrovanou jako službu
* se jménem listRepository, takže se bude volat pomocí
* $this->context->listRepository.
*/
protected function startup() {
parent::startup();
// spojení s modelem listRepository
$this->listRepository = $this->context->listRepository;
}
public function actionDefault($id) {
// TaskPresenter má za úkol zobrazit jeden konkrétní sezman úkolů
// Identifikace se předá v adrese
$this->list = $this->listRepository->findBy(array('id' => $id))->fetch();
}
public function renderDefault() {
$this->template->list = $this->list;
$this->template->tasks = $this->listRepository->tasksOf($this->list);
}
}
?>
<?php
class ListRepository extends Repository {
/**
* Ve třídě Todo\ListRepository si vytvoříme metodu, která nám z
* objektu ActiveRow, obsahujícího řádek z tabulky list, vrátí
* všechny související úkoly.
*/
public function tasksOf(Nette\Database\Table\ActiveRow $list) {
return $list->related('task')->order('created');
}
}
?>
Databáze:
<?php
CREATE TABLE list
(
id integer NOT NULL DEFAULT nextval('list_id'::regclass),
title character varying(50),
CONSTRAINT pk_tlid PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE list
OWNER TO postgres;
?>
<?php
CREATE TABLE task
(
id integer NOT NULL,
text character varying(200),
done boolean,
user_id integer,
list_id integer,
created date,
CONSTRAINT pk_tid PRIMARY KEY (id),
CONSTRAINT task_list_id_fkey FOREIGN KEY (list_id)
REFERENCES list (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT task_user_id_fkey FOREIGN KEY (user_id)
REFERENCES "user" (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE task
OWNER TO postgres;
?>
<?php
CREATE TABLE "user"
(
id integer NOT NULL DEFAULT nextval('user_id'::regclass),
username character varying(50),
password character varying(50),
name character varying,
role character varying(20),
CONSTRAINT pk_userid PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE "user"
OWNER TO postgres;
?>
- Dismember
- Člen | 50
Nedaří se mi dokončit část s výpisem úkolů uživatele
Laděnka hází chybu: Argument 1 passed to Todo\TaskListControl::__construct() must be an instance of Nette\Database\Table\Selection, null given, called in C:\www\app\Apache\htdocs\quickstart-elias\app\presenters\HomepagePresenter.php on line 42 and defined
zdrojáky se shodují s návodem:
HomepagePresenter:
<?php
public function createComponentUserTasks() {
$incomplete = $this->taskRepository->findIncompleteByUser($this->getUser()->getId());
$control = new Todo\TaskListControl($incomplete, $this->taskRepository);
$control->displayList = TRUE;
$control->displayUser = FALSE;
return $control;
}
?>
Tasklist.php:
<?php
<?php
namespace Todo;
use Nette;
class TaskListControl extends Nette\Application\UI\Control {
/** @var \Nette\Database\Table\Selection */
private $selected;
/** @var TaskRepository */
private $taskRepository;
/** @var boolean */
public $displayUser = TRUE;
/** @var boolean */
public $displayList = FALSE;
public function __construct(Nette\Database\Table\Selection $selected, TaskRepository $taskRepository) {
parent::__construct(); // vždy je potřeba volat rodičovský konstruktor
$this->selected = $selected;
$this->taskRepository = $taskRepository;
}
public function render() {
$this->template->setFile(__DIR__ . '/TaskList.latte');
$this->template->tasks = $this->selected;
$this->template->displayUser = $this->displayUser;
$this->template->displayList = $this->displayList;
$this->template->render();
}
public function handleMarkDone($taskId) {
$this->taskRepository->markDone($taskId);
$this->presenter->redirect('this');
}
public function handleDelete($id) {
$this->taskRepository->delete($id);
$this->flashMessage('Nic', 'success');
$this->redirect('this');
}
}
?>
Chybovou hlášku chápu tak, že se do konstruktu nepředal argument, ačkoli by se předat měl:
<?php
$control = new Todo\TaskListControl($incomplete, $this->taskRepository);
?>
Kde může být chyba?
Tak jsem tuto věc zkusil vyřešit jinak. Vytvořil jsem si stránku, kde vypsal seznam uživatelů a kliknutím na jméno se předalo ID a měl by se zobrazit seznam úkolů pro daného uživatele.
UserPresenter:
<?php
public function renderTasks($userId) {
//$this->template->user = $this->userRepository->findByName($user);
$this->template->tasks = $this->taskRepository->findIncompleteByUser($userId);
}
?>
TaskPresenter:
<?php
public function findIncompleteByUser($userId){
$this->findIncomplete()->where(array('user_id' => $userId));
}
?>
Při výpisu mi to hlásí chybu Invalid argument supplied for foreach()
**Můžete mi prosím někdo s tímto pomoci? Děkuji **
- Dismember
- Člen | 50
zdravím po nějaké době ;-) začal jsem tvořit aplikaci a využívám postupy, které jsou představeny ve quickstartu.
Chtěl jsem si vytvořit menu z položek v databázi. Stejně jako ve quickstartu jsem proto připojil jednotlivé repozitáře do BasePresenteru a ve funkci beforeRender volám položky z databáze.
<?php
use Nette\Application\UI;
use Nette\Application\UI\Form;
/**
* Base presenter for all application presenters.
*/
abstract class BasePresenter extends Nette\Application\UI\Presenter {
private $itemRepository;
private $sourceRepository;
private $topicRepository;
private $regionRepository;
function inject(Osint\ItemRepository $itemRepository, Osint\SourceRepository $sourceRepository, Osint\TopicRepository $topicRepository, Osint\RegionRepository $regionRepository) {
$this->itemRepository = $itemRepository;
$this->sourceRepository = $sourceRepository;
$this->topicRepository = $topicRepository;
$this->regionRepository = $regionRepository;
}
public function beforeRender() {
// provede vždy nezávisle na view
$this->template->topics = $this->topicRepository->getTopics();
}
public function handleSignOut() {
$this->getUser()->logout();
$this->redirect('Sign:in');
}
}
?>
Toto ale skončí fatal errorem Call to a member function getTopics() on a non-object
Podobně v jiném presenteru (viz níže) volám položky a vše funguje jak má
Můžete mi poradit prosím, jak upravit výše uvedený kód, abych získal položky z databáze, které použiju na každou stránku do menu?
<?php
use Nette\Application\UI;
use Nette\Application\UI\Form;
class TopicPresenter extends BasePresenter {
private $itemRepository;
private $sourceRepository;
private $topicRepository;
private $regionRepository;
function inject(Osint\ItemRepository $itemRepository, Osint\SourceRepository $sourceRepository, Osint\TopicRepository $topicRepository, Osint\RegionRepository $regionRepository) {
$this->itemRepository = $itemRepository;
$this->sourceRepository = $sourceRepository;
$this->topicRepository = $topicRepository;
$this->regionRepository = $regionRepository;
}
public function renderDefault() {
$this->template->topics = $this->topicRepository->getTopics();
}
}
?>
Editoval Dismember (18. 6. 2013 8:56)
- andrej2005
- Člen | 2
Dobry den. Taky mam potize s quickstartem. Precetl jsem snad vsechna thready na tohle tema, a dospel jsem k nazoru, ze provozovatel stranek bys mel dat to do poradku. Zacatecnik nevidi do hloubky vsech chyb, problemu a souvislosti, proto nedokaze dat to dohromady.
Timto zadam o opravu zdrojaku pro quickstart.
- Glottis
- Člen | 129
a jeste si nejsem jisty tim, jak mas zadeklarovane ty privatni promene. mas je jak v base tak tom podedenem. a v obou do nich priradis pres inject (pokud vubec projdou oba injecty) a cekal bych, ze kdyz priradis v podedenem, tak v parentovy tam ty data mit nebudes :) protoze to je privat
- jiri.pudil
- Nette Blogger | 1032
andrej2005 napsal(a):
Dobry den. Taky mam potize s quickstartem. Precetl jsem snad vsechna thready na tohle tema, a dospel jsem k nazoru, ze provozovatel stranek bys mel dat to do poradku. Zacatecnik nevidi do hloubky vsech chyb, problemu a souvislosti, proto nedokaze dat to dohromady.
Jenže pro člověka, který ten quickstart píše, není vůbec jednoduché se oprostit od toho, co už o Nette ví a kam až do hloubky vidí. Takový člověk prostě neví, co všechno začátečník neví. (Nehledě na to, že to, co začátečník neví, často zahrnuje i elementární věci, které se spíše než Nette týkají samotného PHP a OOP v něm.)
Timto zadam o opravu zdrojaku pro quickstart.
Jakým směrem? Na co se zaměřit? Která místa jsou problematická? Co kde zjednodušit? Co kde vysvětlit víc do hloubky? Když pošleš konkrétní připomínky, určitě s tím půjde něco udělat. Jinak je to jen výkřik do tmy.
- lukaha
- Člen | 2
jiri.pudil napsal(a):
…
Timto zadam o opravu zdrojaku pro quickstart.Jakým směrem? Na co se zaměřit? Která místa jsou problematická? Co kde zjednodušit? Co kde vysvětlit víc do hloubky? Když pošleš konkrétní připomínky, určitě s tím půjde něco udělat. Jinak je to jen výkřik do tmy.
Zdravim, tak ja se pokusim shrnout sve poznatky ze studia quickstartu:
- verze na github.com je diametralne odlisna od textu v quickstartu, protoze se v quickstartu pouziva dle slov hlavnich vyvojaru Nette BAD PRACTICE (lekce se stejným principem Prezentery, Formuláře:
$this->taskRepository = $this->context->taskRepository;
) Chapu,ze se Nette vyviji, ale dle meho nazoru by to mohlo byt aspon trochu sjednocenne at jiz s githubem nebo github s quickstartem (pomerne dost dlouho mi trvalo, nez jsem prisel, kde je chyba a v cem se lisi muj kod od Githubu, kdyz jsem psal podle navodu… metoda injectNeco mi pripomina metodu set)
- dale v kapitole Prezentery je chyba v metode actiondefault, ktera se da objevit celkem snadno, protoze hlasi, ze metoda find ($id) neexistuje, a na Githubu je to opravene, ale jiz se nikdo neotravoval to dat i do textu:
$this->list = $this->listRepository->find($id);
- clovek v quickstartu snadno ztrati orientaci: nadpis TaskPrezenter, kousek pod tim BasePresenter (ac je to v jinem kontextu, muze to par novacku zmast).
V poslednich 3 kapitolach jsem nic nenasel. Zdaji se mi, ze jsou jiz psany novym zpusobem. Je mozne aspon zrevidovat ceskou verzi a upravit ji dle anglicke verze?
- andrej2005
- Člen | 2
>
Timto zadam o opravu zdrojaku pro quickstart.
Jakým směrem? Na co se zaměřit? Která místa jsou problematická? Co kde zjednodušit? Co kde vysvětlit víc do hloubky? Když pošleš konkrétní připomínky, určitě s tím půjde něco udělat. Jinak je to jen výkřik do tmy.
Jakym smerem? Navod je celkem pekny, snazeji se vysvetlit koncepci
frameworku! Ale bohuzel kdyz jedes podle nej, tak ten projekt se nespusti.
Ladenka vyhodi spoustu chyb, a nevis kam s tim. Jestli stahnes z githubu, pak
Composer to neumi sestavit – prej neumi stahnout nejaky tester.git. Rucne
taky nejde. Ja osobne uz nevim kam pichnout. Zkusil vsechno (behem druheho tydne
praci na tom podle moznosti). Je mi zajmave jestli autor to vyzkousel u sebe?
Opravdu mu to bezi? Nebo trochu jinak, je tady nekdo, komu funguje quickstart?
Aspon bezi example CD-collection. Celkem podobny priklad. Podle nej snazim se
prokousat. V PHP jsem opravdu zacatecnik, pro mne je bliz asp.net, ale
okolnosti jsou takove, ze musim to zvladnout.
Proste chtelo by to, pokud je to opravdu quickstart, podle navodu sestavit
projekt a spustit ho, i kdyz clovek nechape vsech souvisloti v PHP. A na
githubu musi byt funkcni zdrojak pro overeni postupu. Bylo by to mozni?