Laravel 5 系列入门教程(二)【最适合中国人的 Laravel 教程】

2015-3-8   /   阅读数:159448   /   分类: Laravel

本教程示例代码见:https://github.com/johnlui/Learn-Laravel-5  

大家在任何地方卡住,最快捷的解决方式就是去看我的示例代码。

我们将改变学习路线,不再像 Laravel 4 教程那样先构建登录系统。在本篇教程中,我们将一起构建 Pages 的管理功能,尝试 Laravel 的路由和 PHP 的命名空间

1. 路由

Laravel 中的路由,跟其他 PHP 框架一样,作用是把各种请求分流到各个控制器。

在 `learnlaravel5/app/Http/routes.php` 的末尾添加以下代码:

Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function()
{
  Route::get('/', 'AdminHomeController@index');
});

这表示创建了一个路由组。

1. `'prefix' => 'admin'` 表示这个路由组的 url 前缀是 /admin,也就是说中间那一行代码 `Route::get('/'` 对应的链接不是 http://fuck.io:88/ 而是 http://fuck.io:88/admin ,如果这段代码是 `Route::get('fuck'` 的话,那么 URL 就应该是 http://fuck.io:88/admin/fuck

2. `'namespace' => 'Admin'` 表示下面的 `AdminHomeController@index` 不是在 `\App\Http\Controllers\AdminHomeController@index` 而是在 `\App\Http\Controllers\Admin\AdminHomeController@index`,加上了一个命名空间的前缀。

如果你用过 Laravel 4,会发现 Laravel 5 的命名空间规划比较怪异,这其实是一个非常大的进步。Laravel 4 其实已经全面引入了命名空间这个强大的特性,但是为了“降低学习成本”,把 路由、控制器、模型 的默认命名空间全部设置成了顶级命名空间,这个举动反而让很多人比较轻易地“上手”了 Laravel,但是在用了一段时间以后,还需要翻越一堵高墙,那就是命名空间,而且有了前面的“容易上手”的印象作为铺垫,后期的学习会更加困难。Laravel 5 把命名空间全部隔开,控制器在 `\App\Http\Controllers`,模型在 `\App`,让我们在刚上手的时候就体验命名空间分离的感觉,总体上其实是会降低学习成本的。

2. 控制器

我们可以使用 Artisan 非常方便地构建控制器:

php artisan make:controller Admin/AdminHomeController

得到 `learnlaravel5/app/Http/Controllers/Admin/AdminHomeController.php` 文件。

在 `class AdminHomeController extends Controller {` 上面增加一行:

use App\Page;

修改 index() 的代码如下:

public function index()
{
  return view('AdminHome')->withPages(Page::all());
}

控制器中文文档:http://laravel-china.org/docs/5.0/controllers

控制器中涉及到了许多的命名空间知识,可以参考 PHP 命名空间 解惑

3. 视图

新建 `learnlaravel5/resources/views/AdminHome.blade.php`:

@extends('app')

@section('content')
<div class="container">
  <div class="row">
    <div class="col-md-10 col-md-offset-1">
      <div class="panel panel-default">
        <div class="panel-heading">后台首页</div>

        <div class="panel-body">

        <a href="{{ URL('admin/pages/create') }}" class="btn btn-lg btn-primary">新增</a>

          @foreach ($pages as $page)
            <hr>
            <div class="page">
              <h4>{{ $page->title }}</h4>
              <div class="content">
                <p>
                  {{ $page->body }}
                </p>
              </div>
            </div>
            <a href="{{ URL('admin/pages/'.$page->id.'/edit') }}" class="btn btn-success">编辑</a>

            <form action="{{ URL('admin/pages/'.$page->id) }}" method="POST" style="display: inline;">
              <input name="_method" type="hidden" value="DELETE">
              <input type="hidden" name="_token" value="{{ csrf_token() }}">
              <button type="submit" class="btn btn-danger">删除</button>
            </form>
          @endforeach

        </div>
      </div>
    </div>
  </div>
</div>
@endsection

视图的基本用法在此不再赘述,请阅读中文文档:http://laravel-china.org/docs/5.0/views

访问 http://fuck.io:88/admin 得到如下页面:

Image

至此,包含 路由 》 控制器 》 模型 》 视图 的整个流程都已经完成。

4. 完成 Pages 管理功能

接下来,我将记录下我实现 Pages 管理功能的过程,不再做过多的阐述。大家有问题可以直接在本文下面留言,我会及时回复。

4.1 修改路由 learnlaravel5/app/Http/routes.php

Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function()
{
  Route::get('/', 'AdminHomeController@index');
  Route::resource('pages', 'PagesController');
});

此处增加了一条“资源控制器”,中文文档地址:http://laravel-china.org/docs/5.0/controllers#restful-resource-controllers

4.2 创建 learnlaravel5/app/Http/Controllers/Admin/PagesController.php

运行:

php artisan make:controller Admin/PagesController

4.3 修改 learnlaravel5/app/Http/Controllers/Admin/PagesController.php 为:

<?php namespace App\Http\Controllers\Admin;

use App\Http\Requests;
use App\Http\Controllers\Controller;

use Illuminate\Http\Request;

use App\Page;

use Redirect, Input, Auth;

class PagesController extends Controller {

	/**
	 * Show the form for creating a new resource.
	 *
	 * @return Response
	 */
	public function create()
	{
		return view('admin.pages.create');
	}

	/**
	 * Store a newly created resource in storage.
	 *
	 * @return Response
	 */
	public function store(Request $request)
	{
		$this->validate($request, [
			'title' => 'required|unique:pages|max:255',
			'body' => 'required',
		]);

		$page = new Page;
		$page->title = Input::get('title');
		$page->body = Input::get('body');
		$page->user_id = 1;//Auth::user()->id;

		if ($page->save()) {
			return Redirect::to('admin');
		} else {
			return Redirect::back()->withInput()->withErrors('保存失败!');
		}

	}

	/**
	 * Show the form for editing the specified resource.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function edit($id)
	{
		return view('admin.pages.edit')->withPage(Page::find($id));
	}

	/**
	 * Update the specified resource in storage.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function update(Request $request,$id)
	{
		$this->validate($request, [
			'title' => 'required|unique:pages,title,'.$id.'|max:255',
			'body' => 'required',
		]);

		$page = Page::find($id);
		$page->title = Input::get('title');
		$page->body = Input::get('body');
		$page->user_id = 1;//Auth::user()->id;

		if ($page->save()) {
			return Redirect::to('admin');
		} else {
			return Redirect::back()->withInput()->withErrors('保存失败!');
		}
	}

	/**
	 * Remove the specified resource from storage.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function destroy($id)
	{
		$page = Page::find($id);
		$page->delete();

		return Redirect::to('admin');
	}

}

4.4 创建视图文件

首先在 learnlaravel5/resources/views 下创建 admin/pages 两级文件夹。

然后创建 learnlaravel5/resources/views/admin/pages/create.blade.php:

@extends('app')

@section('content')
<div class="container">
  <div class="row">
    <div class="col-md-10 col-md-offset-1">
      <div class="panel panel-default">
        <div class="panel-heading">新增 Page</div>

        <div class="panel-body">

          @if (count($errors) > 0)
            <div class="alert alert-danger">
              <strong>Whoops!</strong> There were some problems with your input.<br><br>
              <ul>
                @foreach ($errors->all() as $error)
                  <li>{{ $error }}</li>
                @endforeach
              </ul>
            </div>
          @endif

          <form action="{{ URL('admin/pages') }}" method="POST">
            <input type="hidden" name="_token" value="{{ csrf_token() }}">
            <input type="text" name="title" class="form-control" required="required">
            <br>
            <textarea name="body" rows="10" class="form-control" required="required"></textarea>
            <br>
            <button class="btn btn-lg btn-info">新增 Page</button>
          </form>

        </div>
      </div>
    </div>
  </div>
</div>
@endsection

之后创建 learnlaravel5/resources/views/admin/pages/edit.blade.php:

@extends('app')

@section('content')
<div class="container">
  <div class="row">
    <div class="col-md-10 col-md-offset-1">
      <div class="panel panel-default">
        <div class="panel-heading">编辑 Page</div>

        <div class="panel-body">

          @if (count($errors) > 0)
            <div class="alert alert-danger">
              <strong>Whoops!</strong> There were some problems with your input.<br><br>
              <ul>
                @foreach ($errors->all() as $error)
                  <li>{{ $error }}</li>
                @endforeach
              </ul>
            </div>
          @endif

          <form action="{{ URL('admin/pages/'.$page->id) }}" method="POST">
            <input name="_method" type="hidden" value="PUT">
            <input type="hidden" name="_token" value="{{ csrf_token() }}">
            <input type="text" name="title" class="form-control" required="required" value="{{ $page->title }}">
            <br>
            <textarea name="body" rows="10" class="form-control" required="required">{{ $page->body }}</textarea>
            <br>
            <button class="btn btn-lg btn-info">编辑 Page</button>
          </form>

        </div>
      </div>
    </div>
  </div>
</div>
@endsection

4.5 查看结果

后台首页 http://fuck.io:88/admin

Image

新增 Page http://fuck.io:88/admin/pages/create

Image

编辑 Page http://fuck.io:88/admin/pages/1/edit

Image

页面上的新增、编辑、删除的功能均已经完成,并且加入了表单验证,Pages 管理功能完成!



教程(二)代码快照:https://github.com/johnlui/Learn-Laravel-5/archive/tutorial_2.zip


下一步:Laravel 5 系列入门教程(三)【最适合中国人的 Laravel 教程】

WRITTEN BY

avatar

评论:


2015-04-16 15:30
PDOException in Connector.php line 47:
SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost' (using password: YES)
我明明改  .env  了,为什么还是 'homestead'@'localhost'这个呢?
JohnLui
2015-04-16 15:47
@愚:看下 database.php 里面是不是获取 env 环境变量。如果确实是,可能需要配置成 “本地数据库配置”。文档:http://laravel-china.org/docs/5.0/configuration
见与不见1992
2015-04-30 10:51
@愚:你好~我也遇到了一样的问题,不过解决方案是将.env中的DB_HOST=localhost改为DB_HOST=“192.168.10.10”,现在问题暂时解决了,但是担心会因为这样的改动后期会出现其他问题,特来请教你是怎么改的?
Echol
2015-04-14 16:23
你好,请问withPages(Page::all())
这是获取整个表的数据,
假设我想倒序,或加上动态的限制条件应该怎么做呢
比如只需要某个范围内的id,并倒数或分组应该怎么做
JohnLui
2015-04-14 16:55
@Echol:排序:Page::orderBy('id', 'desc')->get();

具体请查看文档
Echol
2015-04-14 18:26
@JohnLui:请问,在AdminHomeController.php中
$pages=Page::orderBy('updated_at', 'desc')->get();
return view('AdminHome')->withPages($pages);
就ok
但如果把return改成return view('AdminHome',$pages);
会提示 Undefined variable: pages
不明白为什么
JohnLui
2015-04-14 21:10
@Echol:需要compact…
Echol
2015-04-15 23:31
@JohnLui:擦,我错
非常感谢花时间写这些教程&答疑,Thx
jinni
2015-04-09 17:29
感谢博主的教程,一步一步都还算顺利。
目前的问题是
1:新增数据commit后画面回到后台首页,数据能保存成功。
      可是新增的数据刷新不出来,一定要f5后才能显示出来。
      这是什么问题?如何解决?
2:edit按钮点下去后,Title 0这条数据会报错,
      NotFoundHttpException in compiled.php line 7755:
     其余数据都可以正常进入edit画面。

以上两个问题感觉都像是伪静态造成的,但是web方面很小白,盼回答。
JohnLui
2015-04-09 17:34
@jinni:问题1:缓存没有刷新,换浏览器解决。
问题2:NotFoundHttpException 这是 404 的意思,没有成功匹配路由。
jinni
2015-04-09 18:57
@JohnLui:谢谢博主回复
chrome清除缓存后问题2倒是解决了。。。
问题1还是存在中
Jinni
2015-04-09 19:37
@JohnLui:两个看起来都是缓存问题,再次感谢博主!
inxi
2015-04-08 16:04
有三个问题:
1:做Page的增删改查的时候,PagesController中的Redirect,input,auth为什么不用上完整的命名空间?phpstorm提示这三者都是在Illuminate\Support\Facades\下的。我使用你的方式不会有问题,加上完整的也不会有问题,但是Auth在app/http/controllers/下也有个
Auth命名空间,为什么没有完整的命名空间它不会使用到这个空间上去?我写上use App\Http\Controllers\Auth会出错。
2.代码有错误,在create,edit中,view的参数是错误的,提示view模板找不到。view的参数不就是对应模板的名字么,为什么写成admin.pages.create这种形式去了?
3.编辑的模板的名字和截图的名字对不上。。。
JohnLui
2015-04-08 16:15
@inxi:问题很好,很用心,赞一个

1. “phpstorm提示这三者都是在Illuminate\Support\Facades\下的” http://lvwenhan.com/laravel/433.html#comment-9372 这条评论解释了原理。其他的一些问题应该是你没有完全理解命名空间的各种用法导致的,推荐仔细阅读 《PHP 命名空间 解惑》 http://lvwenhan.com/php/401.html
2. admin.pages.create 这是子文件夹的意思。我在文中写了:

4.4 创建视图文件
首先在 learnlaravel5/resources/views 下创建 admin/pages 两级文件夹。
然后创建 learnlaravel5/resources/views/admin/pages/create.blade.php:

3. 教程中的代码忘了改了,我去改了。。
inxi
2015-04-09 09:59
@JohnLui:3q...后来都找到解释啦.
cheng
2015-04-04 13:25
有很多问题 >.>
因为我基本是初学者不知到怎么弄

use App\Page;
这句目标在哪里 :3

public function index()
{
  return view('AdminHome')->withPages(Page::all()); //不清楚这句
}

我什么架构都不熟悉
JohnLui
2015-04-04 13:43
@cheng:不用在意这几句是什么意思,直接用就是了,用多了,或者遇到问题了,就自然明白了。这是最高效的学习方式~
醉红颜
2015-04-03 16:04
为什么建好视图之后,输入http://localhost:8080/learnlaravel5/public/index.php/admin 会出现这个错误呢。
PDOException in E:\PHPTools\Apache2.4\Apache24\htdocs\learnlaravel5\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php line 47:
could not find driver
新手求指教啊
JohnLui
2015-04-03 17:23
@醉红颜:难道你的本地 PHP 环境没有 PDO 这个插件
醉红颜
2015-04-07 09:23
@JohnLui:第一次配PHP环境唉。什么几乎都不懂呢。
醉红颜
2015-04-07 10:29
@JohnLui:请问,怎么修改该框架的编码格式呢?大神求解。
小狼
2015-03-30 17:07
怎么才能做到Controller传入给view的html格式变量,不被转义?
JohnLui
2015-03-30 17:41
@小狼:{!! $name !!}
见:http://laravel-china.org/docs/5.0/templates#other-blade-control-structures
clovergame
2015-03-26 17:35
首先感谢下博主为大家贡献了一份非常精彩的教程.本人菜鸟,有个疑问,crate.blade.php文件中23行
<form action="{{ URL('admin/pages') }}" method="POST">
            <input type="hidden" name="_token" value="{{ csrf_token() }}">
            <input type="text" name="title" class="form-control" required="required">
            <br>
            <textarea name="body" rows="10" class="form-control" required="required"></textarea>
            <br>
            <button class="btn btn-lg btn-info">新增 Page</button>
   </form>
这里的按钮并没有type='submit',却也能够提交表单,并且在实际的网页源代码中出现了bootstrap和jquery的js文件,请问这些是怎么做到的,谢谢
JohnLui
2015-03-26 17:53
@clovergame:能提交表单是因为 chrome 的原因吧。。。静态文件的调用在父 view 里面。
clovergame
2015-03-27 08:21
@JohnLui:明白了,谢谢
spike
2015-03-25 14:24
小弟又来求教了。。PagesController.php里‘use Redirect, Input, Auth;’这句为什么没有路径呢。。
之前没仔细学过php,问了小白问题~
JohnLui
2015-03-25 17:04
@spike:隐藏了,参见 《PHP 命名空间 解惑》 http://lvwenhan.com/php/401.html
spike
2015-03-26 11:32
@JohnLui:查了一下下,这个是不是在\laravel\config\app.php里声明的呢。
'aliases' => [

'Auth'      => 'Illuminate\Support\Facades\Auth',

'Input'     => 'Illuminate\Support\Facades\Input',

'Redirect'  => 'Illuminate\Support\Facades\Redirect',
],
spike
2015-03-26 11:46
@JohnLui:还有个小问题。。我看\laravel\vendor\laravel\framework\src\Illuminate\Support\Facades下的Input.php和Redirect.php源文件,为啥它们最开始都有一句注释呢
/**
* @see \Illuminate\Http\Request
*/
/**
* @see \Illuminate\Routing\Redirector
*/
我这么问是因为,我在教程四的CommentsController 中看你调用了Input::all()和Redirect::back()这些方法。。
但在对应的类和父类里没找到这些方法。。可是在他注释里提到的类里找到了。。

菜鸟一枚,但想搞清楚。。先多谢赐教了~
JohnLui
2015-03-26 12:46
@spike:这里:http://laravel-china.org/docs/5.0/facades
spike
2015-03-26 13:54
@JohnLui:多谢指导~一环扣一环太有意思了~
堕落到妖灬
2015-03-18 17:12
在编辑的页面中加入了<input name="_method" type="hidden" value="PUT">这一句代码  然后点击提交就会出现MethodNotAllowedHttpException in RouteCollection.php line 207:这个错误  这是什么情况?
JohnLui
2015-03-18 17:59
@堕落到妖灬:这涉及到 Laravel 底层对 PUT PATCH 等方法实现的细节,你看一下我的代码就明白了。
堕落到妖灬
2015-03-18 20:58
@JohnLui:代码和你的代码一样  但是还是报错?不知道怎么解决   小白一个  求赐教
堕落到妖灬
2015-03-18 21:00
@JohnLui:更加诡异的是删除方法里面不是也有这行代码么?<input name="_method" type="hidden" value="DELETE">为什么在删除的时候不报错呢?在更新的时候就不行了
JohnLui
2015-03-18 22:24
@堕落到妖灬:上面的 form 里要有 method="POST".
堕落到妖灬
2015-03-18 22:37
@JohnLui:<form action="{{ URL('admin/admin/'.$admin->id) }}" method="POST" role="form" class="form-horizontal">
                    <input type="hidden" name="_method" value="PUT">
                    <input type="hidden" name="_token" value="{{ csrf_token() }}">
都有的  没问题
堕落到妖灬
2015-03-18 22:45
@JohnLui:谢谢  JohnLui 是我自己把{{ URL('admin/admin/'.$admin->id) }}参数弄错了  应该是这样的
{{ URL('admin/admin/'.$admin->admin_id) }}
Salon
2015-03-17 15:32
貌似php artisan make:view 在laravel5里面没有了。有点不爽了
Salon
2015-03-17 10:50
版主您好~我从laravel4开始就留意的blog了。因为真的很有受益。
我发现你的controller也改用了view()这个方法。比起l4,l5增加了view(),redirect(),response()的方法,并且使用依赖注入的编程思想。
想问问其实view(),redirect(),response()这些如此方便的方法是在哪里来的的呢?我往下找父类没找到这些方法。不知道版主有没有研究。
谢谢版主的浏览和分享
JohnLui
2015-03-17 15:22
@Salon:其实就是以前的 Response::view() Redirect::to() Response::make() 啦
yxr
2015-03-12 10:17
在浏览器打开
FatalErrorException in AdminHomeController.php line 18: Class 'App\Http\Controllers\Admin\Page' not found

    in AdminHomeController.php line 18
    at HandleExceptions->fatalExceptionFromError(array('type' => '1', 'message' => 'Class 'App\Http\Controllers\Admin\Page' not found', 'file' => '/usr/local/nginx/html/laravel2/app/Http/Controllers/Admin/AdminHomeController.php', 'line' => '18')) in compiled.php line 1738
    at HandleExceptions->handleShutdown()
JohnLui
2015-03-12 11:44
@yxr:顶部缺少 use App\Page;
黼黻
2015-03-11 16:27
BadMethodCallException in compiled.php line 8295:
Method [show] does not exist.
好像是 method="DELETE" 这个不管用,是不是我哪里没有设置。
JohnLui
2015-03-11 17:41
@黼黻: 参考我的代码,里面有
Zreke
2015-03-12 10:55
@黼黻:在4.2章节里,修改 learnlaravel5/resources/views/AdminHome.blade.php的时候,下面这部分代码错了
<form action="{{ URL('admin/pages/'.$page->id) }}" method="DELETE" style="display: inline;">
    <button type="submit" class="btn btn-danger">删除</button>
</form>
修改成参考代码里面的,或者是在3. 章节里  视图新建 `learnlaravel5/resources/views/AdminHome.blade.php`:下面的
<form action="{{ URL('admin/pages/'.$page->id) }}" method="POST" style="display: inline;">
     <input name="_method" type="hidden" value="DELETE">
     <input type="hidden" name="_token" value="{{ csrf_token() }}">
     <button type="submit" class="btn btn-danger">删除</button>
</form>

PS:好吧,写的有点啰嗦,希望你能看的懂
JohnLui
2015-03-12 11:46
@Zreke: 实际代码更新了,教程里的代码没更新
JohnLui
2015-03-12 11:53
@Zreke: 这个 4.2 根本就是多余的,感谢你发现了这个问题
黼黻
2015-03-12 15:06
@Zreke:看到了,谢谢。
黼黻
2015-03-11 16:17
是不是没有删除功能
12
2015-03-11 03:43
JasonPHP
2015-03-09 16:03
在PageController 中 update 验证中如果只修改其中body ,而title不变 ,验证通不过··怎么修改验证条件;
JohnLui
2015-03-09 16:23
@JasonPHP:这是个 bug,代码已经更新
lewisliang82
2015-03-09 14:24
Route::get('/', 'AdminHomeComtroller@index');里面有一个错误Comtroller
JohnLui
2015-03-09 14:49
@lewisliang82:
Jason
2015-03-31 01:24
@lewisliang82:對啊, 我也找了很久才發現。
很好的教學

发表评论:

© 2011-2019 岁寒  |  Powered by Emlog