You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Laravel 5.5开发带自动分相册功能的图库系统?

实现Laravel 5.5图库系统的分步指南

嘿,这个需求挺常见的,我来一步步给你捋清楚怎么在Laravel 5.5里实现它:

1. 数据库设计

首先得搞定两张核心表:albums(相册表)和photos(照片表)。咱们先写迁移文件:

相册表迁移

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAlbumsTable extends Migration
{
    public function up()
    {
        Schema::create('albums', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title'); // 相册标题
            $table->unsignedInteger('cover_photo_id')->nullable(); // 封面照片ID
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('albums');
    }
}

照片表迁移

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePhotosTable extends Migration
{
    public function up()
    {
        Schema::create('photos', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedInteger('album_id'); // 关联相册ID
            $table->string('path'); // 图片存储路径
            $table->timestamps();

            $table->foreign('album_id')->references('id')->on('albums')->onDelete('cascade');
        });
    }

    public function down()
    {
        Schema::dropIfExists('photos');
    }
}

运行迁移:php artisan migrate

2. 模型与关联

创建两个模型并设置Eloquent关联:

Album模型(app/Album.php)

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Album extends Model
{
    protected $fillable = ['title', 'cover_photo_id'];

    // 相册拥有多张照片
    public function photos()
    {
        return $this->hasMany(Photo::class);
    }

    // 获取封面照片
    public function coverPhoto()
    {
        return $this->belongsTo(Photo::class, 'cover_photo_id');
    }
}

Photo模型(app/Photo.php)

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Photo extends Model
{
    protected $fillable = ['album_id', 'path'];

    // 照片属于一个相册
    public function album()
    {
        return $this->belongsTo(Album::class);
    }
}

3. 路由与控制器逻辑

先定义路由(routes/web.php):

// 展示相册列表
Route::get('/albums', 'AlbumController@index')->name('albums.index');
// 展示上传表单
Route::get('/albums/create', 'AlbumController@create')->name('albums.create');
// 处理上传并创建相册
Route::post('/albums', 'AlbumController@store')->name('albums.store');
// 展示相册详情
Route::get('/albums/{album}', 'AlbumController@show')->name('albums.show');

接下来创建AlbumController:

<?php

namespace App\Http\Controllers;

use App\Album;
use App\Photo;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class AlbumController extends Controller
{
    // 展示所有相册
    public function index()
    {
        $albums = Album::with('coverPhoto')->get();
        return view('albums.index', compact('albums'));
    }

    // 展示上传表单
    public function create()
    {
        return view('albums.create');
    }

    // 处理上传并创建相册
    public function store(Request $request)
    {
        // 验证输入
        $request->validate([
            'title' => 'required|string|max:255',
            'photos' => 'required|array',
            'photos.*' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048' // 限制图片类型和大小
        ]);

        // 创建相册
        $album = Album::create([
            'title' => $request->title
        ]);

        // 处理上传的图片
        $photos = $request->file('photos');
        $firstPhotoId = null;

        foreach ($photos as $photo) {
            // 存储图片到storage/app/public/photos目录
            $path = $photo->store('photos', 'public');
            
            // 创建照片记录
            $photoModel = Photo::create([
                'album_id' => $album->id,
                'path' => $path
            ]);

            // 记录第一张照片的ID作为封面
            if (is_null($firstPhotoId)) {
                $firstPhotoId = $photoModel->id;
            }
        }

        // 更新相册封面
        $album->update(['cover_photo_id' => $firstPhotoId]);

        // 重定向到相册列表页
        return redirect()->route('albums.index')->with('success', '相册创建成功!');
    }

    // 展示相册详情
    public function show(Album $album)
    {
        $album->load('photos');
        return view('albums.show', compact('album'));
    }
}

别忘了创建软链接让public目录能访问storage里的图片:php artisan storage:link

4. 视图文件

现在来写视图,放在resources/views/albums目录下:

相册列表页(index.blade.php)

<!DOCTYPE html>
<html>
<head>
    <title>图库系统</title>
    <style>
        .album-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
            gap: 20px;
            padding: 20px;
        }
        .album-card {
            border: 1px solid #ddd;
            border-radius: 8px;
            overflow: hidden;
            text-decoration: none;
            color: #333;
        }
        .album-cover {
            width: 100%;
            height: 200px;
            object-fit: cover;
        }
        .album-title {
            padding: 10px;
            text-align: center;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <h1>我的相册</h1>
    <a href="{{ route('albums.create') }}">创建新相册</a>
    
    @if(session('success'))
        <p style="color: green;">{{ session('success') }}</p>
    @endif

    <div class="album-grid">
        @foreach($albums as $album)
            <a href="{{ route('albums.show', $album) }}" class="album-card">
                <img src="{{ asset('storage/' . $album->coverPhoto->path) }}" alt="{{ $album->title }}" class="album-cover">
                <div class="album-title">{{ $album->title }}</div>
            </a>
        @endforeach
    </div>
</body>
</html>

上传表单页(create.blade.php)

<!DOCTYPE html>
<html>
<head>
    <title>创建新相册</title>
</head>
<body>
    <h1>创建新相册</h1>
    <form action="{{ route('albums.store') }}" method="POST" enctype="multipart/form-data">
        @csrf
        <div>
            <label>相册标题:</label>
            <input type="text" name="title" value="{{ old('title') }}" required>
            @error('title')
                <p style="color: red;">{{ $message }}</p>
            @enderror
        </div>
        <div>
            <label>选择照片(可多选):</label>
            <input type="file" name="photos[]" multiple required>
            @error('photos')
                <p style="color: red;">{{ $message }}</p>
            @enderror
            @error('photos.*')
                <p style="color: red;">{{ $message }}</p>
            @enderror
        </div>
        <button type="submit">创建相册</button>
    </form>
    <a href="{{ route('albums.index') }}">返回相册列表</a>
</body>
</html>

相册详情页(show.blade.php)

<!DOCTYPE html>
<html>
<head>
    <title>{{ $album->title }}</title>
    <style>
        .photo-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 15px;
            padding: 20px;
        }
        .photo-item {
            width: 100%;
            height: 150px;
            object-fit: cover;
            border-radius: 4px;
        }
    </style>
</head>
<body>
    <h1>{{ $album->title }}</h1>
    <a href="{{ route('albums.index') }}">返回相册列表</a>

    <div class="photo-grid">
        @foreach($album->photos as $photo)
            <img src="{{ asset('storage/' . $photo->path) }}" alt="照片" class="photo-item">
        @endforeach
    </div>
</body>
</html>

这样一套下来,就实现了你要的功能:每次上传照片时创建新相册,相册展示标题和首张照片,点击相册查看所有照片。你可以根据自己的需求调整样式、验证规则或者存储路径哦。

内容的提问来源于stack exchange,提问作者Anand Mainali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:34:10