本文目录导读:

- 核心优势 (Why Platform.sh for Symfony?)
- 核心配置文件 (项目根目录)
- 环境变量适配文件 (关键)
- 本地开发与调试
- 数据库迁移与部署策略
- 常见问题与坑 (Troubleshooting)
- 性能优化建议
- 快速入门脚本
这是一个非常专业且具体的 PHP 项目部署问题,我将为你详细解析 Symfony 项目在 Platform.sh 上的云部署流程、核心配置及最佳实践。
这是目前 PHP 全栈开发中非常主流且高效的 PaaS 方案组合。
核心优势 (Why Platform.sh for Symfony?)
- 无缝集成: Platform.sh 专为 Symfony 设计,拥有官方维护的
symfony工具包和默认配置。 - 完美容器化: 自动为每个环境(开发/测试/生产/PR)生成独立的容器,环境完全隔离且复制。
- 自带 PaaS: 内置数据库(PostgreSQL/MySQL)、Redis、Elasticsearch、Solr 等服务,无需额外配置。
- 自动化部署: 原生支持 Git 驱动部署,每个分支自动生成一个预览环境,可直接访问。
- 无缝迁移: 可以零停机地进行数据库迁移、环境切换。
核心配置文件 (项目根目录)
Platform.sh 通过以下三个 YAML 文件定义整个项目的拓扑结构和构建流程。
.platform/routes.yaml
定义 HTTP 路由规则,决定域名如何连接到哪个应用。
# .platform/routes.yaml
"https://{default}/":
type: upstream
upstream: "app:http"
# 强制 HTTPS
ssl:
enabled: true
"https://www.{default}/":
type: redirect
to: "https://{default}/"
.platform/services.yaml
定义项目所需的外部服务(数据库、缓存、搜索等)。
# .platform/services.yaml
database:
# 推荐使用 PostgreSQL
type: postgresql:15
disk: 2048
cache:
# Redis 用于 Symfony 缓存/会话/锁
type: redis:7.0
search:
# 用于全文搜索 (可选)
type: elasticsearch:8.12
disk: 1024
# 可选:队列
# queue:
# type: rabbitmq:3.13
.platform.app.yaml (核心应用定义)
这是最关键的文件,定义了 PHP 版本、Symfony 构建、依赖、worker 以及磁盘挂载。
要点解读:
# .platform.app.yaml
name: app
type: 'php:8.3' # 使用最新 LTS PHP
# 基础设施
relationships:
database: "database:postgresql"
redis: "cache:redis"
elasticsearch: "search:elasticsearch"
# queue: "queue:rabbitmq"
# 构建步骤 (在 composer install 后执行)
hooks:
build: |
set -x -e
cp .env.platformsh .env.local # 复制环境变量
composer install --no-dev --optimize-autoloader
# Symfony 构建优化
php bin/console cache:clear --env=prod
php bin/console assets:install --symlink --relative public
deploy: |
# 数据库迁移 (仅在主分支或生产环境执行)
php bin/console doctrine:migrations:migrate --env=prod --no-interaction --allow-no-migration
# 预热缓存
php bin/console cache:warmup --env=prod
# Web 入口
web:
locations:
'/':
root: 'public'
passthru: '/index.php' # Symfony 入口
# 静态文件缓存 (长期缓存)
expires: 1y
scripts: false
allow: true
'/var/cache':
# 避免缓存目录被访问
deny: true
# 磁盘挂载 (持久化数据)
disk: 2048
mounts:
# Symfony 日志
'/var/log': { source: local, source_path: log }
# 用户上传文件
'/public/uploads': { source: local, source_path: uploads }
# Doctrine 结果缓存 (可选)
'/var/cache': { source: local, source_path: cache }
# Worker 进程 (可选, 处理异步任务如邮件)
workers:
messenger_consume:
commands:
# 消费 Symfony Messenger 消息
start: php bin/console messenger:consume async -vv
# 与 web 容器共享持久化数据
mounts:
'/var/log': { source: local, source_path: log }
# 环境变量注入
variables:
env:
APP_ENV: 'prod'
# 自动注入 Platform.sh 服务连接信息
DATABASE_URL: '${PLATFORM_RELATIONSHIPS:database:postgresql:url}'
REDIS_URL: '${PLATFORM_RELATIONSHIPS:redis:redis:url}'
# MAILER_DSN: 'sendmail://default' # Platform.sh 内置邮件
环境变量适配文件 (关键)
不要手动写死 DATABASE_URL,使用 symfony/psr-http-message-bridge 提供的自动配置包。
推荐方式:使用 symfony/runtime + symfony/psr-http-message-bridge
无需编写 .env.platformsh 文件,安装依赖即可:
composer require symfony/runtime symfony/psr-http-message-bridge
这样,Symfony 会自动读取 PLATFORM_RELATIONSHIPS 环境变量,并将 services.yaml 中的服务自动注入到 Symfony DI 容器中。
传统方式(手动配置 .env.local)
# 在构建钩子中运行:cp .env.platformsh .env.local
# 然后在 .env.local 中:
DATABASE_URL="${PLATFORM_RELATIONSHIPS:database:postgresql:url}"
REDIS_CACHE_URL="${PLATFORM_RELATIONSHIPS:redis:redis:url}"
ELASTICSEARCH_DSN="${PLATFORM_RELATIONSHIPS:elasticsearch:elasticsearch:url}"
MAILER_DSN="sendmail://default"
本地开发与调试
Platform.sh 提供了 platform CLI 工具,支持本地开发环境。
-
安装 CLI:
curl -fsSL https://platform.sh/cli/installer | bash
-
登录并初始化:
platform login platform project:create --title "My Symfony App"
-
本地启动 (类似 Docker Compose):
platform local:build platform local:start
这会在本地启动一个完全相同的容器化环境(PHP, PostgreSQL, Redis)。
数据库迁移与部署策略
部署时最常见的风险是 数据库 Schema 变更导致生产环境中断。
零停机迁移最佳实践 (适用于高流量站点)
-
利用
deploy钩子: 在.platform.app.yaml的deploy阶段,运行:php bin/console doctrine:migrations:migrate --env=prod --no-interaction
deploy钩子会在新容器启动且 接管旧流量之前 运行,这意味着:- 旧版本仍然在线。
- 新容器执行迁移(可能花了 5 秒)。
- 迁移成功后,路由器将流量切换到新容器。
- 整个过程对用户透明。
-
回滚策略: 如果需要回滚,Platform.sh 会自动将流量切回旧容器,但数据库迁移 回滚需要手动编写。
- 推荐方案: 遵循 可逆迁移 原则,新增字段时,不要立即使该字段 NOT NULL,而是先添加,允许 NULL,然后逐步填充,回滚时,删除该字段即可。
常见问题与坑 (Troubleshooting)
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 502 Bad Gateway | PHP-FPM 崩溃或入口文件错误 | 检查 web.locations 的 root 是否正确指向 public;查看日志:platform log --lines 100 |
| 数据库连接失败 | .platform.app.yaml 的 relationships 与 services.yaml 名称不匹配 |
确保 services.yaml 定义的 database 名称与 relationships: database: 一致 |
| Composer 内存不足 | 构建时 composer 需要大量内存 | 在 hooks.build 中添加:COMPOSER_MEMORY_LIMIT=-1 composer install ... |
| Session 丢失 | 没有配置 Redis 作为 Session 存储 | 修改 config/packages/framework.yaml:session: { handler_id: 'cache.redis' } |
| 文件上传失败 | public/uploads 目录未挂载 |
确保 .platform.app.yaml 的 mounts 正确配置并写入 public/uploads |
| HTTP 缓存不起作用 | Symfony 的 http_cache 没有挂载 |
使用 Redis 或 文件缓存作为 cache.pool;在 public/index.php 中启用反向代理。 |
性能优化建议
-
Redis 做主缓存:
# services.yaml cache: type: redis:7.0# config/packages/cache.yaml framework: cache: app: cache.adapter.redis system: cache.adapter.redis -
启用 OPCache (JIT):
# .platform.app.yaml variables: env: PHP_OPCACHE_VALIDATE_TIMESTAMPS: "0" # 生产环境禁用文件时间检查 PHP_OPCACHE_JIT: "tracing" PHP_OPCACHE_JIT_BUFFER_SIZE: "100M" -
CDN + 静态文件: 在
web.locations['/']中设置expires: 1y并开启gzip。
快速入门脚本
-
安装 Platform.sh CLI:
curl -fsSL https://platform.sh/cli/installer | bash
-
创建新项目:
platform project:create --title "my-symfony-app" --region "eu-3.platform.sh"
-
推送代码到 Platform.sh:
git remote add platform <你的 Platform.sh Git 地址> git push platform main
-
访问预览环境: Platform.sh 会自动为
main分支生成一个可访问的 URL,格式如:https://main-xxxxxxxx-xxxxxxxx-xxxx.eu-3.platformsh.site/ -
一键创建环境:
platform environment:branch feature/new-feature
对于 Symfony 项目,Platform.sh 是目前 最佳的生产级云部署方案 之一。
- 核心价值: 无需管理服务器,自动伸缩,每个分支都是一个完整环境。
- 关键文件: 围绕
routes.yaml,services.yaml,.platform.app.yaml三个文件。 - 最佳实践: 使用
symfony/runtime自动注入环境变量;利用deploy钩子实现零停机迁移;使用 Redis 做缓存和 Session。
如果你是从零开始,强烈建议使用 composer create-project symfony/skeleton . 然后运行 platform project:build,Platform.sh 会自动生成最完整的配置模板。