介绍
这段时间在写一个考试系统ChemLab,期间用到了AJAX
实现增删查改(CRUD
)页面,现在写一个Laravel
入门教程吧,一步步实现最基本的CRUD
页面。
项目地址,求Star
:Laravel_AJAX_CRUD
演示地址:http://115.159.147.250/task
博文地址:Laravel入门教程: 实现简单的AJAX的CRUD页面
先来看看效果图:
这个教程需要安装homestead
环境,关于homestead
可以参考我的另一篇博文:windows下安装Homestead开发环境
创建项目
- vagrant@homestead:~/Code$ laravel new AJAX_CRUD
- vagrant@homestead:~/Code$ cd AJAX_CRUD/
修改配置
修改数据库
打开.env
,主要是修改数据库方面的,我们选择task
数据库,如下:
- DB_CONNECTION=MysqL
- DB_HOST=127.0.0.1
- DB_PORT=3306
- DB_DATABASE=task
- DB_USERNAME=homestead
- DB_PASSWORD=secret
修改网址映射
注意这部分是在主机下进行的,不是在虚拟机homestead
中进行的,后面我提到主机应该注意。
修改homestead
的配置文件:~/.homestead/Homestead.yaml
,增加如下内容:
- sites:
- - map: crud.app
- to: /home/vagrant/Code/AJAX_CRUD/public
修改C:\Windows\System32\drivers\etc\hosts
,增加一条记录:
- 192.168.10.10 crud.app
重启homestead
虚拟机:
- homestead reload --provision
访问项目
浏览器访问crud.app
,应该能见到如下页面:
引入Bootstrap、JQuery、Toastr
刚创建的项目什么都没有,在resources/welcome.blade.PHP
中加入bootstrap
、JQuery
、Toastr
:
- <title>Task Manager</title>
-
- <link href="http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
- <link href="http://cdn.bootcss.com/toastr.js/2.1.3/toastr.min.css" rel="stylesheet">
- <script src="http://cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script>
- <script src="http://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
- <script src="http://cdn.bootcss.com/toastr.js/2.1.3/toastr.min.js"></script>
- <style>
- html,body { height: 100%; }
-
- body { margin: 0; padding: 0; width: 100%; display: table; font-weight: 100; font-family: 'Lato',sans-serif; }
-
- .container { text-align: center; display: table-cell; vertical-align: middle; }
-
- .content { text-align: center; display: inline-block; }
-
- .title { font-size: 96px; }
- </style>
- ...
- <div class="content">
- <div class="title">Laravel 5</div>
- </div>
创建Eloquent模型、数据表
- vagrant@homestead:~/Code/AJAX_CRUD$ PHP artisan make:model Task -m
- Model created successfully.
- Created Migration: 2016_08_17_033029_create_tasks_table
编辑模型:app/Task.PHP
,如下:
- class Task extends Model {
- protected $fillable = ['name','content'];
- }
编辑database/migrations/2016_08_17_033029_create_tasks_table.PHP
,如下
- ...
- public function up() {
- Schema::create('tasks',function (Blueprint $table) {
- $table->increments('id');
- $table->text('name');
- $table->text('content');
- $table->timestamps();
- });
-
- App\Task::create([
- 'name' => '任务1','content' => '完成crud'
- ]);
- App\Task::create([
- 'name' => '任务1','content' => '完成教程'
- ]);
- }
- ...
创建数据表:
- vagrant@homestead:~/Code/AJAX_CRUD$ PHP artisan migrate
- Migration table created successfully.
- Migrated: 2014_10_12_000000_create_users_table
- Migrated: 2014_10_12_100000_create_password_resets_table
- Migrated: 2016_08_17_033029_create_tasks_table
构建页面
创建控制器
- vagrant@homestead:~/Code/AJAX_CRUD$ PHP artisan make:controller TaskController
- Controller created successfully.
修改路由
编辑app/Http/routes.PHP
,
- Route::get('/',function () {
- return redirect('/task');
- });
-
- Route::resource('/task','TaskController');
这样所有动作都由我们刚刚创建的控制器来执行了。
这里的Route::resource
方法可以看这个:RESTful Resource Controllers,它默认帮你创建这几个http verb
* GET
* POST
* PUT
* DELETE
这样就不用自己写路由了。
修改控制器
编辑app/Http/Controllers/TaskController.PHP
,在类中增加如下方法:
- use App\Task;
- ...
- public function index() {
- return view('welcome',[
- 'tasks' => Task::all()
- ]);
- }
编辑页面
编辑resources/welcome.blade.PHP
,如下
- <div class="container">
- {{--task list--}}
- <div class="panel panel-default">
- <div class="panel-heading">
- 任务管理器
- </div>
- <div class="panel-body">
- <button class="btn btn-primary" id="add">添加任务</button>
- </div>
- <table class="table table-striped">
- <thead>
- <tr>
- <th>id</th>
- <th>Name</th>
- <th>Content</th>
- <th>Created_at</th>
- <th>Action</th>
- </tr>
- </thead>
- <tbody id="task-list">
- @foreach($tasks as $task)
- <tr id="task{{ $task->id }}">
- <td>{{ $task->id }}</td>
- <td>{{ $task->name }}</td>
- <td>{{ $task->content }}</td>
- <td>{{ $task->created_at }}</td>
- <td>
- <button class="btn btn-info edit" value="{{ $task->id }}">编辑</button>
- <button class="btn btn-warning delete" value="{{ $task->id }}">删除</button>
- </td>
- </tr>
- @endforeach
- </tbody>
- </table>
- </div>
- {{--Modal--}}
- <div class="modal fade" id="taskModal" tabindex="-1" role="dialog">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal"><span >×</span></button>
- <h4 class="modal-title" id="task-title">编辑任务</h4>
- </div>
- <div class="modal-body">
- <form id="task">
- <div class="form-group">
- <label for="tname" class="control-label">Name:</label>
- <input id="tname" class="form-control" type="text">
- </div>
- <div class="form-group">
- <label for="tcontent" class="control-label">Content:</label>
- <textarea class="form-control" id="tcontent"></textarea>
- </div>
- {!! csrf_field() !!}
- </form>
- </div>
- <div class="modal-footer">
- <button type="button" id="tsave" class="btn btn-primary" value="update">提交</button>
- <input type="hidden" id="tid" name="tid" value="-1">
- </div>
- </div>
- </div>
- </div>
-
- </div>
在<head></head>
中插入:
- <script src="{{ asset('js/app.js') }}"></script>
创建public/js/app.js
好了目前页面如图:
增删查改CRUD
下面我们来实现核心功能:增删查改。
在实现之前,我们记得添加CSRF_TOKEN
,不然ajax
的时候会出现500
错误。
编辑resources/welcome.blade.PHP
,在<form></form>
中添加如下代码:
- ...
- </div>
- {!! csrf_field() !!}
- </form>
- ...
增加
删除
- public function destroy($id) {
- $task = Task::find($id);
- $task->delete();
- return response()->json(['success']);
- }
查、改
- public function show($id) {
- $task = Task::find($id);
- return response()->json($task);
- }
- public function update(Request $request,$id) {
- $this->validate($request,'content' => 'required'
- ]);
- $task = Task::find($id);
- $task->name = $request->get('name');
- $task->content = $request->get('content');
- $task->save();
- return response()->json($task);
- }
app.js
最后的public/js/app.js
如下:
- $(document).ready(function () {
- url = '/task/';
- $.ajaxSetup({
- headers: {
- 'X-CSRF-TOKEN': $('#task input[name="_token"]').val()
- }
- });
-
- $('#add').click(function () {
- $('#task-title').text('添加任务');
- $('#tsave').val('add');
- $('#taskModal').modal('show');
- });
-
- $('body').on('click','button.delete',function() {
- var tid = $(this).val();
- $.ajax({
- type: 'DELETE',url: url+tid,success: function (data) {
- console.log(data);
- $('#task'+tid).remove();
- toastr.success('删除成功!');
- },error: function (data,json,errorThrown) {
- console.log(data);
- var errors = data.responseJSON;
- var errorsHtml= '';
- $.each( errors,function( key,value ) {
- errorsHtml += '<li>' + value[0] + '</li>';
- });
- toastr.error( errorsHtml,"Error " + data.status +': '+ errorThrown);
- }
- });
- });
-
- $('body').on('click','button.edit',function() {
- $('#task-title').text('编辑任务');
- $('#tsave').val('update');
- var tid = $(this).val();
- $('#tid').val(tid);
- $.get(url+tid,function (data) {
- console.log(url+tid);
- console.log(data);
- $('#tname').val(data.name);
- $('#tcontent').val(data.content);
- });
-
- $('#taskModal').modal('show');
- });
-
- $('#tsave').click(function () {
- if($('#tsave').val() == 'add') {
- turl = url;
- var type = "POST"; // add
- }
- else {
- turl = url + $('#tid').val();
- var type = "PUT"; // edit
- }
- var data = {
- name: $('#tname').val(),content: $('#tcontent').val()
- };
-
- $.ajax({
- type: type,url: turl,data: data,dataType: 'json',success: function (data) {
- console.log(data);
- $('#taskModal').modal('hide');
- $('#task').trigger('reset');
- var task = '<tr id="task' + data.id + '">' +
- '<td>'+ data.id +'</td>' +
- '<td>'+ data.name +'</td>' +
- '<td>'+ data.content +'</td>' +
- '<td>'+ data.created_at +'</td>' +
- '<td><button class="btn btn-info edit" value="'+ data.id +'">编辑</button> <button class="btn btn-warning delete" value="'+ data.id +'">删除</button>'+ '</td>' +
- '<tr>';
- console.log(task);
- if(type == 'POST') {
- $('#task-list').append(task);
- toastr.success('添加成功!');
- }
- else { // edit
- $('#task'+data.id).replaceWith(task);
- toastr.success('编辑成功!');
- }
- },"Error " + data.status +': '+ errorThrown);
- }
- });
-
- });
-
- });
问题记录
写这个教程遇到的问题也蛮大的,记录下来。
路由问题
之前路由是这样的:
- Route::resource('/','TaskController');
但是会出现404
问题,于是只好重定向到/task
中,问题解决。
- Route::get('/','TaskController');
新元素事件绑定问题
之前是这样绑定事件的:
- $('.delete').click(function () {
- ...
- }
但是会出现增加记录,无法点击触发事件的问题,将事件绑定到body
解决:
- $('body').on('click',function() {
- ...
- }
参考链接:Event binding on dynamically created elements?
响应Json
Laravel返回模型的时候默认以json
方式返回,所以无需response()->json()