Routování dotazy do databáze se provádí i tehdy kdy nemají

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

Zdravím,

obracím se na Vás s jedním problémem. Mám blog, kde v route factory zadávám tuto masku, která id článku mění na jeho název v URL:

$router[] = new Route('<presenter>/<cathegoryId>[/<articleId>]', array(
                    'cathegoryId' => array(
                        Route::FILTER_IN => function($cathegoryId)
                        {
                            if (is_numeric($cathegoryId)){
                            return $cathegoryId;
                            } else {


                            return $this->connection->table('cathegory')->where('url', $cathegoryId)->fetch()->id;
                            }
                        },
                        Route::FILTER_OUT  => function($cathegoryId)
                        {
                            if (!is_numeric($cathegoryId)){
                            return $cathegoryId;
                            } else {
                                return $this->connection->table('cathegory')->get($cathegoryId)->url;
                            }
                        }

                    ),
                    'articleId' => array(
                        Route::FILTER_IN => function($articleId) {
                        if (is_numeric($articleId)){
                            return $articleId;
                        } else {


                           return $this->connection->table('articles')->where('url', $articleId)->fetch()->id;
                        }
                        },
                       Route::FILTER_OUT => function ($articleId) {
                            if (!is_numeric($articleId)){
                            return $articleId;
                        } else {

                            return $this->connection->table('articles')->get($articleId)->url;
                        }
                       }
                    ),
                    'presenter' => 'Basic',
                    'action' => 'Uvod'
                ));

V případě presenteru Basic se to provede v podstatě správně a vše funguje více méně jak má. Problém nastane tehdy, když se přesměruji na jiný libovolný presenter. Tehdy mi to nahlásí chybu:

Trying to get property of non-object :

return $this->connection->table('cathegory')->where('url', $cathegoryId)->fetch()->id;

Zkrátka se z nějakého důvodu dotazy /--php $this->connection->table(‚articles‘)->get($articleId)->url; \--
provádí i u jiných presenterů ale z mého pohledu by se to mělo provést pouze v případě presenteru Basic.

Děkuji za jakoukoli radu proč se to děje a jak bych to měl opravit

petr.jirous
Člen | 128
+
+2
-

Ukaž jak si tam injectuješ ten connection.

Btw. cathegory je strašný :D

rosakovnik
Člen | 13
+
0
-

Já vím, je tam určitě spousta sémantických chyb…
connection předávám konstruktorem:

/** @var Connection */
 protected $connection;

   function __construct(\Nette\Database\Context $connection)
   {
       $this->connection= $connection;
   }
David Matějka
Moderator | 6445
+
0
-

nemas nahodou php 5.3? tam neni mozne pouzivat $this v anonymnich fcich, musis si tam zavislosti predat pomoci use (bud aliasujes $this na $that, ale pozor – pak musi byt connection public; nebo tam pomoci use predas primo $connection)

rosakovnik
Člen | 13
+
0
-

matej21 napsal(a):

nemas nahodou php 5.3? tam neni mozne pouzivat $this v anonymnich fcich, musis si tam zavislosti predat pomoci use (bud aliasujes $this na $that, ale pozor – pak musi byt connection public; nebo tam pomoci use predas primo $connection)

Mám verzi 5.5.15, takže by to v tom asi být nemělo…

Ot@s
Backer | 476
+
0
-

$this->connection->table('cathegory')->where('url', $cathegoryId)->fetch() Ti vrací false, proto to ...->id logicky vyhazuje Trying to get property of non-object (schválně si vydumpuj obsah $cathegoryId). Problém je v tom, že pravidlo routy je univerzální a zápis 'presenter' => 'Basic', znamená, že definuješ výchozí presenter (a akci). Pokud routu chceš opravdu jen pro BasePresenter, tak definici routy přepiš na:

$router[] = new Route('Basic/<cathegoryId>[/<articleId>]', array(....

a následně si vytvoř druhou pro všechny ostatní stránky. Na nějaké větší rady to není, protože nemáme více informací.

rosakovnik
Člen | 13
+
0
-

No, takto to v podstatě funguje, ovšem jednu věc nedokážu pochopit nebo to mám asi špatně. Když najedu na homepagePresenter, tak se mi udělá dotaz do databáze

„select * from cathegory“

a přitom by se tento dotaz přeci provést neměl nebo se mýlím? A nebo, když najedu na BasicPresenter, kde se mi vypisují články, tak se mi udělá cca 15 dotazů do databáze (když je tato routa vypnutá, tak pouze 2 dotazy, které mám v modelu nastavené):

SELECT *
FROM `cathegory`
...\temp\cache\_Nette.FileTemplate\_templates._layout.latte-7f7bc36d3f6cccdcbb7844d99b671a43.php:103	2
0.281
explain
SELECT `id`, `url`
FROM `cathegory`
WHERE (`cathegory`.`id` = 1)
...\app\router\RouterFactory.php:79	1
0.307
explain
SELECT `id`, `url`
FROM `cathegory`
WHERE (`cathegory`.`id` = 2)
...\app\router\RouterFactory.php:79	1
0.472
explain
SELECT `id`, `title`, `created_at`, `cat_id`
FROM `articles`
WHERE (`cat_id` = 1)
ORDER BY `created_at`
...\temp\cache\_Nette.FileTemplate\_Basic.uvod.latte-06e05e8c7cd2a6192919499f8bdaac7c.php:27	5
0.385
explain
SELECT `id`, `url`
FROM `cathegory`
WHERE (`cathegory`.`id` = 1)
...\app\router\RouterFactory.php:79	1
0.290
explain
SELECT *
FROM `articles`
WHERE (`articles`.`id` = 1)
...\app\router\RouterFactory.php:99	1
0.245
explain
SELECT `id`, `url`
FROM `cathegory`
WHERE (`cathegory`.`id` = 1)
...\app\router\RouterFactory.php:79	1
0.261
explain
SELECT *
FROM `articles`
WHERE (`articles`.`id` = 2)
...\app\router\RouterFactory.php:99	1
0.323
explain
SELECT `id`, `url`
FROM `cathegory`
WHERE (`cathegory`.`id` = 1)
...\app\router\RouterFactory.php:79	1
0.284
explain
SELECT *
FROM `articles`
WHERE (`articles`.`id` = 3)
...\app\router\RouterFactory.php:99	1
0.256
explain
SELECT `id`, `url`
FROM `cathegory`
WHERE (`cathegory`.`id` = 1)
...\app\router\RouterFactory.php:79	1
0.320
explain
SELECT *
FROM `articles`
WHERE (`articles`.`id` = 4)
...\app\router\RouterFactory.php:99	1
0.241
explain
SELECT `id`, `url`
FROM `cathegory`
WHERE (`cathegory`.`id` = 1)
...\app\router\RouterFactory.php:79	1
0.321
explain
SELECT *
FROM `articles`
WHERE (`articles`.`id` = 5)
...\app\router\RouterFactory.php:99
matopeto
Člen | 395
+
0
-

No to musi, lebo vo filtroch mozes menit parametre, a kym ten filter routa nespusti, tak sa nevie ci matchuje :)

Oli
Člen | 1215
+
0
-

@rosakovnik máš podle mě 2 možnosti, pokud nechceš pro každej odkaz dotaz do databáze. Buď si tu routu nakešovat nebo si vytáhnout všechny položky v db do pole [‚id‘ ⇒ ‚slug‘] a potom procházet to pole místo znova databázi.

Jan Suchánek
Člen | 404
+
0
-

@Jan Tvrdík Super, že to někdo konečně vyvrátil, já si taky myslel že je to best practice, když se používá cache.

Editoval jenicek (11. 11. 2014 12:23)