Creating and Running a Zend Framework (Laminas) Project in ServBay
Overview
Zend Framework (now part of the Laminas Project) is a powerful open-source PHP framework featuring a comprehensive collection of high-quality, object-oriented components for building modern web applications and services. Renowned for its flexibility, modular design, and performance, it is an excellent choice for developing anything from simple websites to complex, enterprise-grade systems.
ServBay is a purpose-built local web development environment for macOS, integrating PHP, multiple web servers (such as Caddy and Nginx), databases (like MySQL, PostgreSQL, MongoDB), caching services (like Redis, Memcached), and other developer tools. ServBay offers an effortless way to configure and manage these packages, making it incredibly easy to set up and run PHP framework projects locally.
This documentation will guide you through creating and running a Zend Framework (Laminas) project in the ServBay environment, and demonstrate how to integrate ServBay’s database and caching services into your project.
Prerequisites
Before you begin, ensure you have completed the following:
- Installed ServBay: ServBay is successfully installed and running on your macOS system. If you haven’t installed it yet, visit the official ServBay website for download and installation instructions.
- ServBay Packages: Make sure the necessary packages are installed and running within ServBay, including:
- At least one PHP version (PHP 8.x or higher is recommended, as recent versions of Zend Framework / Laminas require it).
- A web server (Caddy or Nginx).
- Composer (included with ServBay by default).
- The database services (e.g., MySQL, PostgreSQL) and caching services (e.g., Memcached, Redis) you plan to use. You can easily start these services via the ServBay control panel.
Creating a Zend Framework Project
ServBay recommends storing all your website projects in the /Applications/ServBay/www
directory, which allows ServBay to automatically manage and configure your websites.
Go to the Web Root
Open a terminal and navigate to the ServBay recommended web root:
bashcd /Applications/ServBay/www
1Create a Project Using Composer
Composer comes pre-installed with ServBay, so you don’t need to install it separately. Use Composer’s
create-project
command to set up a new Zend Framework (Laminas skeleton application) project. We'll create it in a subdirectory calledservbay-zend-app
:bashcomposer create-project laminas/laminas-skeleton-application servbay-zend-app
1This will download the Zend Framework (Laminas) skeleton application into the
servbay-zend-app
directory and install all required dependencies.Enter the Project Directory
Navigate into your newly created project directory:
bashcd servbay-zend-app
1
Configuring the Web Server
To access your Zend Framework project in the browser, you need to configure a website within ServBay.
- Open ServBay Control Panel: Launch the ServBay application.
- Website Settings: In the ServBay control panel, find and click the Websites tab.
- Add a New Website: Click the
+
button in the bottom left corner to add a new website configuration. - Enter Website Information:
- Name: Give your website an easily recognizable name, such as
My Zend Dev Site
. - Domain: Enter the domain you wish to use for accessing the project in your browser. To avoid conflicts with real domains, it is recommended to use a
.local
or.test
suffix, for example,servbay-zend-test.local
. ServBay will automatically configure local DNS resolution. - Website Type: Select
PHP
. - PHP Version: Choose the PHP version you want this site to use (e.g.,
8.3
). Make sure it is already installed and running in ServBay. - Document Root: This is the folder exposed by the web server. Zend Framework's entry point,
index.php
, is located within the project'spublic
directory. Therefore, set the document root to your project’spublic
folder:/Applications/ServBay/www/servbay-zend-app/public
.
- Name: Give your website an easily recognizable name, such as
- Save and Restart: Click Save. ServBay will prompt you to apply changes—after you confirm, the web server will reload its configuration, making your new site active.
For detailed steps, refer to the Adding Your First Website section in the ServBay documentation.
Basic "Hello ServBay!" Example
Let's modify the project code so that accessing the root URL (/
) displays "Hello ServBay!".
Configure Routing and Controller (module.config.php)
Edit the
module/Application/config/module.config.php
file in your project’s root. Make sure it includes the following basic routing and controller configuration:php<?php declare(strict_types=1); namespace Application; use Laminas\Router\Http\Literal; use Laminas\Router\Http\Segment; use Laminas\ServiceManager\Factory\InvokableFactory; return [ 'router' => [ 'routes' => [ 'home' => [ 'type' => Literal::class, 'options' => [ 'route' => '/', 'defaults' => [ 'controller' => Controller\IndexController::class, 'action' => 'index', ], ], ], // ... other routes ], ], 'controllers' => [ 'factories' => [ Controller\IndexController::class => InvokableFactory::class, ], ], 'view_manager' => [ 'display_not_found_reason' => true, 'display_exceptions' => true, 'doctype' => 'HTML5', 'not_found_template' => 'error/404', 'exception_template' => 'error/index', 'template_map' => [ 'layout/layout' => __DIR__ . '/../view/layout/layout.phtml', 'application/index/index' => __DIR__ . '/../view/application/index/index.phtml', 'error/404' => __DIR__ . '/../view/error/404.phtml', 'error/index' => __DIR__ . '/../view/error/index.phtml', ], 'template_path_stack' => [ __DIR__ . '/../view', ], ], // ... other configurations ];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49Note: This code block is part of
module.config.php
. You must merge it with your file’s existing array. Ensure the'home'
route andController\IndexController::class
factory are present.Create or Modify the Controller (IndexController.php)
Edit or create the file
module/Application/src/Controller/IndexController.php
. Make sure theindexAction
method returns a ViewModel with the message:php<?php declare(strict_types=1); namespace Application\Controller; use Laminas\Mvc\Controller\AbstractActionController; use Laminas\View\Model\ViewModel; class IndexController extends AbstractActionController { /** * Default action to display the welcome page. */ public function indexAction() { // Returns a ViewModel and passes the 'message' variable to the view return new ViewModel([ 'message' => 'Hello ServBay!', ]); } // ... other action methods }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24Create or Edit the View File (index.phtml)
Edit or create the file
module/Application/view/application/index/index.phtml
. This file will receive themessage
variable from the controller and display it:php<h1><?php echo $this->message; ?></h1>
1Here, you're using Zend Framework (Laminas) view helpers to access the data passed from the controller.
Accessing Your Website
Open your web browser and visit the domain you configured in ServBay, such as https://servbay-zend-test.local
.
If everything is set up correctly, you should see a page displaying Hello ServBay!
. This confirms your Zend Framework project is running successfully in ServBay.
Database and Cache Integration Examples
ServBay provides various database and caching services. The following examples illustrate how to connect and use Memcached, Redis, MySQL, and PostgreSQL in a Zend Framework project.
Important: The following database and cache examples are standalone demos. In real-world projects, you’ll typically choose one database and one or more cache services as needed, and manage connections via dependency injection, etc. Make sure the relevant packages (e.g., MySQL, PostgreSQL, Memcached, Redis) are started in ServBay before running these examples.
Database Interaction Example - Creating a Table
Let's start by demonstrating how to interact with a database using the Laminas DB component, including creating a simple table. This code snippet shows how to define and run a table creation operation manually, rather than using the full Laminas Migrations tool.
Install the Laminas DB Component
In your project root directory, use Composer to install the Laminas DB component:
bashcomposer require laminas/laminas-db
1Manually Create the Database
Before running the database examples, manually create a database named
servbay_zend_app
in your chosen ServBay database service. You can use tools like phpMyAdmin, pgAdmin, or MongoDB Compass via the ServBay control panel. The default username for MySQL/MariaDB in ServBay isroot
, and the default password ispassword
. The same defaults apply for PostgreSQL.Define and Run a Table Creation Script (Example)
Create a PHP file (e.g.,
create_users_table.php
in your project root or a temporary location) with the following code to define and execute creation of ausers
table:php<?php // create_users_table.php use Laminas\Db\Adapter\Adapter; use Laminas\Db\Sql\Sql; // Assuming you are using MySQL or MariaDB $adapter = new Adapter([ 'driver' => 'Pdo_Mysql', // or 'Pdo_Pgsql' 'database' => 'servbay_zend_app', 'username' => 'root', 'password' => 'password', // ServBay default password 'hostname' => '127.0.0.1', // 'port' => 3306, // MySQL default port // 'port' => 5432, // PostgreSQL default port ]); $sql = new Sql($adapter); // Define the SQL to create the users table $create = $sql->createTable('users') ->addColumn(new \Laminas\Db\Sql\Ddl\Column\Integer('id', false, null, ['AUTO_INCREMENT' => true])) ->addColumn(new \Laminas\Db\Sql\Ddl\Column\Varchar('name', 255)) ->addColumn(new \Laminas\Db\Sql\Ddl\Column\Varchar('email', 255, ['UNIQUE' => true])) ->addConstraint(new \Laminas\Db\Sql\Ddl\Constraint\PrimaryKey('id')); echo "Executing SQL:\n"; echo $sql->buildSqlString($create, $adapter->getPlatform()) . "\n"; try { // Execute the SQL $adapter->query( $sql->buildSqlString($create, $adapter->getPlatform()), Adapter::QUERY_MODE_EXECUTE ); echo "Table 'users' created successfully.\n"; } catch (\Exception $e) { echo "Error creating table: " . $e->getMessage() . "\n"; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38Note: This is a manual script for demonstration. In real projects, you would manage your schema using Laminas Migrations.
Run this script using the PHP CLI (ensure you’re in the project root or know the script’s path):
bashphp create_users_table.php
1
MySQL Integration Example
Demonstrates how to connect and query a MySQL database within a Zend Framework controller.
Configure Database Connection
Edit the
config/autoload/global.php
file to set up MySQL connection details. If adb
config already exists, modify it; if not, add:php<?php // config/autoload/global.php return [ 'db' => [ 'driver' => 'Pdo_Mysql', 'database' => 'servbay_zend_app', // Make sure the database exists 'username' => 'root', // ServBay default username 'password' => 'password', // ServBay default password 'hostname' => '127.0.0.1', 'port' => 3306, // MySQL default port 'charset' => 'utf8mb4', ], // ... other global configs ];
1
2
3
4
5
6
7
8
9
10
11
12
13
14Configure Controller Factory (module.config.php)
To inject
Laminas\Db\Adapter\Adapter
into your controller, define a factory forIndexController
. Inmodule/Application/config/module.config.php
, in thecontrollers
section, add a factory. If you already haveInvokableFactory
forIndexController
, replace it with this:php<?php // module/Application/config/module.config.php namespace Application; use Laminas\ServiceManager\Factory\InvokableFactory; // Keep this use statement if InvokableFactory is used elsewhere use Laminas\Db\Adapter\AdapterInterface; // Add this return [ // ... other configs 'controllers' => [ 'factories' => [ Controller\IndexController::class => function($container) { // Get the database adapter from the Service Manager $adapter = $container->get(AdapterInterface::class); // Create and return IndexController instance with adapter injected return new Controller\IndexController($adapter); }, // Add factories for other controllers if needed ], ], 'service_manager' => [ 'aliases' => [ // Set alias for Laminas\Db\Adapter\AdapterInterface to actual Adapter AdapterInterface::class => 'Laminas\Db\Adapter\Adapter', ], 'factories' => [ // Define factory for Laminas\Db\Adapter\Adapter 'Laminas\Db\Adapter\Adapter' => \Laminas\Db\Adapter\AdapterServiceFactory::class, ], ], // ... other configs ];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32Note: This code block should be merged into your existing
module.config.php
configuration, especially theservice_manager
part.Configure Routing (module.config.php)
In
module/Application/config/module.config.php
, add new routes for the MySQL example:php<?php // module/Application/config/module.config.php namespace Application; use Laminas\Router\Http\Literal; // ... other use statements return [ 'router' => [ 'routes' => [ // ... existing routes (e.g., 'home') 'mysql-add' => [ 'type' => Literal::class, 'options' => [ 'route' => '/mysql-add', 'defaults' => [ 'controller' => Controller\IndexController::class, 'action' => 'mysqlAdd', ], ], ], 'mysql' => [ 'type' => Literal::class, 'options' => [ 'route' => '/mysql', 'defaults' => [ 'controller' => Controller\IndexController::class, 'action' => 'mysql', ], ], ], ], ], // ... other configs (controllers, service_manager, view_manager, etc.) ];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35Add these routes within the
'routes'
subarray ofrouter
.Add Controller Methods (IndexController.php)
Modify
module/Application/src/Controller/IndexController.php
: add a constructor to receive the injectedAdapter
and add themysqlAddAction
andmysqlAction
methods:php<?php declare(strict_types=1); namespace Application\Controller; use Laminas\Mvc\Controller\AbstractActionController; use Laminas\View\Model\ViewModel; use Laminas\Db\Adapter\AdapterInterface; // Add this use Laminas\Db\Sql\Sql; // Add this class IndexController extends AbstractActionController { private $adapter; // Private property // Constructor receives AdapterInterface public function __construct(AdapterInterface $adapter) { $this->adapter = $adapter; } /** * Default action to display the welcome page. */ public function indexAction() { return new ViewModel([ 'message' => 'Hello ServBay!', ]); } /** * Action to add a user to the 'users' table via MySQL. */ public function mysqlAddAction() { $sql = new Sql($this->adapter); $insert = $sql->insert('users') ->values([ 'name' => 'ServBay Demo User', 'email' => '[email protected]', // Example email ]); $statement = $sql->prepareStatementForSqlObject($insert); $result = $statement->execute(); // Check result, return message $message = $result->getAffectedRows() > 0 ? 'MySQL User added successfully.' : 'Failed to add MySQL user.'; return new ViewModel([ 'message' => $message, ]); } /** * Action to fetch all users from the 'users' table via MySQL. */ public function mysqlAction() { $sql = new Sql($this->adapter); $select = $sql->select('users'); $statement = $sql->prepareStatementForSqlObject($select); $result = $statement->execute(); $users = []; foreach ($result as $row) { $users[] = $row; } // Convert results to JSON for the view return new ViewModel([ 'users' => json_encode($users, JSON_PRETTY_PRINT), ]); } // ... other action methods }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78Add these to the
IndexController
class.Create View Files
Create
module/Application/view/application/index/mysql-add.phtml
:php<h1><?php echo $this->message; ?></h1>
1Create
module/Application/view/application/index/mysql.phtml
:php<h1>MySQL Users</h1> <pre><?php echo $this->users; ?></pre>
1
2Access the MySQL Example
Ensure MySQL is running in ServBay. First, visit
https://servbay-zend-test.local/mysql-add
to add a user. You should see "MySQL User added successfully." Then, visithttps://servbay-zend-test.local/mysql
to view data in theusers
table. You should see the recently added user information (in JSON format).
PostgreSQL Integration Example
Demonstrates how to connect and query a PostgreSQL database from a Zend Framework controller.
Configure Database Connection
Edit
config/autoload/global.php
to configure PostgreSQL connection details. Note: To use both MySQL and PostgreSQL examples simultaneously, more advanced configuration may be needed. This example assumes you switch the'db'
config to PostgreSQL:php<?php // config/autoload/global.php return [ 'db' => [ 'driver' => 'Pdo_Pgsql', 'database' => 'servbay_zend_app', // Make sure the database exists 'username' => 'root', // ServBay default username 'password' => 'password', // ServBay default password 'hostname' => '127.0.0.1', 'port' => 5432, // PostgreSQL default port ], // ... other global configs ];
1
2
3
4
5
6
7
8
9
10
11
12
13Configure Controller Factory (module.config.php)
(Same as in the MySQL example) Ensure the
controllers
andservice_manager
configs inmodule/Application/config/module.config.php
are set up correctly soIndexController
receives the injectedAdapterInterface
.Configure Routing (module.config.php)
In
module/Application/config/module.config.php
, add new routes for the PostgreSQL example:php<?php // module/Application/config/module.config.php namespace Application; use Laminas\Router\Http\Literal; // ... other use statements return [ 'router' => [ 'routes' => [ // ... existing routes (like 'home', 'mysql-add', 'mysql') 'pgsql-add' => [ 'type' => Literal::class, 'options' => [ 'route' => '/pgsql-add', 'defaults' => [ 'controller' => Controller\IndexController::class, 'action' => 'pgsqlAdd', ], ], ], 'pgsql' => [ 'type' => Literal::class, 'options' => [ 'route' => '/pgsql', 'defaults' => [ 'controller' => Controller\IndexController::class, 'action' => 'pgsql', ], ], ], ], ], // ... other configs ];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35Add these routes within the
'routes'
subarray ofrouter
.Add Controller Methods (IndexController.php)
Edit
module/Application/src/Controller/IndexController.php
to addpgsqlAddAction
andpgsqlAction
methods:php<?php declare(strict_types=1); namespace Application\Controller; use Laminas\Mvc\Controller\AbstractActionController; use Laminas\View\Model\ViewModel; use Laminas\Db\Adapter\AdapterInterface; use Laminas\Db\Sql\Sql; class IndexController extends AbstractActionController { private $adapter; public function __construct(AdapterInterface $adapter) { $this->adapter = $adapter; } // ... existing actions (indexAction, mysqlAddAction, mysqlAction) /** * Action to add a user to the 'users' table via PostgreSQL. */ public function pgsqlAddAction() { $sql = new Sql($this->adapter); $insert = $sql->insert('users') ->values([ 'name' => 'ServBay Demo User', 'email' => '[email protected]', // Example email ]); $statement = $sql->prepareStatementForSqlObject($insert); $result = $statement->execute(); // Check result, return message $message = $result->getAffectedRows() > 0 ? 'PostgreSQL User added successfully.' : 'Failed to add PostgreSQL user.'; return new ViewModel([ 'message' => $message, ]); } /** * Action to fetch all users from the 'users' table via PostgreSQL. */ public function pgsqlAction() { $sql = new Sql($this->adapter); $select = $sql->select('users'); $statement = $sql->prepareStatementForSqlObject($select); $result = $statement->execute(); $users = []; foreach ($result as $row) { $users[] = $row; } // Convert results to JSON for the view return new ViewModel([ 'users' => json_encode($users, JSON_PRETTY_PRINT), ]); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67Add these two methods to your
IndexController
.Create View Files
Create
module/Application/view/application/index/pgsql-add.phtml
:php<h1><?php echo $this->message; ?></h1>
1Create
module/Application/view/application/index/pgsql.phtml
:php<h1>PostgreSQL Users</h1> <pre><?php echo $this->users; ?></pre>
1
2Access the PostgreSQL Example
Ensure PostgreSQL is running in ServBay. First, visit
https://servbay-zend-test.local/pgsql-add
to add a user. You should see "PostgreSQL User added successfully." Then, visithttps://servbay-zend-test.local/pgsql
to view data in theusers
table. The new user information should appear (in JSON format).
Memcached Integration Example
Demonstrates how to use Memcached for caching in a Zend Framework controller.
Install the Memcached Adapter
Use Composer in your project root to install the Laminas Cache Memcached storage adapter:
json// composer.json { "require": { "laminas/laminas-skeleton-application": "^1.0", "laminas/laminas-cache-storage-adapter-memcached": "^2.0" // Add this line // ... other dependencies }, // ... other config }
1
2
3
4
5
6
7
8
9Then run
composer update
to install dependencies:bashcomposer update
1ServBay comes with the PHP
memcached
extension pre-installed, so no extra steps are needed.Configure Routing (module.config.php)
In
module/Application/config/module.config.php
, add a new route for the Memcached example:php<?php // module/Application/config/module.config.php namespace Application; use Laminas\Router\Http\Literal; // ... other use statements return [ 'router' => [ 'routes' => [ // ... existing routes 'memcached' => [ 'type' => Literal::class, 'options' => [ 'route' => '/memcached', 'defaults' => [ 'controller' => Controller\IndexController::class, 'action' => 'memcached', ], ], ], ], ], // ... other configs ];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25Add this route within the
'routes'
subarray ofrouter
.Add Controller Method (IndexController.php)
Add a method called
memcachedAction
tomodule/Application/src/Controller/IndexController.php
:php<?php declare(strict_types=1); namespace Application\Controller; use Laminas\Mvc\Controller\AbstractActionController; use Laminas\View\Model\ViewModel; // ... other use statements (AdapterInterface, Sql) use Laminas\Cache\StorageFactory; use Laminas\Cache\Storage\StorageInterface; class IndexController extends AbstractActionController { // ... constructor and existing action methods /** * Action to demonstrate Memcached usage. */ public function memcachedAction() { // Create Memcached cache storage instance // ServBay's Memcached runs at 127.0.0.1:11211 by default $cache = StorageFactory::factory([ 'adapter' => [ 'name' => 'memcached', 'options' => [ 'servers' => [ ['127.0.0.1', 11211], ], 'ttl' => 300, // Cache time-to-live: 300 seconds ], ], 'plugins' => [ // Add some typical cache plugins 'serializer', 'exception_handler' => ['throw_exceptions' => false], ], ]); $cacheKey = 'my_memcached_data'; $cachedData = $cache->getItem($cacheKey, $success); // Try to get from cache if (!$success) { // Cache miss $cachedData = 'Hello Memcached! (Data from source, cached at ' . date('Y-m-d H:i:s') . ')'; $cache->setItem($cacheKey, $cachedData); // Store in cache $cachedData .= ' - CACHE MISS'; } else { // Cache hit $cachedData .= ' - CACHE HIT'; } return new ViewModel([ 'message' => $cachedData, ]); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58Add this method to your
IndexController
.Create View File
Create
module/Application/view/application/index/memcached.phtml
:php<h1>Memcached Example</h1> <p><?php echo $this->message; ?></p>
1
2Access the Memcached Example
Make sure Memcached is running in ServBay. Visit
https://servbay-zend-test.local/memcached
. The first time, you’ll see a message with "CACHE MISS." On subsequent visits within the cache lifetime (300 seconds), you’ll see "CACHE HIT" and the timestamp won’t change, indicating data was loaded from cache.
Redis Integration Example
Demonstrates how to use Redis for caching or storage in a Zend Framework controller.
Install the Redis Adapter
In your project root, use Composer to install the Laminas Cache Redis storage adapter:
json// composer.json { "require": { "laminas/laminas-skeleton-application": "^1.0", "laminas/laminas-cache-storage-adapter-redis": "^2.0", // Add this line "ext-redis": "*" // Ensure the PHP redis extension is installed // ... other dependencies }, // ... other config }
1
2
3
4
5
6
7
8
9
10Then run
composer update
:bashcomposer update
1ServBay pre-installs the PHP
redis
extension—no need for further installation.Configure Routing (module.config.php)
In
module/Application/config/module.config.php
, add a new route for the Redis example:php<?php // module/Application/config/module.config.php namespace Application; use Laminas\Router\Http\Literal; // ... other use statements return [ 'router' => [ 'routes' => [ // ... existing routes 'redis' => [ 'type' => Literal::class, 'options' => [ 'route' => '/redis', 'defaults' => [ 'controller' => Controller\IndexController::class, 'action' => 'redis', ], ], ], ], ], // ... other configs ];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25Add this route within the
'routes'
subarray ofrouter
.Add Controller Method (IndexController.php)
Add a
redisAction
method tomodule/Application/src/Controller/IndexController.php
:php<?php declare(strict_types=1); namespace Application\Controller; use Laminas\Mvc\Controller\AbstractActionController; use Laminas\View\Model\ViewModel; // ... other use statements use Laminas\Cache\StorageFactory; use Laminas\Cache\Storage\StorageInterface; class IndexController extends AbstractActionController { // ... constructor and existing action methods /** * Action to demonstrate Redis usage. */ public function redisAction() { // Create Redis cache storage instance // ServBay's Redis runs at 127.0.0.1:6379 by default $cache = StorageFactory::factory([ 'adapter' => [ 'name' => 'redis', 'options' => [ 'server' => [ 'host' => '127.0.0.1', 'port' => 6379, // 'database' => 0, // Redis DB index // 'password' => null, // Set password if needed ], 'ttl' => 300, // Cache TTL: 300 seconds ], ], 'plugins' => [ 'serializer', 'exception_handler' => ['throw_exceptions' => false], ], ]); $cacheKey = 'my_redis_data'; $cachedData = $cache->getItem($cacheKey, $success); // Try to get from cache if (!$success) { // Cache miss $cachedData = 'Hello Redis! (Data from source, cached at ' . date('Y-m-d H:i:s') . ')'; $cache->setItem($cacheKey, $cachedData); // Store in cache $cachedData .= ' - CACHE MISS'; } else { // Cache hit $cachedData .= ' - CACHE HIT'; } return new ViewModel([ 'message' => $cachedData, ]); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60Add this method to your
IndexController
.Create View File
Create
module/Application/view/application/index/redis.phtml
:php<h1>Redis Example</h1> <p><?php echo $this->message; ?></p>
1
2Access the Redis Example
Make sure Redis is running in ServBay. Visit
https://servbay-zend-test.local/redis
. The first visit shows "CACHE MISS." Subsequent visits within the 300-second lifespan display "CACHE HIT" and the timestamp remains unchanged, meaning the data is being read from cache.
Summary
Through the above steps, you’ve successfully created, configured, and run a Zend Framework (Laminas) project in the ServBay local development environment. You learned how to set up the website feature in ServBay to configure the web server to serve your project’s public directory, and how to integrate and use ServBay-provided MySQL and PostgreSQL databases, as well as Memcached and Redis caching services.
ServBay streamlines the setup and management of your local development environment, so you can focus on coding and project development. With its rich package offerings and flexible configuration, ServBay lets you easily simulate a production environment locally, boosting your development efficiency.