1 Composer in Depth
Composer is the dependency management tool for PHP and the cornerstone of the entire modern PHP ecosystem. It handles downloading and installing third-party packages and automatically generates autoload files.
npm is to Node.js, pip is to Python, and Maven/Gradle is to Java. The config file composer.json is equivalent to package.json / requirements.txt. The lock file composer.lock is equivalent to package-lock.json.
Common Commands
# 初始化项目(交互式生成 composer.json)
composer init
# 安装一个包(自动写入 composer.json 并下载)
composer require guzzlehttp/guzzle
# 安装开发依赖(仅开发环境使用)
composer require --dev phpunit/phpunit
# 根据 composer.lock 安装所有依赖(部署时使用)
composer install
# 更新依赖到最新兼容版本
composer update
# 更新 autoload 映射(添加新类后)
composer dump-autoload
composer.json Structure
{
"name": "myvendor/myproject",
"description": "我的 PHP 项目",
"type": "project",
"require": {
"php": ">=8.4",
"guzzlehttp/guzzle": "^7.8",
"monolog/monolog": "^3.0",
"nesbot/carbon": "~3.0"
},
"require-dev": {
"phpunit/phpunit": "^11.0"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}
Version Constraints
| Symbol | Meaning | Example |
|---|---|---|
^ |
Compatible update (won't break major version) | ^7.8 → >=7.8.0 <8.0.0 |
~ |
Allow last digit to grow | ~3.0 → >=3.0.0 <4.0.0 |
* |
Wildcard | 3.* → any 3.x version |
| Exact version | Lock to specific version | 3.7.2 |
PSR-4 Autoloading
After configuring autoload.psr-4, you only need to include vendor/autoload.php and all classes will be autoloaded:
<?php
// 项目入口文件
require __DIR__ . '/vendor/autoload.php';
// 直接使用,无需手动 require 每个文件
use App\Services\UserService;
use App\Models\User;
$service = new UserService();
$user = $service->findById(1);
Directory mapping: namespace App\Services\UserService maps to file src/Services/UserService.php.
2 Guzzle — HTTP Client
Guzzle is the most popular HTTP client library for PHP, providing a clean API for sending HTTP requests, handling responses, and supporting async concurrency.
composer require guzzlehttp/guzzle
Basic Usage
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
$client = new Client([
'base_uri' => 'https://api.example.com',
'timeout' => 5.0,
]);
// GET 请求
$response = $client->get('/users', [
'query' => ['page' => 1, 'limit' => 10],
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
]);
$statusCode = $response->getStatusCode(); // 200
$body = json_decode($response->getBody(), true); // 解析 JSON
// POST 请求(发送 JSON)
$response = $client->post('/users', [
'json' => [
'name' => '张三',
'email' => 'zhangsan@example.com',
],
]);
// POST 表单数据
$response = $client->post('/login', [
'form_params' => [
'username' => 'admin',
'password' => 'secret',
],
]);
Exception Handling
<?php
try {
$response = $client->get('/users/999');
} catch (RequestException $e) {
if ($e->hasResponse()) {
$error = json_decode($e->getResponse()->getBody(), true);
echo "错误: " . $error['message'];
} else {
echo "请求失败: " . $e->getMessage();
}
}
Async Requests
<?php
use GuzzleHttp\Promise\Utils;
$promises = [
'users' => $client->getAsync('/users'),
'products' => $client->getAsync('/products'),
'orders' => $client->getAsync('/orders'),
];
// 并发执行所有请求
$results = Utils::unwrap($promises);
$users = json_decode($results['users']->getBody(), true);
$products = json_decode($results['products']->getBody(), true);
$orders = json_decode($results['orders']->getBody(), true);
cURL to send requests. In real projects, Guzzle is recommended — the API is cleaner, with built-in retry, connection pooling, async, and other advanced features.
3 Monolog — Logging Library
Monolog is the standard logging library for PHP (following the PSR-3 interface), supporting output to files, databases, Slack, email, and many other targets. Frameworks like Laravel and Symfony include Monolog by default.
composer require monolog/monolog
Basic Usage
<?php
require 'vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Formatter\LineFormatter;
// 创建日志通道
$log = new Logger('app');
// Handler 1:所有日志写入文件
$log->pushHandler(new StreamHandler(__DIR__ . '/logs/app.log', Logger::DEBUG));
// Handler 2:错误日志单独归档,按天轮转,保留 30 天
$errorHandler = new RotatingFileHandler(
__DIR__ . '/logs/error.log',
30, // 保留天数
Logger::ERROR // 最低记录级别
);
$log->pushHandler($errorHandler);
// 写入日志
$log->debug('调试信息', ['module' => 'auth']);
$log->info('用户登录成功', ['user_id' => 42]);
$log->warning('缓存命中率低', ['rate' => 0.35]);
$log->error('数据库连接失败', ['host' => 'db.example.com']);
$log->critical('支付网关无响应');
Log Levels (Low to High)
| Level | Usage |
|---|---|
DEBUG | Detailed debug information |
INFO | Key business events (user login, order creation) |
NOTICE | Normal but noteworthy events |
WARNING | Anomalies that don't affect operation |
ERROR | Runtime errors that need fixing |
CRITICAL | Critical component unavailable |
ALERT | Requires immediate action |
EMERGENCY | System is unusable |
Custom Formatting
<?php
$formatter = new LineFormatter(
"[%datetime%] %channel%.%level_name%: %message% %context%\n",
'Y-m-d H:i:s'
);
$handler = new StreamHandler(__DIR__ . '/logs/app.log', Logger::DEBUG);
$handler->setFormatter($formatter);
$log = new Logger('app');
$log->pushHandler($handler);
// 输出: [2026-03-31 10:30:00] app.INFO: 用户登录成功 {"user_id":42}
4 Carbon — Date & Time
Carbon is an enhanced wrapper around PHP's DateTime, providing an extremely fluent API for date and time handling. It comes integrated by default in Laravel.
composer require nesbot/carbon
dayjs / moment.js is to JavaScript, and pendulum / arrow is to Python. PHP's native DateTime has limited functionality, and Carbon fills the gap.
Creating & Formatting
<?php
require 'vendor/autoload.php';
use Carbon\Carbon;
// 创建实例
$now = Carbon::now(); // 当前时间
$today = Carbon::today(); // 今天 00:00:00
$date = Carbon::create(2026, 3, 31, 10, 30); // 指定时间
$parsed = Carbon::parse('2026-03-31 10:30:00');
// 格式化输出
echo $now->format('Y-m-d H:i:s'); // 2026-03-31 10:30:00
echo $now->toDateString(); // 2026-03-31
echo $now->toDateTimeString(); // 2026-03-31 10:30:00
echo $now->isoFormat('YYYY年MM月DD日'); // 2026年03月31日
Date Arithmetic
<?php
$now = Carbon::now();
// 加减运算
$tomorrow = $now->copy()->addDay();
$nextWeek = $now->copy()->addWeek();
$lastMonth = $now->copy()->subMonth();
$future = $now->copy()->addDays(45)->addHours(3);
// 链式操作
$deadline = Carbon::parse('2026-12-31')
->subDays(7)
->startOfDay(); // 2026-12-24 00:00:00
Comparison & Differences
<?php
$start = Carbon::parse('2026-01-01');
$end = Carbon::parse('2026-03-31');
echo $start->diffInDays($end); // 89
echo $start->diffInMonths($end); // 2
echo $start->diffForHumans($end); // "2个月前"
// 布尔判断
$date = Carbon::parse('2026-03-31');
$date->isWeekday(); // true
$date->isToday(); // true (假设今天是 3/31)
$date->isFuture(); // false
$date->isPast(); // false
$date->isLeapYear(); // false
// 比较
$a = Carbon::parse('2026-01-01');
$b = Carbon::parse('2026-06-01');
$a->lt($b); // true (less than)
$a->gte($b); // false (greater than or equal)
Timezone Handling
<?php
$beijing = Carbon::now('Asia/Shanghai');
$newYork = $beijing->copy()->setTimezone('America/New_York');
echo $beijing->format('Y-m-d H:i'); // 2026-03-31 22:30
echo $newYork->format('Y-m-d H:i'); // 2026-03-31 10:30
add/sub methods modify the original object. If you need to preserve the original date, use copy() first, or use the immutable version CarbonImmutable.
5 PHPUnit — Unit Testing
PHPUnit is the de facto standard testing framework for PHP, supporting unit testing, mocking, code coverage, and more.
# 安装为开发依赖
composer require --dev phpunit/phpunit
# 运行测试
./vendor/bin/phpunit
phpunit.xml Configuration
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
colors="true"
stopOnFailure="false">
<testsuites>
<testsuite name="Unit">
<directory>tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory>src</directory>
</include>
</source>
</phpunit>
Writing Test Classes
<?php
// tests/CalculatorTest.php
namespace Tests;
use PHPUnit\Framework\TestCase;
use App\Calculator;
class CalculatorTest extends TestCase
{
private Calculator $calc;
// 每个测试方法执行前调用
protected function setUp(): void
{
$this->calc = new Calculator();
}
// 每个测试方法执行后调用
protected function tearDown(): void
{
// 清理资源(如果需要)
}
public function testAdd(): void
{
$this->assertEquals(5, $this->calc->add(2, 3));
$this->assertEquals(0, $this->calc->add(-1, 1));
}
public function testDivide(): void
{
$this->assertEquals(2.5, $this->calc->divide(5, 2));
}
public function testDivideByZeroThrowsException(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('除数不能为零');
$this->calc->divide(10, 0);
}
}
Common Assertions
<?php
// 相等性
$this->assertEquals('hello', $result); // 值相等(== 宽松比较)
$this->assertSame('hello', $result); // 类型+值完全相同(===)
// 布尔
$this->assertTrue($user->isActive());
$this->assertFalse($user->isBanned());
$this->assertNull($user->deletedAt());
// 数组
$this->assertCount(3, $items);
$this->assertContains('admin', $roles);
$this->assertArrayHasKey('email', $data);
$this->assertEmpty($errors);
// 类型与实例
$this->assertInstanceOf(User::class, $result);
$this->assertIsString($name);
$this->assertIsArray($list);
// 字符串
$this->assertStringContainsString('error', $message);
$this->assertMatchesRegularExpression('/^\d{4}-\d{2}/', $date);
Data Providers
<?php
use PHPUnit\Framework\Attributes\DataProvider;
class MathTest extends TestCase
{
public static function additionProvider(): array
{
return [
'正数相加' => [3, 4, 7],
'负数相加' => [-1, -2, -3],
'零加任意数' => [0, 5, 5],
'大数相加' => [PHP_INT_MAX, 0, PHP_INT_MAX],
];
}
#[DataProvider('additionProvider')]
public function testAdd(int $a, int $b, int $expected): void
{
$this->assertSame($expected, $a + $b);
}
}
# 运行特定测试文件
./vendor/bin/phpunit tests/CalculatorTest.php
# 运行特定方法
./vendor/bin/phpunit --filter testAdd
# 显示详细输出
./vendor/bin/phpunit --testdox
6 vlucas/phpdotenv — Environment Variables
phpdotenv loads environment variables from a .env file, separating sensitive configuration (database passwords, API keys) from code.
composer require vlucas/phpdotenv
.env File Example
# .env(不要提交到 Git!加入 .gitignore)
APP_NAME=MyApp
APP_ENV=production
APP_DEBUG=false
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=myapp
DB_USERNAME=root
DB_PASSWORD=secret
REDIS_HOST=127.0.0.1
API_KEY=sk-xxxxxxxxxxxx
Loading & Usage
<?php
require 'vendor/autoload.php';
// 加载 .env 文件(通常在应用入口处执行一次)
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
// 必须存在的变量(缺少则抛异常)
$dotenv->required(['DB_HOST', 'DB_DATABASE', 'DB_USERNAME']);
// 读取环境变量(三种方式)
$dbHost = $_ENV['DB_HOST']; // 推荐
$dbHost = $_SERVER['DB_HOST']; // 也可以
$dbHost = getenv('DB_HOST'); // 传统方式
// 实际使用
$dsn = sprintf(
'mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4',
$_ENV['DB_HOST'],
$_ENV['DB_PORT'],
$_ENV['DB_DATABASE']
);
$pdo = new PDO($dsn, $_ENV['DB_USERNAME'], $_ENV['DB_PASSWORD']);
Best Practices
✅ Recommended
- • Add
.envto.gitignore - • Provide
.env.exampleas a template - • Use
required()to validate essential variables - • Use real environment variables in production instead of .env
❌ Avoid
- • Committing
.envto version control - • Hardcoding passwords or keys in code
- • Calling
load()multiple times outside the entry file - • Storing large text blocks in .env
7 Other Recommended Libraries
The PHP ecosystem has many high-quality libraries. Here are some frequently used in real projects:
symfony/console
A framework for building CLI tools, supporting argument parsing, colored output, progress bars, and interactive prompts.
composer require symfony/console
league/flysystem
Filesystem abstraction layer providing a unified API for local disk, S3, FTP, Alibaba Cloud OSS, and more.
composer require league/flysystem
ramsey/uuid
Generates RFC 4122 standard UUIDs (v4 random, v7 time-ordered), widely used for distributed IDs.
composer require ramsey/uuid
respect/validation
A fluent data validation library with chainable API for validating email, phone, length, range, and more.
composer require respect/validation
predis/predis
A pure PHP Redis client that connects to Redis without requiring any C extensions.
composer require predis/predis
intervention/image
An image processing library supporting crop, resize, watermark, and format conversion with an elegant API.
composer require intervention/image
Quick Examples
<?php
// ramsey/uuid - 生成 UUID
use Ramsey\Uuid\Uuid;
$uuid = Uuid::uuid4()->toString(); // "550e8400-e29b-41d4-a716-446655440000"
$uuid7 = Uuid::uuid7()->toString(); // 时间排序的 UUID v7
// respect/validation - 数据验证
use Respect\Validation\Validator as v;
$valid = v::email()->validate('user@example.com'); // true
$valid = v::stringType()->length(2, 50)->validate('张三'); // true
$valid = v::numericVal()->between(1, 100)->validate(42); // true
// predis/predis - Redis 操作
$redis = new Predis\Client(['host' => '127.0.0.1']);
$redis->set('user:1:name', '张三');
$redis->expire('user:1:name', 3600);
$name = $redis->get('user:1:name'); // "张三"
8 PHP Framework Overview
After mastering PHP fundamentals, choosing a framework can dramatically boost development efficiency. Here are the three most popular frameworks today:
| Framework | Type | Features | Use Cases | Learning Curve |
|---|---|---|---|---|
| Laravel | Full-stack | Elegant syntax, Eloquent ORM, Blade templates, queues, broadcasting, rich ecosystem | Web apps, SaaS, API backends | ⭐⭐ Medium |
| Symfony | Full-stack | Enterprise-grade, component-based design, highly configurable, long-term support | Large enterprise projects, complex business systems | ⭐⭐⭐ Higher |
| Slim | Micro-framework | Lightweight, routing + middleware only, freedom to choose components | REST APIs, microservices, small projects | ⭐ Simple |
Quick Project Creation
# Laravel
composer create-project laravel/laravel my-app
cd my-app && php artisan serve # 启动开发服务器 http://localhost:8000
# Symfony
composer create-project symfony/skeleton my-app
cd my-app && symfony server:start
# Slim
composer require slim/slim slim/psr7
Slim Micro-Framework Example
<?php
// public/index.php
require __DIR__ . '/../vendor/autoload.php';
use Slim\Factory\AppFactory;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
$app = AppFactory::create();
$app->addErrorMiddleware(true, true, true);
$app->get('/', function (Request $request, Response $response) {
$response->getBody()->write(json_encode(['message' => '你好,PHP!']));
return $response->withHeader('Content-Type', 'application/json');
});
$app->get('/users/{id}', function (Request $request, Response $response, array $args) {
$userId = $args['id'];
$response->getBody()->write(json_encode(['id' => $userId]));
return $response->withHeader('Content-Type', 'application/json');
});
$app->run();
- • Beginners or building APIs → Slim (lightweight, fewer concepts, quick start)
- • Rapid web app development → Laravel (richest ecosystem, most active community, excellent docs)
- • Large enterprise projects → Symfony (rigorous architecture, suitable for complex business)
- • After completing this tutorial, we recommend starting with Laravel or Slim for hands-on practice
9 Chapter Summary
📦 Composer
- •
requireto install,installto deploy - •
^/~semantic version constraints - • PSR-4 autoloading maps classes to files
🌐 Guzzle
- • GET/POST requests, JSON handling
- • Async concurrent requests
- • Best alternative to raw cURL
📋 Monolog
- • PSR-3 standard logging interface
- • Handlers control output targets
- • 8 levels from DEBUG to EMERGENCY
📅 Carbon
- • Enhanced DateTime wrapper
- • Fluent chainable date operations
- •
copy()to avoid modifying the original
🧪 PHPUnit
- •
TestCase+assert*methods - • Data Provider parameterized tests
- •
setUp/tearDownmanage test lifecycle
🔒 phpdotenv
- • Load env variables from
.envfiles - • Separate sensitive config from code
- • Don't commit
.env; do commit.env.example
🎉 Congratulations on completing the PHP Quick Tutorial!
You've mastered the core knowledge of PHP 8.4 — from environment setup, basic syntax, functions & OOP, database operations, network programming, file processing, to the Composer ecosystem and essential tool libraries.
Next Steps:
- Build a complete REST API project using Slim or Laravel
- Write PHPUnit tests for your project and adopt test-driven habits
- Read the PHP-FIG PSR Standards to learn community best practices
- Explore more open-source packages on Packagist