Creating and Running a ThinkPHP 8 Project in ServBay 
This article guides you through using ServBay—a powerful local web development environment—to quickly create, configure, and run a PHP project based on the ThinkPHP 8 framework. ServBay comes pre-configured with PHP, web servers (Caddy or Nginx), and multiple databases, greatly simplifying the local setup process for ThinkPHP projects.
What is ThinkPHP? 
ThinkPHP is an open-source, fast, and straightforward object-oriented PHP development framework originating from China. It follows a principle of simplicity and efficiency, providing developers with a user-friendly toolkit for building modern web applications. Thanks to its ease-of-use, robust features (such as a powerful ORM, flexible routing, built-in template engine, caching support, etc.), and an active community, ThinkPHP enjoys wide adoption in the Chinese PHP development sphere.
Key Features and Benefits of ThinkPHP 
- Simplicity & Efficiency: The framework is designed for clean code and structured architecture, making it easy to understand, maintain, and accelerate development.
- Comprehensive Functionality: Features all essential web development components like MVC structure, ORM, template engine, cache, session management, access control, form tokens, and more.
- Powerful ORM: Provides an easy-to-use and feature-rich Object Relational Mapping to simplify database operations.
- Flexible Routing: Supports multiple routing methods to handle complex URL structures.
- Rich Ecosystem: Includes numerous extension libraries and plugins, with a large, active developer community and abundant resources.
- Continuous Updates: Frequent framework updates keep pace with developments in PHP and the broader web ecosystem.
ThinkPHP is suitable for both small projects and large-scale enterprise web applications.
Setting Up a ThinkPHP 8 Project with ServBay 
ServBay offers an ideal local development environment for ThinkPHP 8 projects, featuring:
- Pre-installed PHP (multiple versions) and commonly used extensions.
- Built-in web server (Caddy or Nginx) for easy website configuration.
- Integrated database services including MySQL, PostgreSQL, MongoDB, Redis, Memcached, and more.
- Composer dependency manager included.
This guide leverages these ServBay features to quickly build your ThinkPHP 8 project.
Prerequisites 
Before you begin, ensure you have completed the following steps:
- Downloaded and installed ServBay on macOS or Windows.
- ServBay is running, and the required PHP version (ThinkPHP 8 requires PHP 8.0 or higher) as well as any needed database services (such as MySQL, PostgreSQL, Redis, Memcached, etc.) are started. You can check and activate these services under the “Packages” tab in the ServBay control panel.
Creating a ThinkPHP Project 
ServBay recommends storing all your local site files in the /Applications/ServBay/www directory. This helps ServBay organize and manage your sites more efficiently.
- Ensure Composer is Installed - ServBay comes with Composer pre-installed, so you typically won’t need to install it separately. Run - composer --versionin the ServBay terminal to confirm Composer is available.
- Create a ThinkPHP Project Using Composer - Open the macOS Terminal, and execute the following commands to create a new ThinkPHP 8 project in the ServBay web root: bash- cd /Applications/ServBay/www composer create-project topthink/think servbay-thinkphp-app1
 2- This will create a new - servbay-thinkphp-appfolder in- /Applications/ServBay/www, and download the core ThinkPHP 8 files and dependencies.
- Enter the Project Directory - After creation, navigate into your new project directory: bash- cd /Applications/ServBay/www/servbay-thinkphp-app1
Initial Project Configuration 
Once your project is created, some basic configuration steps are required.
- Configure Database Connection - ThinkPHP’s database configuration is usually found in the - config/database.phpfile. Edit this file to set your connection details according to the database service started in ServBay.- Below is a sample configuration for ServBay’s default MySQL service: php- <?php // config/database.php return [ // Default database connection configuration 'default' => env('database.driver', 'mysql'), // Database connections 'connections' => [ 'mysql' => [ // Database type 'type' => 'mysql', // Server address 'hostname' => env('database.hostname', '127.0.0.1'), // Database name 'database' => env('database.database', 'servbay_thinkphp_app'), // It’s recommended to create a separate DB for your project // Username 'username' => env('database.username', 'root'), // Password 'password' => env('database.password', 'password'), // ServBay default password, use for local development only! // Port 'hostport' => env('database.hostport', '3306'), // ... other settings ... ], // ... other database connection 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- Important Notes: - Change the value of databaseto the actual database name you’ve created for your project (for example, use ServBay’s phpMyAdmin or Adminer to createservbay_thinkphp_app).
- ServBay’s default rootpassword ispassword. This password is for local development only—never use it for production! In production, always set strong passwords and create users with minimal required permissions.
- If you manage environment variables with a .envfile, ensure its settings override those inconfig/database.php.
 
- Change the value of 
Configuring the Web Server 
The entry point for ThinkPHP is public/index.php, and URL rewriting (Rewrite rules) are required for routing. As ThinkPHP rules differ from straightforward static file delivery, you should use ServBay’s built-in Rewrite rules.
In your site’s settings interface, select ThinkPHP from the Rewrite Rules dropdown, and click Save.
For detailed steps, refer to Adding Your First Website.
Adding Sample Code 
To test your site configuration and ThinkPHP’s basic routing and features, add a simple route and controller to your project.
Edit /Applications/ServBay/www/servbay-thinkphp-app/route/app.php, and define a simple GET route:
php
<?php
// route/app.php
use think\facade\Route;
// Define servbay route; when visiting /servbay, execute anonymous function
Route::get('servbay', function () {
    return 'Hello ServBay!';
});
// ... other routes ...1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Accessing Your Website 
Once the steps above are completed, open your web browser and access your configured local domain and test route:
https://thinkphp.servbay.demo/servbay
If everything is set up correctly, you’ll see Hello ServBay! output. This means your ThinkPHP 8 project is successfully running in ServBay, with both the web server and PHP-FPM configured properly.
NoSQL Database Examples 
ServBay includes built-in NoSQL databases like Memcached and Redis. ThinkPHP provides a convenient cache abstraction layer, making it easy to use these NoSQL services as cache drivers.
Memcached Example 
- Install Memcached Extension - ServBay’s PHP package comes with Memcached extension pre-installed. Just make sure the Memcached service is started via the “Packages” tab in the ServBay control panel. 
- Configure Memcached Caching - Edit - config/cache.phpto set ThinkPHP’s cache driver to Memcached:php- <?php // config/cache.php return [ // Default cache driver 'default' => env('cache.driver', 'memcached'), // Cache connection settings 'stores' => [ 'memcached' => [ // Type of cache 'type' => 'memcached', // Server list 'host' => '127.0.0.1', // ServBay Memcached default address 'port' => 11211, // ServBay Memcached default port 'persistent' => false, 'expire' => 0, 'timeout' => 0, 'prefix' => '', ], // ... other cache configs ... ], ];1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
- Using Memcached Cache in Code - In your controller or route callback, use ThinkPHP’s - CacheFacade to work with Memcached:php- <?php use think\facade\Cache; use think\facade\Route; Route::get('/memcached-example', function () { // Set cache, valid for 600 seconds Cache::set('my_memcached_key', 'This value is from Memcached!', 600); // Get cache $value = Cache::get('my_memcached_key'); return 'Value from Memcached: ' . $value; });1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- Visit - https://thinkphp.servbay.demo/memcached-exampleto test.
Redis Example 
- Install Redis Extension - ServBay’s PHP package comes with Redis extension pre-installed. Just make sure the Redis service is running via the “Packages” tab in ServBay. 
- Configure Redis Caching - Edit - config/cache.phpto set ThinkPHP’s cache driver to Redis:php- <?php // config/cache.php return [ // Default cache driver 'default' => env('cache.driver', 'redis'), // Cache connection settings 'stores' => [ 'redis' => [ // Type of cache 'type' => 'redis', // Server address 'host' => env('cache.host', '127.0.0.1'), // ServBay Redis default address // Port 'port' => env('cache.port', 6379), // ServBay Redis default port // Password (ServBay default: none) 'password' => env('cache.password', ''), // ServBay Redis default: none 'select' => 0, 'timeout' => 0, 'expire' => 0, 'persistent' => false, 'prefix' => '', ], // ... other cache 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- Note: By default, ServBay’s Redis is installed without a password. If you manually set a password for Redis, update the - passwordfield here.
- Using Redis Cache in Code - In your controller or route callback, use ThinkPHP’s - CacheFacade to interact with Redis:php- <?php use think\facade\Cache; use think\facade\Route; Route::get('/redis-example', function () { // Set cache, permanent (or pass an expiry as the third parameter) Cache::set('my_redis_key', 'Hello from Redis!'); // Get cache $value = Cache::get('my_redis_key'); return 'Value from Redis: ' . $value; });1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- Visit - https://thinkphp.servbay.demo/redis-exampleto test.
Relational Database Examples 
ServBay integrates popular relational databases like MySQL and PostgreSQL. ThinkPHP’s ORM makes it easy to interact with these databases.
Using ThinkPHP’s Database Migration Tool 
In ThinkPHP, you can use a migration tool to manage database schema changes, making teamwork and version control much easier.
- Install the Migration Tool - Use Composer to install ThinkPHP’s migration extension in the project root: bash- cd /Applications/ServBay/www/servbay-thinkphp-app composer require topthink/think-migration1
 2
- Create a Migration File - Use ThinkPHP’s CLI to generate a migration file, e.g. for a - userstable:bash- php think migrate:create CreateUserTable1- This creates a new PHP file in - database/migrations, with a timestamped filename such as- 20231027100000_create_user_table.php.
- Edit the Migration File - Open your new migration file in - database/migrations, and define the- up()method with your table structure:php- <?php // database/migrations/YYYYMMDDHHMMSS_create_user_table.php use think\migration\Migrator; use think\migration\db\Column; class CreateUserTable extends Migrator { /** * Change Method. * * Write your reversible migrations using this method. * * More information on writing migrations is available here: * http://docs.phinx.org/en/latest/migrations.html#the-change-method * * The following commands can be used in this method and Phinx will * automatically reverse them when rolling back: * * createTable * renameTable * addColumn * addCustomColumn * renameColumn * addIndex * addForeignKey * createDatabase * renameDatabase * dropTable * dropColumn * dropIndex * dropForeignKey */ public function change() { // Create a new table using createTable $table = $this->table('users'); $table->addColumn('name', 'string', ['limit' => 50, 'comment' => 'User name']) ->addColumn('email', 'string', ['limit' => 100, 'comment' => 'Email address']) ->addIndex(['email'], ['unique' => true]) // Add unique index ->addTimestamps() // Add created_at and updated_at fields ->create(); // Execute creation } // Alternatively, you can define up() and down() methods instead of change() /* public function up() { $table = $this->table('users'); $table->addColumn('name', 'string', ['limit' => 50, 'comment' => 'User name']) ->addColumn('email', 'string', ['limit' => 100, 'comment' => 'Email address']) ->addIndex(['email'], ['unique' => true]) ->addTimestamps() ->create(); } public function down() { $this->dropTable('users'); } */ }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
- Run Database Migrations - In the ServBay terminal, make sure you’re in the project root, then run the migration command: bash- php think migrate:run1- Once successful, you’ll see the newly created - userstable in your database.
MySQL Example 
Assuming MySQL service is running in ServBay and you’ve configured the MySQL connection in config/database.php as described earlier.
- Configure MySQL Connection - Refer to the earlier “Initial Project Configuration” MySQL sample and make sure the connection info in - config/database.phpis correct.
- Add User Data in Code - Use ThinkPHP’s - DbFacade or ORM models to insert data. Here’s a sample using the Db Facade:php- <?php use think\facade\Db; use think\facade\Route; Route::get('/mysql-add-user', function () { try { Db::table('users')->insert([ 'name' => 'ServBay Demo User', 'email' => 'demo@servbay.demo', // Use brand sample email 'created_at' => date('Y-m-d H:i:s'), // Manually add timestamps if addTimestamps() didn't autofill 'updated_at' => date('Y-m-d H:i:s'), ]); return 'User added successfully!'; } catch (\Exception $e) { return 'Error adding user: ' . $e->getMessage(); } });1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- Visit - https://thinkphp.servbay.demo/mysql-add-userto test data insertion.
- Read User Data in Code - Use the Db Facade or ORM models to query data: php- <?php use think\facade\Db; use think\facade\Route; Route::get('/mysql-users', function () { $users = Db::table('users')->select(); // Retrieve all users return json($users); // Return results as JSON });1
 2
 3
 4
 5
 6
 7
 8- Visit - https://thinkphp.servbay.demo/mysql-usersto view data from the- userstable.
PostgreSQL Example 
Assuming PostgreSQL service is running in ServBay and you’ve configured the PostgreSQL connection.
- Configure PostgreSQL Connection - In - config/database.php, ensure you have the following (or appropriately adjusted for your setup):php- <?php // config/database.php (partial) return [ // ... other configs ... 'connections' => [ // ... MySQL config ... 'pgsql' => [ // Database type 'type' => 'pgsql', // Server address 'hostname' => env('database.hostname', '127.0.0.1'), // Database name 'database' => env('database.database', 'servbay_thinkphp_app'), // Recommended to create a separate DB for your project // Username 'username' => env('database.username', 'root'), // Password 'password' => env('database.password', 'password'), // ServBay default password, for local development only! // Port 'hostport' => env('database.hostport', '5432'), // PostgreSQL default port // ... other settings ... ], // ... other database 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- Important Notes: - Like MySQL, create a dedicated PostgreSQL database for your project and specify it here.
- ServBay’s default PostgreSQL root password is also password. Use it only for local development.
 
- Add User Data in Code - Use the - DbFacade or ORM models, and specify the- pgsqlconnection:php- <?php use think\facade\Db; use think\facade\Route; Route::get('/pgsql-add-user', function () { try { Db::connect('pgsql')->table('users')->insert([ // Use the pgsql connection 'name' => 'ServBay PgSQL User', 'email' => 'pgsql-demo@servbay.demo', // Use brand sample email // PostgreSQL timestamp fields may need to be filled manually depending on migration and ThinkPHP version 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), ]); return 'PostgreSQL User added successfully!'; } catch (\Exception $e) { return 'Error adding PostgreSQL user: ' . $e->getMessage(); } });1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18- Visit - https://thinkphp.servbay.demo/pgsql-add-userto test data insertion.
- Read User Data in Code - Use - DbFacade or ORM models, specifying the- pgsqlconnection:php- <?php use think\facade\Db; use think\facade\Route; Route::get('/pgsql-users', function () { $users = Db::connect('pgsql')->table('users')->select(); // Retrieve data using pgsql connection return json($users); // Return results as JSON });1
 2
 3
 4
 5
 6
 7
 8- Visit - https://thinkphp.servbay.demo/pgsql-usersto view PostgreSQL data in the- userstable.
Summary 
Following these steps, you’ve successfully created, configured, and run a ThinkPHP 8 project using ServBay for local development. You’ve learned how to use ServBay’s built-in Composer to create a project, configure the Caddy web server to handle ThinkPHP routing, and connect to ServBay’s integrated MySQL, PostgreSQL, Memcached, and Redis database services.
ServBay greatly streamlines setting up local development environments for PHP frameworks like ThinkPHP, allowing you to focus on crafting business logic. You’re now ready to continue developing your ThinkPHP application and make the most of ServBay’s rich software packages and features.
