本文目录导读:

我来为您详细介绍如何使用 Laravel Spark 快速搭建 SaaS 项目。
环境准备
系统要求
- PHP >= 8.1 - Laravel >= 10.x - MySQL >= 5.7 或 PostgreSQL - Composer - Node.js & NPM
安装 Laravel
# 创建项目 composer create-project laravel/laravel my-saas # 进入项目目录 cd my-saas # 配置环境变量 cp .env.example .env php artisan key:generate
安装 Laravel Spark
通过 Composer 安装
# 添加 Spark 仓库 composer require laravel/spark # 发布配置文件 php artisan vendor:publish --tag=spark-config php artisan vendor:publish --tag=spark-migrations # 运行迁移 php artisan migrate # 安装前端资源 npm install npm run dev
配置 Stripe(支付)
# .env 文件中配置 STRIPE_KEY=your_stripe_key STRIPE_SECRET=your_stripe_secret STRIPE_WEBHOOK_SECRET=your_webhook_secret
基础配置
创建 Plan 配置
// config/spark.php
<?php
return [
'bills' => [
'stripe' => [
'plans' => [
[
'name' => 'Basic',
'short_reference' => 'basic',
'monthly_price' => 9.00,
'yearly_price' => 90.00,
'features' => [
'1 Project',
'5GB Storage',
'Basic Support'
]
],
[
'name' => 'Pro',
'short_reference' => 'pro',
'monthly_price' => 29.00,
'yearly_price' => 290.00,
'features' => [
'Unlimited Projects',
'100GB Storage',
'Priority Support',
'API Access'
]
],
],
],
],
];
配置用户模型
// app/Models/User.php
<?php
namespace App\Models;
use Laravel\Spark\Billable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Billable;
protected $fillable = [
'name',
'email',
'password',
'trial_ends_at',
];
protected $hidden = [
'password',
'remember_token',
];
}
创建 SaaS 核心功能
多租户支持
// app/Traits/TenantTrait.php
<?php
namespace App\Traits;
use Illuminate\Support\Facades\Auth;
trait TenantTrait
{
protected static function bootTenantTrait()
{
static::creating(function ($model) {
if (Auth::check() && empty($model->user_id)) {
$model->user_id = Auth::id();
}
});
static::addGlobalScope('user', function ($builder) {
if (Auth::check()) {
$builder->where('user_id', Auth::id());
}
});
}
}
订阅管理控制器
// app/Http/Controllers/SubscriptionController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Laravel\Spark\Spark;
class SubscriptionController extends Controller
{
public function subscribe(Request $request)
{
$request->validate([
'plan' => 'required|string',
'payment_method' => 'required|string'
]);
try {
$user = $request->user();
// 创建订阅
$subscription = $user->newSubscription(
$request->plan,
$request->plan
)->create($request->payment_method);
return response()->json([
'success' => true,
'subscription' => $subscription
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => $e->getMessage()
], 422);
}
}
public function cancel(Request $request)
{
$user = $request->user();
$user->subscription()->cancel();
return response()->json(['success' => true]);
}
}
前端页面设置
路由配置
// routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\SubscriptionController;
Route::middleware(['auth'])->group(function () {
// 仪表盘
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
// 订阅管理
Route::get('/settings/subscription', function () {
return view('subscription');
})->name('subscription');
Route::post('/subscribe', [SubscriptionController::class, 'subscribe'])->name('subscribe');
Route::post('/cancel-subscription', [SubscriptionController::class, 'cancel'])->name('cancel-subscription');
});
订阅页面视图
{{-- resources/views/subscription.blade.php --}}
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">订阅管理</div>
<div class="card-body">
@if(auth()->user()->subscribed())
<div class="alert alert-success">
当前订阅: {{ auth()->user()->subscription()->stripe_plan }}
</div>
<button class="btn btn-danger" onclick="handleCancel()">
取消订阅
</button>
@else
<form method="POST" action="{{ route('subscribe') }}" id="subscription-form">
@csrf
<div class="form-group">
<label>选择套餐</label>
<select name="plan" class="form-control" required>
<option value="basic">基础版 - $9/月</option>
<option value="pro">专业版 - $29/月</option>
</select>
</div>
<div class="form-group mt-3">
<label>支付方式</label>
<div id="card-element"></div>
</div>
<button type="submit" class="btn btn-primary mt-3">
立即订阅
</button>
</form>
@endif
</div>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
<script>
const stripe = Stripe('{{ config('services.stripe.key') }}');
const elements = stripe.elements();
const card = elements.create('card');
card.mount('#card-element');
const form = document.getElementById('subscription-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const {token} = await stripe.createToken(card);
// 添加 token 到表单
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = 'payment_method';
hiddenInput.value = token.id;
form.appendChild(hiddenInput);
// 提交表单
form.submit();
});
</script>
@endpush
中间件配置
订阅检查中间件
// app/Http/Middleware/CheckSubscription.php
<?php
namespace App\Http\Middleware;
use Closure;
class CheckSubscription
{
public function handle($request, Closure $next)
{
if (!$request->user()->subscribed()) {
return redirect()->route('subscription')
->with('error', '请先订阅才能访问此功能');
}
return $next($request);
}
}
管理后台功能
管理员面板
// app/Http/Controllers/Admin/DashboardController.php
<?php
namespace App\Http\Controllers\Admin;
use App\Models\User;
use App\Models\Subscription;
use Illuminate\Http\Request;
class DashboardController extends Controller
{
public function index()
{
$stats = [
'total_users' => User::count(),
'active_subscriptions' => Subscription::where('status', 'active')->count(),
'monthly_revenue' => Subscription::where('status', 'active')->sum('amount'),
];
return view('admin.dashboard', compact('stats'));
}
}
Webhook 处理
// app/Http/Controllers/WebhookController.php
<?php
namespace App\Http\Controllers;
use Laravel\Spark\Spark;
use Illuminate\Http\Request;
class WebhookController extends Controller
{
public function handleStripeWebhook(Request $request)
{
$payload = json_decode($request->getContent(), true);
// 处理不同事件
switch ($payload['type']) {
case 'invoice.payment_succeeded':
// 更新订阅状态
break;
case 'customer.subscription.deleted':
// 处理订阅取消
break;
}
return response()->json(['received' => true]);
}
}
部署建议
生产环境优化
# 优化配置 php artisan config:cache php artisan route:cache php artisan view:cache # 使用队列 php artisan queue:work redis # 定时任务 (crontab) * * * * * cd /path-to-project && php artisan schedule:run >> /dev/null 2>&1
数据库优化
-- 添加索引 ALTER TABLE subscriptions ADD INDEX idx_user_id (user_id); ALTER TABLE subscriptions ADD INDEX idx_status (status);
安全建议
-
API 限流
// app/Http/Kernel.php 'api' => [ 'throttle:60,1', 'bindings', ],
-
数据加密
// 加密敏感数据 $encrypted = encrypt($sensitiveData);
-
审计日志
-
定期备份
Laravel Spark 提供了完整的 SaaS 解决方案,包括:
- ✅ 订阅计费系统
- ✅ 多租户支持
- ✅ 发票管理
- ✅ 客户门户
- ✅ 管理后台
建议根据实际需求调整配置,确保系统安全和性能,如果需要更详细的功能实现,请告诉我具体需求!