Router – hezké url – po přepisu odkazu nelze zobrazit článek

aha009
Člen | 50
+
0
-

Ahoj,
chtěl bych mít adresy ve tvaru neco.cz/about, neco.cz/contact.

Dle zdejších rad jsem něco pochytil, ale nějak jsem se zasekl.

V tuto chvíli se mi načítají články z DB a odkazy se zobrazují v těch požadovaných tvarech dle sloupce slug, ale po jejich rozkliknutí vždy narazím na chybu v routeru:
Trying to get property ‚id‘ of non-object

Už jsem toho vyzkoušel hodně, ale netuším kde dělám chybu.

Zde je ukázka

Router:

namespace App\Router;

use App\Model\ArticleManager;
use Nette\Application\Routers\RouteList,
    Nette\Application\Routers\Route;

final class RouterFactory
{

    private $articleManager;

    public function __construct(ArticleManager $articleManager)
    {
        $this->articleManager = $articleManager;
    }

    public function createRouter(): RouteList
	{
		$router = new RouteList;

        $router[] = new Route('<id>', array(
            'id' => array(
                Route::FILTER_IN => function ($id){
                    if(is_numeric($id)){
                        return $id;
                    }else{
                        $page = $this->articleManager->getArticle($id);
                        return $page->id;
                    }
                },
                Route::FILTER_OUT => function ($id){
                    if(!is_numeric($id)){
                        return $id;
                    }else{
                        $page = $this->articleManager->getArticle($id);
                        return $page->slug;
                    }
                }
            ),
            'presenter' => 'Article',
            'action' => 'show'
        ));

        $router[] = new Route('<presenter>/<action>', 'Homepage:default');

		return $router;
	}
}

ArticleManager:

namespace App\Model;

use Nette;

class ArticleManager
{
    use Nette\SmartObject;

    /** @var Nette\Database\Context */
    private $database;

    public function __construct(Nette\Database\Context $database)
    {
        $this->database = $database;
    }

    public function getPublicArticles()
    {
        return $this->database->table('posts');
    }

    public function getArticle($id)
    {
        return $this->database->table('posts')->get($id);
    }

}

ArticlePreseter:

namespace App\Presenters;

use App\Model\ArticleManager;
use Nette\Application\UI\Presenter;

class ArticlePresenter extends Presenter
{
    private $articleManager;

    public function __construct(ArticleManager $articleManager)
    {
        $this->articleManager = $articleManager;
    }

    public function renderShow($id)
    {
        $this->template->article = $this->articleManager->getArticle($id);
    }

}

Config:

services:
    router: @App\Router\RouterFactory::createRouter
    - App\Router\RouterFactory
    - App\Model\ArticleManager
Kamil Valenta
Člen | 752
+
0
-

Nevím, na jakém řádku se chyba vrací, ale patrně zde:

$page = $this->articleManager->getArticle($id);
return $page->id;

Asi saháš na id neexistujícího článku, articleManager Tě vrátí false (nebo null) a následně vracíš false->id…

Ta routa by přeci měla zachytávat slug, následně požádat articleManager o překlad slugu na id…

Editoval kamil_v (21. 1. 2020 13:24)

aha009
Člen | 50
+
0
-

Chyba je přesně tam co píšeš.
Router:

return $page->id;

ID co to volá by mělo existovat.

Odkazy volám přes id

<a href="{link Article:show $article->id}">Zobrazit - {$article->title}</a>

Toto mi vrátí link ve tvaru neco.cz/about

Myslel jsem, že přes ten filter v routeru můžu volat články pořád přes ID.
Když zadám neco.cz/1, tak se to přeloží na neco.cz/about, atd.

Zkoušel jsem, když si natvrdo v routeru nastavím

//return $page->id;
return 1;
/* a místo */
//return $page->slug;
return 'about';

tak to potom funguje.

David Matějka
Moderator | 6445
+
+2
-

v tom filter_in ma ta else branche vypadat zhruba:

$page = $this->articleManager->getArticleBySlug($id); // (musis implementovat)
if (!$page) {
  return null;
}
return $page->id;
aha009
Člen | 50
+
0
-

Podařilo se dořešit. Děkuji za radu.