淺析如何創(chuàng)建和使用Shell腳本實(shí)現(xiàn)PHP部署自動(dòng)化
傳統(tǒng)部署方式的困境
如果你的 PHP 部署流程是這樣的:
- SSH 登錄服務(wù)器
git pullcomposer install- 可能跑一下
php artisan migrate - 清一些緩存
- 重載 PHP-FPM 或 nginx
- 雙手合十祈禱
這個(gè)流程能跑,直到:
- 你要管理多臺(tái)服務(wù)器
- 你需要快速回滾
- 你忘了某個(gè)小步驟,然后生產(chǎn)環(huán)境炸了
- 團(tuán)隊(duì)里其他人的操作方式跟你不太一樣
到那時(shí)候,部署就不再是一個(gè)任務(wù)了——它變成了一種儀式,脆弱、沒有文檔、而且只有"知道確切步驟"的那個(gè)人才能搞定。
Shell 腳本是解決這個(gè)問題的一種非常簡單的方式。
你不需要 Kubernetes、Terraform,也不需要一整套 CI/CD 平臺(tái)來實(shí)現(xiàn)真正的部署自動(dòng)化。一個(gè)寫得好的 shell 腳本可以:
- 把 15 條手動(dòng)命令變成一條可重復(fù)執(zhí)行的命令
- 讓你的部署過程用代碼記錄下來
- 減少人為錯(cuò)誤和"哎呀,我忘了清緩存"的時(shí)刻
- 成為后續(xù) CI/CD 流水線的構(gòu)建基礎(chǔ)
在這篇文章中,我們將講解:
- Shell 腳本基礎(chǔ)(從 PHP 開發(fā)者的角度)
- 為 PHP 應(yīng)用構(gòu)建一個(gè)簡單的部署腳本
- 用安全檢查、日志、回滾來改進(jìn)它
- 用
releases/和current/符號(hào)鏈接組織部署 - 把腳本接入 Git 或 CI
讀完之后,你會(huì)有一個(gè)可以適配到自己應(yīng)用的部署腳本——無論是 Laravel 項(xiàng)目、自定義 PHP 后端,還是其他業(yè)務(wù)系統(tǒng)。
PHP 應(yīng)用部署的核心步驟
在寫任何腳本之前,先搞清楚在你的場景下"部署"具體意味著什么會(huì)很有幫助。
在 Linux 服務(wù)器上,一個(gè)典型的 PHP 部署可能需要:
獲取代碼
- 克隆倉庫(或拉取最新更改)
- 切換到特定的分支或標(biāo)簽
安裝依賴
composer install --no-dev --optimize-autoloader- (可選)前端:
npm ci && npm run build
準(zhǔn)備環(huán)境
- 確保
.env文件存在 - 鏈接共享目錄(上傳文件、storage、日志)
運(yùn)行維護(hù)任務(wù)
- 數(shù)據(jù)庫遷移:
php artisan migrate --force - 清除/優(yōu)化緩存:
php artisan config:cache、route:cache等
切換版本并重啟服務(wù)
- 更新符號(hào)鏈接指向新版本
- 重載 PHP-FPM(
systemctl reload php-fpm) - 可能需要重啟隊(duì)列 worker
可選:回滾
- 如果出問題,能夠切換回上一個(gè)版本
你腳本的工作就是把這一切用可靠、可重復(fù)的方式編碼下來。
Shell 腳本入門(PHP 開發(fā)者視角)
如果你對(duì) PHP 很熟悉但對(duì) shell 腳本還不太了解,這里有足夠的 Bash 基礎(chǔ)讓你能上手干活。
每個(gè) shell 腳本都應(yīng)該以一行開頭,告訴系統(tǒng)用什么解釋器:
#!/usr/bin/env bash
這讓你的腳本可以像其他命令一樣執(zhí)行。
讓腳本可執(zhí)行
創(chuàng)建一個(gè)文件:
nano deploy.sh
寫入:
#!/usr/bin/env bash echo "Deploying PHP app..."
保存,然后:
chmod +x deploy.sh ./deploy.sh
你應(yīng)該會(huì)看到:
Deploying PHP app...
這樣你的第一個(gè) shell 腳本就跑起來了。
快速失?。簊et -euo pipefail
在腳本頂部(shebang 之后),加上:
set -euo pipefail
這做了三件重要的事:
-e:如果任何命令返回非零退出碼,腳本就退出-u:把未設(shè)置的變量當(dāng)作錯(cuò)誤-o pipefail:如果管道cmd1 | cmd2中cmd1失敗了,整個(gè)管道都算失敗
這就像告訴你的腳本:"如果出了任何問題,就停下來。別繼續(xù)跑然后假裝一切正常。"
變量和參數(shù)
基本變量:
APP_NAME="my-php-app" REPO_URL="git@github.com:yourname/your-app.git"
訪問位置參數(shù):
ENVIRONMENT="${1:-production}" # 如果沒提供參數(shù),默認(rèn)是 production
運(yùn)行:
./deploy.sh staging
在腳本里,$ENVIRONMENT 就是 staging。
函數(shù)
你可以用函數(shù)來組織腳本:
deploy() {
echo "Deploying to environment: $ENVIRONMENT"
}
rollback() {
echo "Rolling back..."
}
調(diào)用它們:
case "${1:-deploy}" in
deploy)
deploy
;;
rollback)
rollback
;;
*)
echo "Usage: $0 [deploy|rollback]"
exit 1
;;
esac
這種模式讓你的腳本更易讀、更好維護(hù)。
退出碼
exit 0→ 成功exit 1→ 通用失敗- 其他代碼可以表示特定錯(cuò)誤(可選但挺好)
知道了這些基礎(chǔ),你就可以開始自動(dòng)化真正的工作了。
構(gòu)建簡單的 PHP 部署腳本(單服務(wù)器)
讓我們從一個(gè)直接的場景開始:
- 單臺(tái) Linux 服務(wù)器(比如 Ubuntu)
- Nginx + PHP-FPM
- PHP 應(yīng)用在
/var/www/myapp - 你通過 SSH 登錄服務(wù)器然后運(yùn)行
./deploy.sh來部署
目錄結(jié)構(gòu)
我們先保持簡單:
/var/www/myapp/
├── .git/
├── public/
├── vendor/
├── storage/
└── ...
部署流程:
git pullcomposer install- 清緩存
- 重載 PHP-FPM
這是一個(gè)最小腳本:
#!/usr/bin/env bash
set -euo pipefail
APP_DIR="/var/www/myapp"
PHP_FPM_SERVICE="php8.2-fpm" # 根據(jù)你的 PHP 版本調(diào)整
BRANCH="${1:-main}" # 默認(rèn)分支
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
cd "$APP_DIR"
log "Fetching latest code from branch '$BRANCH'..."
git fetch --all
git checkout "$BRANCH"
git pull origin "$BRANCH" --ff-only
log "Installing PHP dependencies with Composer..."
COMPOSER_ALLOW_SUPERUSER=1 composer install \
--no-dev \
--prefer-dist \
--optimize-autoloader
# 如果你用的是 Laravel 或其他框架,添加框架特定的步驟:
if [[ -f artisan ]]; then
log "Running database migrations..."
php artisan migrate --force
log "Clearing and caching Laravel configuration..."
php artisan config:clear
php artisan config:cache
php artisan route:cache || true # route cache 在開發(fā)環(huán)境可能會(huì)失敗
fi
log "Reloading PHP-FPM service..."
sudo systemctl reload "$PHP_FPM_SERVICE"
log "Deployment completed successfully."
用法:
chmod +x deploy.sh ./deploy.sh # 部署 main 分支 ./deploy.sh production # 如果你想用名為 'production' 的分支
這已經(jīng)比手動(dòng)運(yùn)行每條命令好多了:
- 步驟在腳本里清晰可見
- 如果出問題會(huì)快速失敗
- 任何有權(quán)限的人都能運(yùn)行同樣的流程
但我們可以大幅改進(jìn)它。
增強(qiáng)安全性:備份、檢查與回滾
上面的簡單腳本有個(gè)大問題:如果遷移掛了或者部署半途出問題,你唯一的回滾方式是"希望你有備份"。
讓我們開始加安全網(wǎng)。
開頭的健全性檢查
在腳本頂部,在做任何危險(xiǎn)操作之前,檢查:
- 你沒有意外地在錯(cuò)誤的服務(wù)器上運(yùn)行
- 必需的二進(jìn)制文件存在(git、composer、php、systemctl)
示例:
check_requirements() {
local bins=("git" "composer" "php" "systemctl")
for bin in "${bins[@]}"; do
if ! command -v "$bin" >/dev/null 2>&1; then
echo "Error: required binary '$bin' not found in PATH."
exit 1
fi
done
}
盡早調(diào)用 check_requirements:
check_requirements
你也可以斷言環(huán)境:
if [[ "$(hostname)" != "prod-app-1" ]]; then
echo "Warning: this does not look like the production server ($(hostname))."
# sleep 5 或者 exit;你自己選
fi
數(shù)據(jù)庫備份(可選但推薦)
對(duì)于小型系統(tǒng),你可以在遷移之前快速做個(gè)數(shù)據(jù)庫備份:
backup_database() {
local backup_dir="/var/backups/myapp"
mkdir -p "$backup_dir"
local filename="${backup_dir}/db-$(date '+%Y%m%d-%H%M%S').sql.gz"
log "Creating database backup at $filename..."
# MySQL 示例 - 調(diào)整憑據(jù)
mysqldump -u myuser -p'mypassword' mydatabase | gzip > "$filename"
}
在遷移之前調(diào)用 backup_database。
(正式環(huán)境一般會(huì)用托管備份,這里只是展示思路。)
回滾策略(基礎(chǔ))
在非常簡單的設(shè)置上(沒有 releases 目錄),回滾很棘手。這就是為什么很多團(tuán)隊(duì)會(huì)轉(zhuǎn)向 releases + 符號(hào)鏈接的模式,我們接下來會(huì)講。
現(xiàn)在只需要知道:最好的回滾策略是避免就地修改"當(dāng)前"代碼。相反,你把新代碼部署到一個(gè)單獨(dú)的目錄,然后在一切通過健康檢查后切換符號(hào)鏈接。
讓我們進(jìn)入那個(gè)模式。
基于版本目錄的零停機(jī)部署
一個(gè)非常常見的部署模式(受 Capistrano、Envoyer、Deployer 等工具啟發(fā))是:
在 releases/ 中保留多個(gè)應(yīng)用版本
有一個(gè) current 符號(hào)鏈接指向當(dāng)前活躍的版本
部署時(shí):
- 創(chuàng)建一個(gè)新的
releases/20251127-153000/目錄 - 在那里安裝代碼 + 依賴
- 運(yùn)行遷移、構(gòu)建資源等
- 更新
current指向新版本 - 可選保留幾個(gè)舊版本用于回滾
目錄結(jié)構(gòu):
/var/www/myapp/
├── releases/
│ ├── 2025-11-27-153000/
│ └── 2025-11-26-112030/
├── shared/
│ ├── .env
│ ├── storage/
│ └── uploads/
└── current -> releases/2025-11-27-153000/
Nginx 指向 /var/www/myapp/current/public。
使用 releases 的部署腳本
這是一個(gè)使用這種模式的更高級(jí)腳本:
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="myapp"
BASE_DIR="/var/www/${APP_NAME}"
RELEASES_DIR="${BASE_DIR}/releases"
SHARED_DIR="${BASE_DIR}/shared"
CURRENT_LINK="${BASE_DIR}/current"
REPO_URL="git@github.com:yourname/your-app.git"
PHP_FPM_SERVICE="php8.2-fpm"
KEEP_RELEASES=5
TIMESTAMP="$(date '+%Y-%m-%d-%H%M%S')"
NEW_RELEASE_DIR="${RELEASES_DIR}/${TIMESTAMP}"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
run_composer() {
COMPOSER_ALLOW_SUPERUSER=1 composer install \
--no-dev \
--prefer-dist \
--optimize-autoloader
}
link_shared() {
log "Linking shared files and directories..."
# 鏈接 .env
if [[ -f "${SHARED_DIR}/.env" ]]; then
ln -s "${SHARED_DIR}/.env" "${NEW_RELEASE_DIR}/.env"
fi
# 鏈接 storage(Laravel 用)
if [[ -d "${SHARED_DIR}/storage" ]]; then
rm -rf "${NEW_RELEASE_DIR}/storage"
ln -s "${SHARED_DIR}/storage" "${NEW_RELEASE_DIR}/storage"
fi
# 鏈接 uploads 或其他共享資源
if [[ -d "${SHARED_DIR}/uploads" ]]; then
mkdir -p "${NEW_RELEASE_DIR}/public"
ln -s "${SHARED_DIR}/uploads" "${NEW_RELEASE_DIR}/public/uploads"
fi
}
run_laravel_tasks() {
if [[ -f artisan ]]; then
log "Running Laravel migrations..."
php artisan migrate --force
log "Optimizing Laravel caches..."
php artisan config:clear
php artisan config:cache
php artisan route:cache || true
php artisan view:cache || true
fi
}
update_symlink() {
log "Updating current symlink to ${NEW_RELEASE_DIR}..."
ln -sfn "${NEW_RELEASE_DIR}" "${CURRENT_LINK}"
}
cleanup_old_releases() {
log "Cleaning up old releases, keeping last ${KEEP_RELEASES}..."
cd "${RELEASES_DIR}"
ls -1dt */ | tail -n +$((KEEP_RELEASES + 1)) | xargs -r rm -rf
}
deploy() {
log "Starting deployment to ${BASE_DIR}..."
mkdir -p "${RELEASES_DIR}" "${SHARED_DIR}"
log "Creating new release directory at ${NEW_RELEASE_DIR}..."
git clone --depth=1 "${REPO_URL}" "${NEW_RELEASE_DIR}"
cd "${NEW_RELEASE_DIR}"
log "Installing composer dependencies..."
run_composer
link_shared
run_laravel_tasks
update_symlink
log "Reloading PHP-FPM..."
sudo systemctl reload "${PHP_FPM_SERVICE}"
cleanup_old_releases
log "Deployment finished successfully. New release: ${TIMESTAMP}"
}
deploy
這個(gè)腳本做了什么:
- 把你的倉庫克隆到一個(gè)帶時(shí)間戳的文件夾
- 在那里安裝依賴
- 從
shared/目錄鏈接.env、storage和uploads - 運(yùn)行遷移和緩存(Laravel 用)
- 把
current切換指向新版本 - 清理舊版本以免撐爆磁盤
要手動(dòng)回滾,你可以:
1.列出版本:
ls -1 /var/www/myapp/releases
2.把 current 指向舊版本:
ln -sfn /var/www/myapp/releases/2025-11-26-112030 /var/www/myapp/current sudo systemctl reload php8.2-fpm
你甚至可以把回滾腳本化(比如"回到上一個(gè)版本"),通過檢查 releases/ 目錄來實(shí)現(xiàn)。
多環(huán)境部署(staging 與 production)
大多數(shù)團(tuán)隊(duì)至少有:
- staging(或 test)
- production
你可以重用同一個(gè)腳本,但按環(huán)境參數(shù)化。
使用 ENV 參數(shù)
擴(kuò)展變量:
ENVIRONMENT="${1:-production}"
case "$ENVIRONMENT" in
production)
BASE_DIR="/var/www/myapp"
PHP_FPM_SERVICE="php8.2-fpm"
REPO_URL="git@github.com:yourname/your-app.git"
;;
staging)
BASE_DIR="/var/www/myapp-staging"
PHP_FPM_SERVICE="php8.2-fpm"
REPO_URL="git@github.com:yourname/your-app.git"
;;
*)
echo "Unknown environment: $ENVIRONMENT"
exit 1
;;
esac
然后調(diào)用:
./deploy.sh staging ./deploy.sh production
在腳本內(nèi)部,其他所有東西都用 $BASE_DIR、$REPO_URL 等。
為每個(gè)環(huán)境使用不同的 .env 文件
在 shared/ 里,你可以有:
/var/www/myapp/shared/
├── .env.production
└── .env.staging
然后在 link_shared() 里:
ENV_FILE="${SHARED_DIR}/.env.${ENVIRONMENT}"
if [[ -f "${ENV_FILE}" ]]; then
ln -s "${ENV_FILE}" "${NEW_RELEASE_DIR}/.env"
else
echo "Warning: env file ${ENV_FILE} not found."
fi
這讓環(huán)境配置保持干凈和明確。
集成 PHP 生態(tài)工具
你的 shell 腳本通常會(huì)編排你已經(jīng)熟悉的工具:Composer、Artisan、cron、supervisord 等。
優(yōu)化 Composer
你可以通過添加標(biāo)志讓 Composer 更快更可預(yù)測:
run_composer() {
COMPOSER_ALLOW_SUPERUSER=1 composer install \
--no-dev \
--prefer-dist \
--classmap-authoritative \
--no-interaction \
--no-progress
}
處理隊(duì)列和 worker
如果你使用隊(duì)列(比如 Laravel 隊(duì)列 worker 或 Horizon),部署后你可能需要重啟 worker。
用 supervisor 管理的 Laravel 隊(duì)列 worker 示例:
restart_workers() {
log "Restarting queue workers via supervisor..."
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart all
}
或者就:
php artisan queue:restart
把這加到你的 run_laravel_tasks() 或單獨(dú)的步驟里。
Cron 任務(wù)
如果你依賴 cron 調(diào)用 php artisan schedule:run,不需要做特別的事——cron 會(huì)在下次運(yùn)行時(shí)自動(dòng)使用新的 current 符號(hào)鏈接。
只要確保你的 cron 條目指向 current 路徑,而不是特定的版本:
* * * * * cd /var/www/myapp/current && php artisan schedule:run >> /dev/null 2>&1
接入 CI/CD 系統(tǒng)
一旦你的腳本在 SSH 上可靠運(yùn)行,集成到 CI 就很簡單。
GitHub Actions 通過 SSH 部署
一個(gè)非常簡化的工作流:
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Add SSH key
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Deploy via SSH
run: |
ssh -o StrictHostKeyChecking=no deploy@your-server.com \
"cd /var/www/myapp && ./deploy.sh production"
CI 不需要知道你的部署邏輯;它只需要運(yùn)行你的腳本。
GitLab CI
# .gitlab-ci.yml
stages:
- deploy
deploy_production:
stage: deploy
only:
- main
script:
- ssh deploy@your-server.com "cd /var/www/myapp && ./deploy.sh production"
shell 腳本就是部署流程的唯一規(guī)范。
日志、通知與故障排查
一個(gè)靜默失敗的部署腳本和手動(dòng)部署一樣可怕。
記錄日志到文件
你可以用一個(gè)簡單的日志機(jī)制包裝你的腳本:
LOG_DIR="${BASE_DIR}/logs"
LOG_FILE="${LOG_DIR}/deploy-$(date '+%Y-%m-%d').log"
mkdir -p "$LOG_DIR"
# 在最頂部(在其他所有東西之前):
exec > >(tee -a "$LOG_FILE") 2>&1
這會(huì)把 stdout 和 stderr 都重定向到日志文件(同時(shí)仍然打印到終端)。
現(xiàn)在每次運(yùn)行都會(huì)被記錄,包括錯(cuò)誤信息。
Slack/Discord 通知
你可以用 curl 在部署成功或失敗后發(fā)送一個(gè)簡單的 webhook。
Slack webhook 調(diào)用示例:
notify_slack() {
local status="$1" # "success" 或 "failure"
local webhook_url="https://hooks.slack.com/services/XXX/YYY/ZZZ"
local emoji=":white_check_mark:"
if [[ "$status" == "failure" ]]; then
emoji=":x:"
fi
curl -X POST -H 'Content-type: application/json' \
--data "{
\"text\": \"${emoji} Deploy ${status} for ${APP_NAME} on $(hostname) at $(date '+%Y-%m-%d %H:%M:%S')\"
}" \
"$webhook_url" >/dev/null 2>&1 || true
}
然后使用 Bash trap:
trap 'notify_slack failure' ERR trap 'notify_slack success' EXIT
現(xiàn)在每當(dāng)部署運(yùn)行時(shí)你的團(tuán)隊(duì)都會(huì)收到消息。
(實(shí)際上你可能需要比“EXIT 時(shí)總是 success”更精細(xì)的控制,不過這里先這樣。)
Shell 腳本的局限與進(jìn)階方向
Shell 腳本是很好的第一步,但你應(yīng)該知道它們的局限。
Shell 腳本的適用場景
- 單臺(tái)或少量服務(wù)器
- 簡單的部署拓?fù)洌ㄒ粋€(gè)應(yīng)用,一個(gè)數(shù)據(jù)庫)
- 你的團(tuán)隊(duì)主要是后端開發(fā)和系統(tǒng)管理員
- 你想要快速、易懂的自動(dòng)化,不需要額外工具
需要進(jìn)階的場景
- 很多服務(wù)器,復(fù)雜的環(huán)境
- 復(fù)雜的網(wǎng)絡(luò)、負(fù)載均衡、藍(lán)綠部署
- 基礎(chǔ)設(shè)施即代碼(Terraform、Ansible 等)
- Kubernetes 或容器編排
在那些世界里,shell 腳本仍然有用——但它們通常變成膠水代碼,而不是主要的部署機(jī)制。
好消息是:你現(xiàn)在編碼的部署邏輯(運(yùn)行什么、按什么順序、什么必須成功)如果你后來轉(zhuǎn)向 Deployer、GitHub Actions 工作流、Ansible 或任何其他工具,仍然是有價(jià)值的。這些精力不會(huì)白費(fèi),你是在把部署流程文檔化。
總結(jié)
讓我們回顧一下我們構(gòu)建了什么:
1. 你學(xué)習(xí)了專門用于部署的 shell 腳本基礎(chǔ):
#!/usr/bin/env bash、set -euo pipefail、函數(shù)、參數(shù)
2. 你從一個(gè)簡單腳本開始:
git pullcomposer install- 運(yùn)行遷移和緩存任務(wù)
- 重載 PHP-FPM
3. 然后你把它演進(jìn)成了一個(gè)更健壯的系統(tǒng),使用:
releases/目錄和current符號(hào)鏈接- 用于
.env、storage和uploads的共享目錄 - 自動(dòng)清理舊版本
你讓它具有環(huán)境感知,用單個(gè)腳本處理 staging 和 production。
你集成了 PHP 生態(tài)工具,如 Composer、Artisan、隊(duì)列和 cron。
你把腳本接入了 CI,這樣部署就變成了 push + 流水線,而不是"SSH 然后祈禱"。
你添加了日志和通知,這樣部署就不是黑盒了。
4. 結(jié)果看起來很簡單:
./deploy.sh production
但在這一條命令背后,是一套清晰的、受版本控制的流程,完整定義了你的 PHP 應(yīng)用如何從 Git 到達(dá)線上服務(wù)器。
你不需要一次性采納這篇文章里的每個(gè)想法。一個(gè)你可以遵循的不錯(cuò)的進(jìn)階路徑:
- 從一個(gè)小小的
deploy.sh開始,只是把你當(dāng)前的手動(dòng)步驟包裝起來 - 添加
set -euo pipefail和一些基本的日志 - 向
releases/+current/結(jié)構(gòu)演進(jìn),以獲得更安全的部署和回滾 - 按環(huán)境參數(shù)化
- 最后,把腳本接入 CI
以上就是淺析如何創(chuàng)建和使用Shell腳本實(shí)現(xiàn)PHP部署自動(dòng)化的詳細(xì)內(nèi)容,更多關(guān)于Shell腳本自動(dòng)化部署PHP的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
php防止sql注入示例分析和幾種常見攻擊正則表達(dá)式
這篇文章主要介紹了php防止sql注入漏洞代碼和分析,最近提供了幾種常見攻擊的正則表達(dá)式,大家參考使用吧2014-01-01
從零開始學(xué)YII2框架(六)高級(jí)應(yīng)用程序模板
這篇文章主要介紹了YII2框架學(xué)習(xí)筆記之高級(jí)應(yīng)用程序模板,深入淺出從安裝,配置到使用方法都做了介紹,希望對(duì)大家有所幫助2014-08-08
淺談PHP鏈表數(shù)據(jù)結(jié)構(gòu)(單鏈表)
下面小編就為大家?guī)硪黄獪\談PHP鏈表數(shù)據(jù)結(jié)構(gòu)(單鏈表)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06
php實(shí)現(xiàn)批量下載百度云盤文件例子分享
本文使用百度開放云的PHP SDK實(shí)現(xiàn)批量下載百度云盤的文件,需要的朋友可以參考下。2014-04-04
tp5.1 框架數(shù)據(jù)庫高級(jí)查詢技巧實(shí)例總結(jié)
這篇文章主要介紹了tp5.1 框架數(shù)據(jù)庫高級(jí)查詢技巧,結(jié)合實(shí)例形式總結(jié)分析了tp5.1 框架數(shù)據(jù)庫快捷查詢、區(qū)間查詢、批量查詢、閉包查詢等相關(guān)高級(jí)查詢使用技巧,需要的朋友可以參考下2020-05-05
PHP新特性之字節(jié)碼緩存和內(nèi)置服務(wù)器
這篇文章主要介紹了PHP新特性之字節(jié)碼緩存和內(nèi)置服務(wù)器的相關(guān)資料,需要的朋友可以參考下2017-08-08

