php laravel入门项目

前言

其实没想好写什么项目,先把laravel学习过程写出来把。这章主要写一些laravel的入口项目。所有的练习小项目全部放在这章。这章应该算是长期更新的。目前1.To-Do List应用 2.书签管理 3.API接口 电影管理

什么是laravel

Laravel 是一个 PHP 框架,简化了 Web 开发的复杂工作。它基于 MVC(模型-视图-控制器)架构,提供了很多开箱即用的功能,比如数据库操作(Eloquent ORM)、路由、模板引擎(Blade)等。适合开发博客、电商网站、API 等项目。

准备开发环境

  • PHP:Laravel 11 要求 PHP 8.2 或更高版本。
  • Composer:PHP 的包管理工具,用于安装 Laravel。
  • Web 服务器:推荐用 Laravel 内置的 Artisan 开发服务器,或者用 Nginx/Apache。
  • 数据库:可以选择 MySQL、PostgreSQL 或 SQLite(初学者用 SQLite 最简单)。
  • 代码编辑器:推荐 VS Code、PHPStorm 或 Sublime Text。

这里我说一下我的版本是8.0,懒的换了。版本低点就低点好了

php

php下载地址 另外环境变量自己加一下。加完之后运行cmd然后再命令行输入php -v。出现以下信息就算安装成功

PHP 8.0.2 (cli) (built: Feb  3 2021 18:36:37) ( NTS Visual C++ 2019 x64 )
Copyright (c) The PHP Group
Zend Engine v4.0.2, Copyright (c) Zend Technologies
composer

composer下载。下载完成之后也是cmd,输入composer --version,出现下面信息就算安装成功

Composer version 2.8.9 2025-05-13 14:01:37
PHP version 8.0.2 (D:\phpstudy_pro\Extensions\php\php8.0.2nts\php.exe)
Run the "diagnose" command to get more detailed diagnostics output.

mysql,编辑工具之类的我想你们应该都有了,我就不来写了,在不懂私信或者评论。

安装laravel

打开终端,运行以下命令来安装 Laravel 的全局安装器:

composer global require laravel/installer

创建新项目:

laravel new my-first-laravel

进入项目目录

cd my-first-laravel

启动开发服务器

php artisan serve

然后在浏览器访问 http://localhost:8000,你会看到 Laravel 的欢迎页面!
另外提一句我用的加速器,所以镜像和下载速度慢的问题我是没有考虑的。大家要是感觉太慢的话,切下国内镜像或者用下这个加速器 加速器地址。如果能看到欢迎页面那就OK,否则再查看下教程把。

在这里插入图片描述到这里laravel已经安装完了。我先去看文档写一个项目出来,大家加油

To-Do List

env配置数据库

我用的mysql数据库,大家自行安装,数据库我名字跟项目一个样,反正学习练手。配置大家改成自己的,编辑.env文件

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_first_laravel
DB_USERNAME=root
DB_PASSWORD=root

数据库配置和生成

运行 Artisan 命令生成迁移文件:

php artisan make:migration create_tasks_table

编辑该文件database/migrations/2025_06_04_091610_create_tasks_table.php

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up(): void
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->id(); // 自增主键
            $table->string('title'); // 任务标题
            $table->text('description')->nullable(); // 任务描述,可为空
            $table->timestamps(); // 创建和更新时间
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down(): void
    {
        Schema::dropIfExists('tasks');
    }
};

运行该文件命令

php artisan migrate

自己去mysql里查一下表有没有生成,有的话继续,没有回头找问题把。

生成模型和控制器

执行命令

php artisan make:model Task -c

-c表示同时生成控制器
这会在 app/Models/Task.php 创建模型文件,在 app/Http/Controllers/TaskController.php 创建控制器。
最后打开模型,app/Model/Task.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    protected $fillable = ['title', 'description'];
}

路由

打开路由文件routes/web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TaskController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

// Route::get('/', function () {
//     return view('welcome');
// });


// taks
Route::get('/', [TaskController::class, 'index'])->name('tasks.index');
Route::get('/tasks/create', [TaskController::class, 'create'])->name('tasks.create');
Route::post('/tasks', [TaskController::class, 'store'])->name('tasks.store');
Route::get('/tasks/{task}/edit', [TaskController::class, 'edit'])->name('tasks.edit');
Route::put('/tasks/{task}', [TaskController::class, 'update'])->name('tasks.update');
Route::delete('/tasks/{task}', [TaskController::class, 'destroy'])->name('tasks.destroy');
  • index:显示任务列表。
  • create:显示添加任务的表单。
  • store:处理表单提交,保存新任务。
  • edit:显示编辑任务的表单。
  • update:更新任务。
  • destroy:删除任务。

控制器

编写app/Http/Controllers/TaskController.php

<?php

namespace App\Http\Controllers;

use App\Models\Task;
use Illuminate\Http\Request;

class TaskController extends Controller
{
    // 显示任务列表
    public function index()
    {
        $tasks = Task::all();
        return view('tasks.index', compact('tasks'));
    }

    // 显示添加任务表单
    public function create()
    {
        return view('tasks.create');
    }

    // 保存新任务
    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
        ]);

        Task::create($request->all());

        return redirect()->route('tasks.index')->with('success', '任务添加成功!');
    }

    // 显示编辑任务表单
    public function edit(Task $task)
    {
        return view('tasks.edit', compact('task'));
    }

    // 更新任务
    public function update(Request $request, Task $task)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
        ]);

        $task->update($request->all());

        return redirect()->route('tasks.index')->with('success', '任务更新成功!');
    }

    // 删除任务
    public function destroy(Task $task)
    {
        $task->delete();
        return redirect()->route('tasks.index')->with('success', '任务删除成功!');
    }
}

视图

注意路径哦。
创建resources/views/layouts/app.blade.php

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>To-Do List</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .container { max-width: 800px; margin: auto; }
        .success { color: green; }
        table { width: 100%; border-collapse: collapse; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <div class="container">
        @if (session('success'))
            <div class="success">{{ session('success') }}</div>
        @endif
        @yield('content')
    </div>
</body>
</html>

创建resources/views/tasks/index.blade.php

@extends('layouts.app')

@section('content')
    <h1>任务列表</h1>
    <a href="{{ route('tasks.create') }}">添加新任务</a>
    @if ($tasks->isEmpty())
        <p>暂无任务</p>
    @else
        <table>
            <tr>
                <th>标题</th>
                <th>描述</th>
                <th>操作</th>
            </tr>
            @foreach ($tasks as $task)
                <tr>
                    <td>{{ $task->title }}</td>
                    <td>{{ $task->description ?? '无描述' }}</td>
                    <td>
                        <a href="{{ route('tasks.edit', $task) }}">编辑</a>
                        <form action="{{ route('tasks.destroy', $task) }}" method="POST" style="display:inline;">
                            @csrf
                            @method('DELETE')
                            <button type="submit" onclick="return confirm('确定删除吗?')">删除</button>
                        </form>
                    </td>
                </tr>
            @endforeach
        </table>
    @endif
@endsection

创建resources/views/tasks/create.blade.php

@extends('layouts.app')

@section('content')
    <h1>添加任务</h1>
    <form action="{{ route('tasks.store') }}" method="POST">
        @csrf
        <div>
            <label>标题:</label>
            <input type="text" name="title" required>
        </div>
        <div>
            <label>描述:</label>
            <textarea name="description"></textarea>
        </div>
        <button type="submit">保存</button>
    </form>
    <a href="{{ route('tasks.index') }}">返回</a>
@endsection

创建resources/views/tasks/edit.blade.php

@extends('layouts.app')

@section('content')
    <h1>编辑任务</h1>
    <form action="{{ route('tasks.update', $task) }}" method="POST">
        @csrf
        @method('PUT')
        <div>
            <label>标题:</label>
            <input type="text" name="title" value="{{ $task->title }}" required>
        </div>
        <div>
            <label>描述:</label>
            <textarea name="description">{{ $task->description }}</textarea>
        </div>
        <button type="submit">更新</button>
    </form>
    <a href="{{ route('tasks.index') }}">返回</a>
@endsection

写完了,http://localhost:8000 能输出下面页面就算成功,大家自己测试把。
在这里插入图片描述

书签管理

继续练习下CURD操作,还是这个项目里写哈,数据库之类的都已经配过了,就不来写了。

生成模型和迁移文件

运行命令

php artisan make:migration create_bookmarks_table

文件里加上

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('bookmarks', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('url');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('bookmarks');
    }
};

运行迁移

php artisan migrate 

生成模型命令

php artisan make:model Bookmark

文件添加

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Bookmark extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'url'];
}

控制器

运行生成命令

php artisan make:controller BookmarkController --resource

编写代码app/Http/Controllers/BookmarkController.php

<?php

namespace App\Http\Controllers;

use App\Models\Bookmark;
use Illuminate\Http\Request;

class BookmarkController extends Controller
{
    // 显示书签列表
    public function index()
    {
        $bookmarks = Bookmark::all();
        return view('bookmarks.index', compact('bookmarks'));
    }

    // 显示添加书签表单
    public function create()
    {
        return view('bookmarks.create');
    }

    // 保存新书签
    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'url' => 'required|url',
        ]);

        Bookmark::create($request->all());
        return redirect()->route('bookmarks.index')->with('success', '书签添加成功!');
    }

    // 显示编辑书签表单
    public function edit(Bookmark $bookmark)
    {
        return view('bookmarks.edit', compact('bookmark'));
    }

    // 更新书签
    public function update(Request $request, Bookmark $bookmark)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'url' => 'required|url',
        ]);

        $bookmark->update($request->all());
        return redirect()->route('bookmarks.index')->with('success', '书签更新成功!');
    }

    // 删除书签
    public function destroy(Bookmark $bookmark)
    {
        $bookmark->delete();
        return redirect()->route('bookmarks.index')->with('success', '书签删除成功!');
    }
}

路由

修改路由文件routes/web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TaskController;
use App\Http\Controllers\BookmarkController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

// Route::get('/', function () {
//     return view('welcome');
// });

// taks
Route::get('/', [TaskController::class, 'index'])->name('tasks.index');
Route::get('/tasks/create', [TaskController::class, 'create'])->name('tasks.create');
Route::post('/tasks', [TaskController::class, 'store'])->name('tasks.store');
Route::get('/tasks/{task}/edit', [TaskController::class, 'edit'])->name('tasks.edit');
Route::put('/tasks/{task}', [TaskController::class, 'update'])->name('tasks.update');
Route::delete('/tasks/{task}', [TaskController::class, 'destroy'])->name('tasks.destroy');

// bookmark
Route::get('bookmarks', [BookmarkController::class, 'index'])->name('bookmarks.index');
Route::get('bookmarks/create', [BookmarkController::class, 'create'])->name('bookmarks.create');
Route::post('bookmarks', [BookmarkController::class, 'store'])->name('bookmarks.store');
Route::get('bookmarks/{bookmark}/edit', [BookmarkController::class, 'edit'])->name('bookmarks.edit');
Route::put('bookmarks/{bookmark}', [BookmarkController::class, 'update'])->name('bookmarks.update');
Route::delete('bookmarks/{bookmark}', [BookmarkController::class, 'destroy'])->name('bookmarks.destroy');

页面

这里加了bootstrap美化页面
创建resources/views/layouts/appbook.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>书签管理</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light mb-4">
        <div class="container">
            <a class="navbar-brand" href="{{ route('bookmarks.index') }}">书签管理</a>
            <div class="navbar-nav">
                <a class="nav-link" href="{{ route('bookmarks.index') }}">书签列表</a>
                <a class="nav-link" href="{{ route('bookmarks.create') }}">添加书签</a>
            </div>
        </div>
    </nav>
    <div class="container">
        @yield('content')
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

创建文件resources/views/bookmarks/index.blade.php

@extends('layouts.appbook')

@section('content')
    <h1 class="mb-4">书签列表</h1>
    @if (session('success'))
        <div class="alert alert-success">
            {{ session('success') }}
        </div>
    @endif
    <a href="{{ route('bookmarks.create') }}" class="btn btn-primary mb-3">添加新书签</a>
    <table class="table table-striped table-bordered">
        <thead class="table-dark">
            <tr>
                <th>标题</th>
                <th>URL</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            @forelse ($bookmarks as $bookmark)
                <tr>
                    <td>{{ $bookmark->title }}</td>
                    <td><a href="{{ $bookmark->url }}" target="_blank">{{ $bookmark->url }}</a></td>
                    <td>
                        <a href="{{ route('bookmarks.edit', $bookmark->id) }}" class="btn btn-sm btn-warning">编辑</a>
                        <form action="{{ route('bookmarks.destroy', $bookmark->id) }}" method="POST" style="display:inline;">
                            @csrf
                            @method('DELETE')
                            <button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('确定删除?')">删除</button>
                        </form>
                    </td>
                </tr>
            @empty
                <tr>
                    <td colspan="3" class="text-center">暂无书签</td>
                </tr>
            @endforelse
        </tbody>
    </table>
@endsection

创建文件resources/views/bookmarks/create.blade.php

@extends('layouts.appbook')

@section('content')
    <h1 class="mb-4">添加书签</h1>
    <form action="{{ route('bookmarks.store') }}" method="POST">
        @csrf
        <div class="mb-3">
            <label for="title" class="form-label">书签标题</label>
            <input type="text" name="title" id="title" class="form-control" value="{{ old('title') }}">
            @error('title')
                <div class="text-danger">{{ $message }}</div>
            @enderror
        </div>
        <div class="mb-3">
            <label for="url" class="form-label">URL</label>
            <input type="text" name="url" id="url" class="form-control" value="{{ old('url') }}">
            @error('url')
                <div class="text-danger">{{ $message }}</div>
            @enderror
        </div>
        <button type="submit" class="btn btn-success">保存</button>
        <a href="{{ route('bookmarks.index') }}" class="btn btn-secondary">取消</a>
    </form>
@endsection

创建文件resources/views/bookmarks/edit.blade.php

@extends('layouts.appbook')

@section('content')
    <h1 class="mb-4">编辑书签</h1>
    <form action="{{ route('bookmarks.update', $bookmark->id) }}" method="POST">
        @csrf
        @method('PUT')
        <div class="mb-3">
            <label for="title" class="form-label">书签标题</label>
            <input type="text" name="title" id="title" class="form-control" value="{{ old('title', $bookmark->title) }}">
            @error('title')
                <div class="text-danger">{{ $message }}</div>
            @enderror
        </div>
        <div class="mb-3">
            <label for="url" class="form-label">URL</label>
            <input type="text" name="url" id="url" class="form-control" value="{{ old('url', $bookmark->url) }}">
            @error('url')
                <div class="text-danger">{{ $message }}</div>
            @enderror
        </div>
        <button type="submit" class="btn btn-success">更新</button>
        <a href="{{ route('bookmarks.index') }}" class="btn btn-secondary">取消</a>
    </form>
@endsection

OK了,能输出以下内容就算成功,大家自己测试一下

在这里插入图片描述

电影管理 API接口

模型和迁移

php artisan make:model Movie -m

编辑迁移

$table->string('title');
$table->string('director');

编辑模型

protected $fillable = ['title', 'director'];

运行迁移

php artisan migrate

控制器

创建命令

php artisan make:controller Api/MovieController --api

编辑文件

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Movie;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class MovieController extends Controller
{
    // 获取所有电影
    public function index(): JsonResponse
    {
        $movies = Movie::all();
        return response()->json([
            'status' => 'success',
            'data' => $movies,
        ], 200);
    }

    // 获取单个电影
    public function show(Movie $movie): JsonResponse
    {
        return response()->json([
            'status' => 'success',
            'data' => $movie,
        ], 200);
    }

    // 添加新电影
    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'director' => 'required|string|max:255',
        ], [
            'title.required' => '电影标题不能为空',
            'title.max' => '标题不能超过255个字符',
            'director.required' => '导演名称不能为空',
            'director.max' => '导演名称不能超过255个字符',
        ]);

        $movie = Movie::create($validated);
        return response()->json([
            'status' => 'success',
            'message' => '电影添加成功',
            'data' => $movie,
        ], 201);
    }

    // 更新电影
    public function update(Request $request, Movie $movie): JsonResponse
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'director' => 'required|string|max:255',
        ], [
            'title.required' => '电影标题不能为空',
            'title.max' => '标题不能超过255个字符',
            'director.required' => '导演名称不能为空',
            'director.max' => '导演名称不能超过255个字符',
        ]);

        $movie->update($validated);
        return response()->json([
            'status' => 'success',
            'message' => '电影更新成功',
            'data' => $movie,
        ], 200);
    }

    // 删除电影
    public function destroy(Movie $movie): JsonResponse
    {
        $movie->delete();
        return response()->json([
            'status' => 'success',
            'message' => '电影删除成功',
        ], 204);
    }
}

每个方法返回 JSON 响应,包含 status、message(可选)和 data(可选)。

HTTP 状态码:

  • 200:成功(index, show, update)。
  • 201:创建成功(store)。
  • 204:删除成功,无内容返回。

路由

编辑routes/api.php

use App\Http\Controllers\Api\MovieController;

Route::apiResource('movies', MovieController::class);

这会生成以下 API 端点:

  • GET /api/movies → index
  • GET /api/movies/{movie} → show
  • POST /api/movies → store
  • PUT /api/movies/{movie} → update
  • DELETE /api/movies/{movie} → destroy

注意:Laravel 的 API 路由默认带 /api 前缀,访问时需使用 http://localhost:8000/api/movies。

写完了。应该没什么问题了。大家自己测试吧

`

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值