AI Reading
Quick summary of this article
This chapter explains how to set up routing and controllers in Zend Framework 3 for a Blog module. It shows how to map URLs to specific controller actions, create a controller to handle requests, and build views to display content, resulting in a working blog page with a detail view for each post.
- Routes are defined in each module's
config/module.config.phpfile, mapping URLs like/blogto theindexaction and/blog/detail/:idto thedetailaction. - Controllers extend
AbstractActionControllerand returnViewModelobjects to pass data to views, keeping business logic out of controllers. - The example
PostControllerhas anindexAction()that lists sample posts and adetailAction()that retrieves a post ID from the route. - Views are stored in the module's
viewdirectory, withindex.phtmldisplaying post links anddetail.phtmlshowing the selected post ID. - Best practices include using
Segmentroutes for dynamic parameters, keeping routes module-specific, and placing business logic in services or models.
Chapter 3: Routing & Controllers in Zend Framework 3
In this chapter, we continue building our Blog module from Chapter 2.
You will learn how to define routes, create controllers, and connect them with views inside the Blog module.
By the end, you’ll have a working /blog page with a detail view for each post.
✅ Introduction to Routing
- Routing maps a URL request to a specific controller and action.
- Each module has its own routes defined in
config/module.config.php. - Controllers inside the module handle the requests and return responses (usually
ViewModel).
✅ Defining Routes in Blog Module
// module/Blog/config/module.config.php
<?php
use Laminas\ServiceManager\Factory\InvokableFactory;
return [
'router' => [
'routes' => [
'blog' => [
'type' => 'Literal',
'options' => [
'route' => '/blog',
'defaults' => [
'controller' => Blog\Controller\PostController::class,
'action' => 'index',
],
],
'may_terminate' => true,
'child_routes' => [
'detail' => [
'type' => 'Segment',
'options' => [
'route' => '/detail[/:id]',
'constraints' => [
'id' => '[0-9]+',
],
'defaults' => [
'action' => 'detail',
],
],
],
],
],
],
],
'controllers' => [
'factories' => [
Blog\Controller\PostController::class => InvokableFactory::class,
],
],
'view_manager' => [
'template_path_stack' => [
__DIR__ . '/../view',
],
],
];
- /blog → Loads
PostController::indexAction. - /blog/detail/:id → Loads
PostController::detailActionwith a numeric ID.
✅ Creating PostController
// module/Blog/src/Controller/PostController.php
namespace Blog\Controller;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class PostController extends AbstractActionController
{
public function indexAction()
{
// Example blog posts
$posts = [
['id' => 1, 'title' => 'First Blog Post'],
['id' => 2, 'title' => 'Second Blog Post'],
];
return new ViewModel([
'posts' => $posts,
]);
}
public function detailAction()
{
$id = $this->params()->fromRoute('id', 0);
return new ViewModel([
'postId' => $id,
]);
}
}
- Controllers extend
AbstractActionController. indexAction()shows all posts.detailAction()displays details of a specific post usingid.
✅ Creating Views
// module/Blog/view/blog/post/index.phtml
<h2>Blog Posts</h2>
<ul>
<?php foreach ($this->posts as $post): ?>
<li>
<a href="/blog/detail/<?= $post['id'] ?>">
<?= $this->escapeHtml($post['title']); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
// module/Blog/view/blog/post/detail.phtml
<h2>Blog Post Detail</h2>
<p>You are viewing post with ID: <?= $this->escapeHtml($this->postId); ?></p>
index.phtmllists blog posts.detail.phtmlshows the selected post ID.
✅ Best Practices
- Keep routes for each module inside its own
module.config.php. - Use
Segmentfor dynamic parameters like:id. - Return
ViewModelobjects to pass data to views. - Keep controllers lightweight—business logic should go in services or models.
✅ Exercises
- Add a new route
/blog/createmapped toPostController::createAction. - Update
index.phtmlto display a “View Details” link for each post. - Pass post titles into
detail.phtmlinstead of just the ID. - Create another controller
CategoryControllerwith its own routes and views.
Congratulations! 🎉 You have completed Chapter 3: Routing & Controllers in Zend Framework 3.
Your Blog module now has functional routes, controllers, and views.
In the next chapter, we’ll cover Views & Layouts in detail.
