Laravel - 数据库操作
Laravel - 数据库操作
Section titled “Laravel - 数据库操作”Laravel 提供了一种强大而优雅的方式与数据库交互。它开箱即用地支持多种数据库系统,并提供了多种执行数据库操作的方式:原生 SQL 查询(raw SQL queries)、流畅的查询构造器(Query Builder)以及 Eloquent ORM(对象关系映射器)。
支持的数据库:
- MySQL / MariaDB
- PostgreSQL
- SQLite
- SQL Server
数据库连接配置主要在 Laravel 项目根目录下的 .env 文件中管理。Laravel 的 config/database.php 文件会使用这些环境变量来设置连接。
MySQL 的 .env 配置示例:
DB_CONNECTION=mysqlDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=your_database_nameDB_USERNAME=your_usernameDB_PASSWORD=your_password请务必将 your_database_name、your_username 和 your_password 替换为您的实际数据库凭据。修改 .env 文件后,您可能需要清除配置缓存:
php artisan config:clear数据库迁移 (Schema 管理)
Section titled “数据库迁移 (Schema 管理)”在执行 CRUD 操作之前,您需要一个数据库表。Laravel 的数据库迁移(Migrations)就像是数据库的版本控制,让您可以轻松地定义和修改数据库 schema(模式)。您可以使用以下命令创建一个迁移:
php artisan make:migration create_students_table然后,在生成的迁移文件(例如,database/migrations/xxxx_xx_xx_xxxxxx_create_students_table.php)中定义您的表结构:
use Illuminate\Database\Migrations\Migration;use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema;
return new class extends Migration{ public function up(): void { Schema::create('students', function (Blueprint $table) { $table->id(); // Auto-incrementing BIGINT primary key 'id' $table->string('name', 100); $table->string('email')->unique(); $table->timestamps(); // Adds 'created_at' and 'updated_at' columns }); }
public function down(): void { Schema::dropIfExists('students'); }};运行迁移以创建表:
php artisan migrate运行原生 SQL 查询
Section titled “运行原生 SQL 查询”Laravel 允许您使用 DB Facade(外观)运行原生 SQL 查询。虽然出于安全性和可维护性的考虑,通常不建议优先使用它,但当需要时它是可用的。
警告:使用原生 SQL 时,务必始终使用参数绑定(parameter binding)来防范 SQL 注入(SQL injection)漏洞。
使用 DB::insert() 进行 INSERT 语句操作。它返回 true 或 false。
use Illuminate\Support\Facades\DB;
DB::insert('INSERT INTO students (name, email, created_at, updated_at) VALUES (?, ?, ?, ?)', ['Alice Smith', 'alice@example.com', now(), now()]);使用 DB::select() 进行 SELECT 语句操作。它返回一个 stdClass 对象数组。
$students = DB::select('SELECT * FROM students WHERE id = ?', [1]);
foreach ($students as $student) { // echo $student->name;}使用 DB::update() 进行 UPDATE 语句操作。它返回受影响的行数。
$affectedRows = DB::update('UPDATE students SET name = ? WHERE email = ?', ['Alicia Smith', 'alice@example.com']);使用 DB::delete() 进行 DELETE 语句操作。它返回受影响的行数。
$deletedRows = DB::delete('DELETE FROM students WHERE id = ?', [1]);对于其他类型的语句(例如,如果不使用迁移,可以使用 CREATE TABLE、DROP TABLE),请使用 DB::statement():
DB::statement('DROP TABLE IF EXISTS old_table');查询构造器 (Query Builder)
Section titled “查询构造器 (Query Builder)”Laravel 的数据库查询构造器(Query Builder)提供了一个方便、流畅的接口来创建和运行数据库查询。它可用于在应用程序中执行大多数数据库操作,并且适用于所有支持的数据库系统。
它提供了更好的安全性(自动 PDO 参数绑定),并且比原生 SQL 查询更具表现力。
DB::table('students')->insert([ 'name' => 'Bob Johnson', 'email' => 'bob@example.com', 'created_at' => now(), 'updated_at' => now()]);
// Insert multiple recordsDB::table('students')->insert([ ['name' => 'Charlie Brown', 'email' => 'charlie@example.com', 'created_at' => now(), 'updated_at' => now()], ['name' => 'Diana Prince', 'email' => 'diana@example.com', 'created_at' => now(), 'updated_at' => now()]]);// Get all students$allStudents = DB::table('students')->get();
// Get a single student by ID$student = DB::table('students')->where('id', 2)->first();
// Get students matching a condition$activeStudents = DB::table('students')->where('name', 'like', 'A%')->get();
// Pluck a single column's values$studentNames = DB::table('students')->pluck('name');$affected = DB::table('students') ->where('id', 2) ->update(['name' => 'Robert Johnson']);$deleted = DB::table('students')->where('id', 3)->delete();
// Delete all records (use with caution!)// DB::table('students')->delete();
// Better way to truncate a table (resets auto-incrementing ID)// DB::table('students')->truncate();Eloquent ORM
Section titled “Eloquent ORM”Laravel 的 Eloquent ORM 是一个优雅的 ActiveRecord 实现,用于与数据库交互。每个数据库表都有一个对应的“模型”(Model),用于与该表进行交互。模型允许您查询表中的数据,以及向表中插入新记录。
虽然查询构造器功能强大,但 Eloquent 添加了一个面向对象的层,使得交互更加直观,特别是在处理表之间的关系时。这个主题内容广泛,通常会在单独的章节中介绍。
示例:学生管理 CRUD 操作
Section titled “示例:学生管理 CRUD 操作”让我们概述如何在控制器中使用查询构造器实现“学生”实体的 CRUD(创建、读取、更新、删除)操作。首先,确保您有一个 students 表(参见上面的“数据库迁移”部分)。
创建一个 StudentController:
php artisan make:controller StudentController然后,将方法添加到 app/Http/Controllers/StudentController.php 中(这些是简化示例):
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;use Illuminate\Support\Facades\DB;use Illuminate\View\View;use Illuminate\Http\RedirectResponse;
class StudentController extends Controller{ // Display a list of students public function index(): View { $students = DB::table('students')->orderBy('name')->get(); return view('students.index', ['students' => $students]); }
// Show the form for creating a new student public function create(): View { return view('students.create'); }
// Store a newly created student in storage public function store(Request $request): RedirectResponse { $validated = $request->validate([ 'name' => 'required|string|max:100', 'email' => 'required|email|unique:students,email', ]);
DB::table('students')->insert([ 'name' => $validated['name'], 'email' => $validated['email'], 'created_at' => now(), 'updated_at' => now(), ]);
return redirect()->route('students.index')->with('success', 'Student created successfully.'); }
// Show the form for editing the specified student public function edit(int $id): View { $student = DB::table('students')->where('id', $id)->first(); if (!$student) { abort(404); } return view('students.edit', ['student' => $student]); }
// Update the specified student in storage public function update(Request $request, int $id): RedirectResponse { $validated = $request->validate([ 'name' => 'required|string|max:100', 'email' => 'required|email|unique:students,email,' . $id, // Ignore current student's email for unique check ]);
$affected = DB::table('students') ->where('id', $id) ->update([ 'name' => $validated['name'], 'email' => $validated['email'], 'updated_at' => now(), ]);
if ($affected) { return redirect()->route('students.index')->with('success', 'Student updated successfully.'); } return redirect()->route('students.index')->with('error', 'Student not found or no changes made.'); }
// Remove the specified student from storage public function destroy(int $id): RedirectResponse { $deleted = DB::table('students')->where('id', $id)->delete(); if ($deleted) { return redirect()->route('students.index')->with('success', 'Student deleted successfully.'); } return redirect()->route('students.index')->with('error', 'Student not found.'); }}然后,您需要在 routes/web.php 中定义路由(Routes),将 URL 映射到这些控制器操作,并创建相应的 Blade 视图(Views)(students/index.blade.php、students/create.blade.php 等)。
常见学习障碍:忘记参数绑定
在使用原生 SQL(DB::select、DB::insert 等)时,一个常见的错误是直接将用户输入嵌入到查询字符串中。这会使您的应用程序容易受到 SQL 注入攻击。务必始终使用 ? 占位符,并将值作为数组传递给第二个参数。查询构造器和 Eloquent 会自动为您处理此问题。
- Laravel 数据库文档:https://laravel.com/docs/database
- 查询构造器:https://laravel.com/docs/queries
- Eloquent ORM:https://laravel.com/docs/eloquent
- 数据库迁移:https://laravel.com/docs/migrations