Yii 2.0 提供兩種官方專案模板:**Basic** (單一應用、適合中小專案) 與 **Advanced** (前後台分離、多環境、適合大型專案)。本文以 **Basic 模板** 為主,涵蓋 Composer 安裝、需求檢查、入口腳本、URL 美化 (隱藏 index.php)、Nginx/Apache 配置、多環境參數化、常見部署坑點。
pdo, mbstring, intl, gd 或 imagick, openssl, curl。composer self-update)。# 快速檢查 php -m | grep -E 'pdo|mbstring|intl|gd|openssl|curl' php -r "echo 'PHP ' . PHP_VERSION . PHP_EOL;" composer --version
# 建議:指定穩定版本 composer create-project --prefer-dist yiisoft/yii2-app-basic myapp "2.0.*" # 進入目錄 cd myapp # 執行需求檢查 (會檢查 PHP 版本、擴展、目錄權限) php requirements.php # 或瀏覽器開啟 https://localhost/myapp/requirements.php
myapp/
├── assets/ # AssetBundle 發布後的公開資源 (JS/CSS)
├── commands/ # Console Command 類別
├── config/ # 配置檔
│ ├── console.php # Console 應用配置
│ ├── db.php # 資料庫配置 (獨立檔案,建議 gitignore)
│ ├── params.php # 參數配置
│ ├── web.php # Web 應用主配置
│ └── ...
├── controllers/ # Controller 類別
├── models/ # Model 類別 (ActiveRecord, Form)
├── runtime/ # 執行期產生檔案 (log, cache, debug) - 需寫入權限
├── tests/ # 單元/功能測試
├── vendor/ # Composer 依賴
├── views/ # View 檔案
│ ├── layouts/ # 佈局
│ └── site/ # SiteController 對應視圖
├── web/ # **Web 根目錄 (DocumentRoot)**
│ ├── index.php # 入口腳本
│ ├── favicon.ico
│ └── robots.txt
└── yii # Console 入口腳本
<?php
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=yii2basic;charset=utf8mb4',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
'tablePrefix' => 'tbl_',
'enableSchemaCache' => YII_ENV_PROD,
'schemaCacheDuration' => 3600,
'schemaCache' => 'cache',
];
<?php
$params = require __DIR__ . '/params.php';
$db = require __DIR__ . '/db.php';
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'aliases' => [
'@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset',
],
'components' => [
'request' => [
'cookieValidationKey' => 'your-secret-key-here', // 必填,用於 Cookie 簽名
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
],
'cache' => [
'class' => 'yii\caching\FileCache', // 生產建議 Redis/Memcached
],
'user' => [
'identityClass' => 'app\models\User',
'enableAutoLogin' => true,
'identityCookie' => ['name' => '_identity', 'httpOnly' => true],
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '@app/mail',
'useFileTransport' => true, // 開發環境存檔而非寄送
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
'logFile' => '@app/runtime/logs/app.log',
'maxFileSize' => 1024 * 1024 * 10, // 10MB
'maxLogFiles' => 20,
],
],
],
'db' => $db,
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false, // 隱藏 index.php
'enableStrictParsing' => false,
'rules' => [
'' => 'site/index',
'/' => '/',
'/' => '/view',
],
],
],
'params' => $params,
'modules' => [
'gridview' => ['class' => 'kartik\grid\Module'], // 若安裝 kartik-v/yii2-grid
],
];
if (YII_ENV_DEV) {
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = ['class' => 'yii\debug\Module', 'allowedIPs' => ['127.0.0.1', '::1']];
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = ['class' => 'yii\gii\Module', 'allowedIPs' => ['127.0.0.1', '::1']];
}
return $config;
server {
listen 80;
server_name myapp.local;
root /var/www/myapp/web; # 指向 web 目錄
index index.php;
charset utf-8;
client_max_body_size 20M;
access_log /var/log/nginx/myapp_access.log;
error_log /var/log/nginx/myapp_error.log;
location / {
# 嘗試直接服務檔案,否則轉給 index.php
try_files $uri $uri/ /index.php$is_args$args;
}
# 禁止存取隱藏檔案、框架核心目錄
location ~ /\.(htaccess|svn|git) { deny all; }
location ~ ^/(protected|framework|vendor|runtime) { deny all; }
# PHP 處理
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock; # 或 127.0.0.1:9000
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
}
# 靜態資源快取
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}
RewriteEngine On
# 禁止存取隱藏檔案
RewriteRule ^\.(htaccess|svn|git) - [F,L]
# 禁止存取框架核心目錄
RewriteRule ^(protected|framework|vendor|runtime) - [F,L]
# 如果是實體檔案/目錄直接服務
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# 否則轉給 index.php
RewriteRule . index.php [L]
Apache 需啟用 mod_rewrite 並允許 AllowOverride All。
# 1. 環境變數區分 (推薦)
# .env (不納入 git)
APP_ENV=production
DB_HOST=prod-db
DB_PASS=secret
# config/db.php 讀取環境變數
'dsn' => 'mysql:host=' . getenv('DB_HOST') . ';dbname=myapp;charset=utf8mb4',
'password' => getenv('DB_PASS'),
# 2. 部署腳本 (Deployer / GitLab CI / GitHub Actions)
# 共享目錄
set('shared_dirs', ['runtime', 'web/assets']);
set('shared_files', ['.env', 'config/db.php']);
# 執行遷移
php yii migrate/up --interactive=0
# 清除快取
php yii cache/flush-all
php yii cache/flush-schema
| 現象 | 原因 | 解決 |
|---|---|---|
| 首頁 404 / No input file specified | Nginx root 未指向 web/、fastcgi_param SCRIPT_FILENAME 錯誤 | root /path/web; SCRIPT_FILENAME $document_root$fastcgi_script_name; |
| assets 目錄 403/404 | web/assets 權限不足、AssetBundle 未發布 | chown -R www-data:www-data web/assets runtime; php yii asset/compress |
| Cookie 無法寫入 / CSRF 驗證失敗 | cookieValidationKey 未設定、domain 不匹配、SameSite 限制 | 設定 cookieValidationKey、同站部署、HTTPS 環境設定 SameSite=Lax |
| Migration 失敗 "Base table or view not found" | tablePrefix 設定與實際表名不符 | 確認 config/db.php tablePrefix、Migration 中使用 {{%table}} |
| Gii/Debug 403 Forbidden | allowedIPs 未包含客戶端 IP | config/web.php 加入 'allowedIPs' => ['*'] (僅開發) 或實際 IP |
YII_ENV=prod、YII_DEBUG=false (環境變數或 index.php 定義)。composer install --no-dev --optimize-autoloader。yii\caching\RedisCache)。yii\web\DbSession 或 RedisSession)。php yii migrate/up、php yii cache/flush-schema。yii\debug\Module 僅開發開啟,生產用 APM (DataDog, NewRelic, Pinpoint)。