codefog/contao-news_categories

Category link not working if two pages with the same alias is enabled

netzarbeiter opened this issue · 13 comments

I have tried to use the new feature «two pages with the same alias» of Contao 4.13.
https://docs.contao.org/manual/en/layout/site-structure/configure-pages/#routing

For the list page:

Page name: Blog
Page alias: blog
Module: Newslist (Filter by categories is enabled and the redirect settings for the category target page is the list page)

For the reader page:

Page name: Blog
Page alias: blog
Require an item: is enabled
Module: Newsreader (The redirect settings for the category target page is the list page)

Following the category link on the list page results in the following errors:

[2/2] NotFoundHttpException

Symfony\Component\HttpKernel\Exception\NotFoundHttpException:
Page not found: https://www.example.com/blog/kategorie/blog-beitrag.html

  at vendor/contao/core-bundle/src/EventListener/ExceptionConverterListener.php:97
  at Contao\CoreBundle\EventListener\ExceptionConverterListener->convertToHttpException(object(PageNotFoundException), 'NotFoundHttpException')
     (vendor/contao/core-bundle/src/EventListener/ExceptionConverterListener.php:68)
  at Contao\CoreBundle\EventListener\ExceptionConverterListener->__invoke(object(ExceptionEvent), 'kernel.exception', object(TraceableEventDispatcher))
     (vendor/symfony/event-dispatcher/Debug/WrappedListener.php:117)
  at Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(object(ExceptionEvent), 'kernel.exception', object(TraceableEventDispatcher))
     (vendor/symfony/event-dispatcher/EventDispatcher.php:230)
  at Symfony\Component\EventDispatcher\EventDispatcher->callListeners(array(object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener)), 'kernel.exception', object(ExceptionEvent))
     (vendor/symfony/event-dispatcher/EventDispatcher.php:59)
  at Symfony\Component\EventDispatcher\EventDispatcher->dispatch(object(ExceptionEvent), 'kernel.exception')
     (vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php:154)
  at Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch(object(ExceptionEvent), 'kernel.exception')
     (vendor/symfony/http-kernel/HttpKernel.php:213)
  at Symfony\Component\HttpKernel\HttpKernel->handleThrowable(object(PageNotFoundException), object(Request), 1)
     (vendor/symfony/http-kernel/HttpKernel.php:85)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor/symfony/http-kernel/Kernel.php:202)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (public/index.php:44)

[1/2] PageNotFoundException

Contao\CoreBundle\Exception\PageNotFoundException:
Page not found: https://www.example.com/blog/kategorie/blog-beitrag.html

  at vendor/contao/core-bundle/src/Resources/contao/controllers/FrontendIndex.php:211
  at Contao\FrontendIndex->renderPage(object(PageModel))
     (vendor/symfony/http-kernel/HttpKernel.php:152)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (vendor/symfony/http-kernel/HttpKernel.php:74)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor/symfony/http-kernel/Kernel.php:202)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (public/index.php:44)

If I change the page alias of the reader page to blog/artikel it works.

@aschempp can you give us a hint how we should approach this issue? Here is a short summary:

# Requested URL Expected page ID Page requires item? Page alias Actual Result
1 news.html 1 no news Correct, matched page ID 1.
2 news/category/category-3.html 1 no news 404 page not found, matched page ID 2.
3 news/lorem-ipsum-dolor-sit-amet-3.html 2 yes news Correct, matched page ID 2.

Of course when we change the alias of page ID 2 to e.g. news-article, then the 2nd case works fine.

That might be a bug. But that's also exactly what the route priority field is for, you should increase the priority of route no. 2 to make sure it is taken before route no. 3.

However, I also think the setup intended by @netzarbeiter is not possible. The system cannot know whether the news/xy is a category or a news alias. You cannot have two different pages with the same alias accept the same (type of) parameter.

Hmm, that's what I thought. So we would need a custom controller handling the news/xy URL, to distinguish whether it is a news category or a news article. Thanks for the reply.

not sure what you would do in a custom controller?

I'd catch that news/{params} route and manually check what $params is about, then render the appropriate content (we did that in one or two projects for sure, maybe even TN or that similar one). But that is a tailored solution so won't work as an open source thingy.

what if a category has the same alias as a news?

Came upon this issue today. And more or less found a possible solution from a previous comment:

The page with the news-list (and subsequently the one the category-url should route towards) requires a higher "Route priority" than the page with the news-reader (which would get routed towards otherwise).

From OPs example:

For the list page:
Page name: Blog
Page alias: blog
Route priority: 1
Module: Newslist (Filter by categories is enabled and the redirect settings for the category target page is the list page)

For the reader page:
Page name: Blog
Page alias: blog
Require an item: is enabled
Route priority: 0 (default)
Module: Newsreader (The redirect settings for the category target page is the list page)

Example links:

  • /blog.html > routed to page with news list
  • /blog/category/catA.html > routed to page with news list, filtered by category
  • /blog/my-blog-entry.html > routed to page with news details

At least, this worked for us just now. Cheers!

I have a similar problem, even if I use three pages where one is used for the news list, one for the news reader and one for the categories.
The list and the reader work fine, but if I visit /blog/kategorie/mycategory.html I get a NotFoundHttpException.
If I enable the debug mode I can see that the page id for the page I am on is the id of my category page.

For better understanding:

  • /blog.html -> Page id 228
  • /blog/article.html -> Page id 229
  • /blog/kategorie/category.html -> Page id 230, but 404

The solution mentioned in #209 (comment) does not work for me. The content of the news article is then displayed inside the list and the title, description, etc. is not set correctly, or I receive a 404 error if I disable that.

@lbnetprofit did you set the correct priority of the pages, like in the comment mentioned above?

@lbnetprofit did you set the correct priority of the pages, like in the comment mentioned above?

Yes, I have. The news article is routed to the page for the list if I do that.
I have also already tried switching the priorities, but then accessing one of the categories results in 404.

I can confirm the problem that @lbnetprofit has. Tried with version 3.5.4. Used the exact same config, that @Songworks used (see)

Can confirm the error. We switched to an alias for list and detail page and get a 404. In the meantime I did this via jQuery.

<script>

    $(document).ready(function() {
        // Initially show all teasers
        $(".layout_latest").show();

        // Add click event to category buttons
        $(".news_category_1, .news_category_2, .news_category_3, .reset").click(function(e) {
            e.preventDefault(); // Prevent the link from navigating to the URL

            var category = $(this).attr("class").split(" ")[0];

            // Hide all teasers
            $(".layout_latest").hide();

            if (category == "reset") {
                // Show all teasers for "All" category
                $(".layout_latest").show();
            } else {
                // Show teasers for selected category
                $("." + category).show();
            }

            // Set active state for selected category button
            $(".reset, .news_category_1, .news_category_2, .news_category_3").removeClass("active");
            $(this).addClass("active");
        });
    });

</script>