
本文档旨在指导开发者如何在 Laravel 框架下构建一个内容管理系统(CMS),并解决在前端页面展示管理后台数据时遇到的“Undefined variable”错误。我们将以博文管理和关于我们信息管理为例,详细讲解后台数据录入、编辑、展示的完整流程,并提供关键代码示例和注意事项,帮助开发者快速搭建可维护、易扩展的内容管理系统。
问题分析与解决方案
出现 Undefined variable: aboutresult 错误的原因是在 user.english.index 视图中使用了 $aboutresult 变量,但在对应的控制器方法 EngHafizController@home 中,只将 $result 变量传递给了视图。
正确的做法是将 $aboutresult 和 $result 两个变量都传递给 user.english.index 视图。修改后的 EngHafizController@home 方法如下:
<?php
namespace App\Http\Controllers\user;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
class EngHafizController extends Controller
{
// ... 其他方法
public function home()
{
$data['aboutresult'] = DB::table('abouts')->get();
$data['result'] = DB::table('posts')->get();
return view('user.english.index', $data);
}
// ... 其他方法
}解释:
- $data['aboutresult'] = DB::table('abouts')-youjiankuohaophpcnget();:从 abouts 表中获取所有数据,并将其赋值给 $data 数组中的 aboutresult 键。
- $data['result'] = DB::table('posts')->get();:从 posts 表中获取所有数据,并将其赋值给 $data 数组中的 result 键。
- return view('user.english.index', $data);:将包含 aboutresult 和 result 键的 $data 数组传递给 user.english.index 视图。
内容管理系统构建步骤
以下将更详细地介绍如何构建一个完整的内容管理系统,包括后台管理和前台展示两部分。
1. 数据库设计
首先,需要设计数据库表结构。根据需求,我们创建了 posts 表用于存储博文信息,abouts 表用于存储“关于我们”信息。
posts 表结构:
| 字段名 | 数据类型 | 说明 |
|---|---|---|
| id | INT | 主键,自增 |
| title | VARCHAR(255) | 标题 1 |
| description | TEXT | 描述 1 |
| title2 | VARCHAR(255) | 标题 2 |
| description2 | TEXT | 描述 2 |
| image | VARCHAR(255) | 图片 1 文件名 |
| image2 | VARCHAR(255) | 图片 2 文件名 |
| created_at | TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | 更新时间 |
abouts 表结构:
| 字段名 | 数据类型 | 说明 |
|---|---|---|
| id | INT | 主键,自增 |
| title3 | VARCHAR(255) | 标题 |
| heading3 | VARCHAR(255) | 标题 |
| description3 | TEXT | 描述 |
| image3 | VARCHAR(255) | 图片文件名 |
| created_at | TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | 更新时间 |
可以使用 Laravel 的 Migration 来创建这些表:
php artisan make:migration create_posts_table php artisan make:migration create_abouts_table
然后在对应的 Migration 文件中定义表结构。
2. 后台管理功能实现
后台管理功能主要包括数据的增删改查(CRUD)操作。
2.1 模型创建
首先,创建对应的 Eloquent 模型:
php artisan make:model Post php artisan make:model About
2.2 控制器实现
创建控制器 PostController 和 AboutController 来处理后台请求。
PostController:
<?php
namespace App\Http\Controllers\admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class Post extends Controller
{
function listing()
{
$data['result'] = DB::table('posts')->orderBy('id','desc')->get();
return view('admin.post.list',$data);
}
function submit(Request $req)
{
//validation
$req->validate([
'title' => 'required',
'description' => 'required',
'title2' => 'required',
'description2' => 'required',
'image' => 'mimes: jpg,jpeg,png',
'image2' => 'mimes: jpg,jpeg,png'
]);
//storing image
$image=$req->file('image');
$ext = $image->extension();
$file=time().'.'.$ext;
$image->storeAs('public/post',$file);
$image2=$req->file('image2');
$ext2 = $image2->extension();
$file2=time().'.'.$ext2;
$image2->storeAs('public/post/secondbanner',$file2);
//array
$data = array(
'title' => $req->input('title'),
'description' => $req->input('description'),
'title2' => $req->input('title2'),
'description2' => $req->input('description2'),
'image' => $file,
'image2' => $file2,
);
//inserting data
DB::table('posts')->insert($data);
$req->session()->flash('msg','Data has been Added');
return redirect('/admin/post/list');
}
function delete(Request $req , $id)
{
DB::table('posts')->where('id',$id)->delete();
$req->session()->flash('msgForDelete','Data has been Deleted');
return redirect('/admin/post/list');
}
function edit(Request $req , $id)
{
$data['result'] = DB::table('posts')->where('id',$id)->get();
return view('admin.post.edit',$data);
}
function update(Request $req , $id)
{
//validation
$req->validate([
'title' => 'required',
'description' => 'required',
'title2' => 'required',
'description2' => 'required',
'image' => 'mimes: jpg,jpeg,png',
'image2' => 'mimes: jpg,jpeg,png'
]);
//array
$data = array(
'title' => $req->input('title'),
'description' => $req->input('description'),
'title2' => $req->input('title2'),
'description2' => $req->input('description2'),
);
if($req->hasfile('image'))
{
$image=$req->file('image');
$ext = $image->extension();
$file=time().'.'.$ext;
$file2=time().'.'.$ext;
$image->storeAs('public/post/',$file,$file2);
$data['image']=$file;
}
if($req->hasfile('image2'))
{
$image2=$req->file('image2');
$ext = $image2->extension();
$file2=time().'.'.$ext;
$image2->storeAs('public/post/secondbanner',$file2);
$data['image2']=$file2;
}
//updating data
DB::table('posts')->where('id',$id)->update($data);
$req->session()->flash('msg','Data has been Updated');
return redirect('/admin/post/list');
}
}AboutController:
<?php
namespace App\Http\Controllers\admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AboutController extends Controller
{
function about_listing()
{
$data['aboutresult'] = DB::table('abouts')->orderBy('id','desc')->get();
return view('admin.post.about.aboutlist',$data);
}
function about_submit(Request $request)
{
//validation
$request->validate([
'title3' => 'required',
'heading3' => 'required',
'description3' => 'required',
'image3' => 'mimes: jpg,jpeg,png'
]);
//storing image
$image3=$request->file('image3');
$ext = $image3->extension();
$file=time().'.'.$ext;
$image3->storeAs('public/post/about_image',$file);
//array
$data = array(
'title3' => $request->input('title3'),
'heading3' => $request->input('heading3'),
'description3' => $request->input('description3'),
'image3' => $file,
);
//inserting data
DB::table('abouts')->insert($data);
$request->session()->flash('msg','Data has been Added');
return redirect('/admin/post/about/aboutlist');
}
function about_delete(Request $request , $id)
{
DB::table('abouts')->where('id',$id)->delete();
$request->session()->flash('msgForDelete','Data has been Deleted');
return redirect('/admin/post/list');
}
function about_edit(Request $request , $id)
{
$data['aboutresult'] = DB::table('abouts')->where('id',$id)->get();
return view('admin.post.about.aboutedit',$data);
}
function about_update(Request $request , $id)
{
//validation
$request->validate([
'title3' => 'required',
'heading3' => 'required',
'description3' => 'required',
'image3' => 'mimes: jpg,jpeg,png'
]);
//array
$data = array(
'title3' => $request->input('title3'),
'heading3' => $request->input('heading3'),
'description3' => $request->input('description3'),
);
if($request->hasfile('image3'))
{
$image3=$request->file('image3');
$ext = $image3->extension();
$file=time().'.'.$ext;
$image3->storeAs('public/post/about_image',$file);
$data['image3']=$file;
}
//updating data
DB::table('abouts')->where('id',$id)->update($data);
$request->session()->flash('msg','Data has been Updated');
return redirect('/admin/post/about/aboutlist');
}
}2.3 视图创建
创建对应的 Blade 视图文件,用于展示数据和提供表单。例如:
- admin/post/list.blade.php:博文列表
- admin/post/add.blade.php:添加博文
- admin/post/edit.blade.php:编辑博文
- admin/post/about/aboutlist.blade.php:关于我们列表
- admin/post/about/aboutadd.blade.php:添加关于我们信息
- admin/post/about/aboutedit.blade.php:编辑关于我们信息
示例:admin/post/list.blade.php
@extends('admin.layouts.app')
@section('main-content')
<div class="content-wrapper">
<div class="card" style="margin-top:5%">
<div class="card-header">
<h2 class="text-center">English Home Section</h2>
<div class="col-sm-12" style="text-align: center; color:green; font-size:20px">{{session('msg')}}</div>
<div class="col-sm-12" style="text-align: center; color:red; font-size:20px">{{session('msgForDelete')}}</div>
</div>
<div class="card-header">
<a class="btn btn-success" href="{{ URL('/admin/post/add')}}">Add Post</a>
</div>
<!-- /.card-header -->
<div class="card-body">
<table id="example1" class="table table-bordered table-striped table-responsive">
<thead>
<tr width="100%">
<th width="3%">ID</th>
<th width="10%">Title 1</th>
<th width="23.5%">Description 1</th>
<th width="10%">Title 2</th>
<th width="23.5%">Description 2</th>
<th width="10%">Image 1</th>
<th width="10%">Image 2</th>
<th width="10%">Action</th>
</tr>
</thead>
<tbody>
<?php
// echo '';
// print_r([$result]);
// die();
?>
@foreach ($result as $list)
<tr>
<td>{{$list->id}}</td>
<td>{{$list->title}}</td>
<td>{{$list->description}}</td>
<td>{{$list->title2}}</td>
<td>{{$list->description2}}</td>
<td><img src="{{ asset('storage/app/public/post/'.$list->image) }}" width="150px"/></td> <td><img src="{{ asset('storage/app/public/post/secondbanner/'.$list->image2) }}" width="150px"/></td>
<td><a class="btn btn-primary" href="{{('/haffiz/admin/post/edit/'.$list->id)}}">Edit</a>
<a class="btn btn-danger" href="{{('/haffiz/admin/post/delete/'.$list->id)}}">Delete</a>
</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr>
<th>ID</th>
<th>Title 1</th>
<th>Description 1</th>
<th>Title 2</th>
<th>Description 2</th>
<th>Image 1</th>
<th>Image 2</th>
<th>Action</th>
</tr>
</tfoot>
</table>
</div></div></div> </div>
@endsection2.4 路由配置
在 routes/web.php 文件中配置后台路由:
Route::group(['prefix' => 'admin/post'], function () {
Route::get('list', [App\Http\Controllers\admin\Post::class, 'listing']);
Route::get('add', function () {
return view('admin.post.add');
});
Route::post('submit', [App\Http\Controllers\admin\Post::class, 'submit']);
Route::get('delete/{id}', [App\Http\Controllers\admin\Post::class, 'delete']);
Route::get('edit/{id}', [App\Http\Controllers\admin\Post::class, 'edit']);
Route::post('update/{id}', [App\Http\Controllers\admin\Post::class, 'update']);
// About Routes
Route::group(['prefix' => 'about'], function () {
Route::get('aboutlist', [App\Http\Controllers\admin\AboutController::class, 'about_listing']);
Route::get('about', function () {
return view('admin.post.about.about');
});
Route::post('aboutsubmit', [App\Http\Controllers\admin\AboutController::class, 'about_submit']);
Route::get('aboutdelete/{id}', [App\Http\Controllers\admin\AboutController::class, 'about_delete']);
Route::get('aboutedit/{id}', [App\Http\Controllers\admin\AboutController::class, 'about_edit']);
Route::post('aboutupdate/{id}', [App\Http\Controllers\admin\AboutController::class, 'about_update']);
});
});3. 前台展示功能实现
前台展示功能负责将后台管理的数据展示给用户。
3.1 控制器修改
如前面所述,确保 EngHafizController@home 方法正确传递数据。
3.2 视图修改
修改 user.english.index 视图,正确展示数据。
<!-- 博文展示 -->
@foreach ($result as $list)
<img src="{{ asset('storage/app/public/post/'.$list->image) }}" class="d-block w-100" alt="...">
<div class="col-12 text-left">
<h1 class="animated slideInDown">{{ $list->title }}</h1>
<svg class="animated slideInDown" width="128" height="9" viewBox="0 0 128 9" fill="none" xmlns="http://www.w3.org/2000/svg"></svg>
<p class="animated slideInLeft">{{ $list->description }}</p>
<a href="#" class="animated slideInRight btn btn-gold btn-p">Read More</a>
</div>
<div class="carousel-item">
<img src="{{ asset('storage/app/public/post/secondbanner/'.$list->image2) }}" class="d-block w-100" alt="...">
<h1 class="animated slideInDown">{{ $list->title2}}</h1>
<p class="animated slideInLeft">{{ $list->description2 }}</p>
</div>
@endforeach
<!-- 关于我们展示 -->
@foreach($aboutresult as $aboutlist)
<div class="col-xl-7 about-p">
<h5 class="about-welcome">{{$aboutlist->title3}}</h5>
</div>
@endforeach代码优化与注意事项
- 使用 Eloquent 模型: 尽量使用 Eloquent 模型来操作数据库,而不是直接使用 DB::table(),这样可以提高代码的可读性和可维护性。
- 图片存储路径: 建议将图片存储在 public/storage 目录下,并在 .env 文件中配置 FILESYSTEM_DISK=public,然后使用 php artisan storage:link 命令创建软链接。
- 表单验证: 使用 Laravel 的表单验证功能,确保数据的有效性。
- 错误处理: 完善错误处理机制,例如使用 try-catch 块捕获异常,并记录日志。
- 权限控制: 根据实际需求,添加权限控制功能,限制不同用户对后台管理功能的访问。
- 前端优化: 使用前端框架(如 Vue.js、React)来构建交互性更强的用户界面。
总结
本文详细介绍了如何在 Laravel 框架下构建一个内容管理系统,并解决了在前端页面展示管理后台数据时遇到的“Undefined variable”错误。通过遵循本文档的步骤和建议,开发者可以快速搭建一个可维护、易扩展的内容管理系统,满足各种业务需求。










