lavarel5.2官方文档阅读——基本概念

《目录》php

1.安装html

2.配置laravel

3.基本操做git

4.中级操做github

5.路由web

6.中间件express

7.控制器json

8.请求对象api

9.响应对象数组

10.views视图

11.blade模板引擎

 

1.安装

若经过Composer 或 the Laravel installer 进行项目建立,会使用php artisan key:generate自动生成一个app_key,保存在.env文件中。该key的做用是保证session等加密数据的安全。

config/app.php中的配置通常不用改,其中的timezone和locale能够根据实际状况配置一下。

2.配置

在代码中,配置的使用:

$value = config('app.timezone');//读取配置值
config(['app.timezone' => 'America/Chicago']);//运行中设置配置值

环境配置,位于.env.php中,使用方法,第二个参数是默认值:

'debug' => env('APP_DEBUG', false),

在生产环境下,开启配置文件的缓存:

php artisan config:cache

上述方式使得配置融合进一个文件当中,能够加快配置的载入。

开启维护模式,在维护模式下,网站将使用resources/views/errors/503.blade.php做为响应

php artisan down//启动维护模式
php artisan up//关闭维护模式

官方提供了homestead虚拟机,用于构建lavarel开发环境。

3.基本操做

建立新项目:

composer create-project laravel/laravel quickstart --prefer-dist
git clone https://github.com/laravel/quickstart-basic quickstart cd quickstart composer install php artisan migrate

新建数据表:

php artisan make:migration create_tasks_table --create=tasks //在database文件夹中新生成的文件中添加name字段
<?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateTasksTable extends Migration { /** * Run the migrations. * * @return void */
    public function up() { Schema::create('tasks', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */
    public function down() { Schema::drop('tasks'); } }

新建model:

php artisan make:model Task //新生成的文件以下:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Task extends Model { // }

新建route,使用web中间件,使得他们具备session state 和 CSRF protection:

(帐号项目中好像没用到这个)

//文件位于app/Http/routes.php
<?php use App\Task; use Illuminate\Http\Request; Route::group(['middleware' => 'web'], function () { /** * Show Task Dashboard */ Route::get('/', function () { //  }); /** * Add New Task */ Route::post('/task', function (Request $request) { //  }); /** * Delete Task */ Route::delete('/task/{task}', function (Task $task) { //  }); });

网页视图位于resources/views中,调用方式:

Route::get('/', function () { return view('tasks'); //该视图文件位于resources/views/tasks.blade.php中
});

布局layout文件,通常地,应该建立到resources/views/layouts/app.blade.php

<!-- resources/views/layouts/app.blade.php -->

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Laravel Quickstart - Basic</title>

        <!-- CSS And JavaScript -->
    </head>

    <body>
        <div class="container">
            <nav class="navbar navbar-default">
                <!-- Navbar Contents -->
            </nav>
        </div> @yield('content') //这是section的名称,能够被子视图继承
    </body>
</html>

添加tasks子视图,并继承上述的layouts:

<!-- resources/views/tasks.blade.php --> @extends('layouts.app') //继承layouts视图
 @section('content')//扩展其中的content section

    <!-- Bootstrap Boilerplate... -->

    <div class="panel-body">
        <!-- Display Validation Errors --> @include('common.errors') //直接载入另外一个视图文件,该文件位于resources/views/common/errors.blade.php

        <!-- New Task Form -->
        <form action="{{ url('task') }}" method="POST" class="form-horizontal"> {!! csrf_field() !!} <!-- Task Name -->
            <div class="form-group">
                <label for="task" class="col-sm-3 control-label">Task</label>

                <div class="col-sm-6">
                    <input type="text" name="name" id="task-name" class="form-control">
                </div>
            </div>

            <!-- Add Task Button -->
            <div class="form-group">
                <div class="col-sm-offset-3 col-sm-6">
                    <button type="submit" class="btn btn-default">
                        <i class="fa fa-plus"></i> Add Task </button>
                </div>
            </div>
        </form>
    </div>

    <!-- TODO: Current Tasks --> @endsection

完成建立任务的表单:

//路由以下设置:
Route::post('/task', function (Request $request) { $validator = Validator::make($request->all(), [ 'name' => 'required|max:255', ]); if ($validator->fails()) { return redirect('/') ->withInput() ->withErrors($validator); //这里将flash错误到session中。视图中使用$errors变量
 } // Create The Task...
    $task = new Task; $task->name = $request->name; $task->save(); return redirect('/'); }); //处理错误的视图
<!-- resources/views/common/errors.blade.php --> @if (count($errors) > 0) //$errors是ViewErrorBag类的实例
    <!-- Form Error List -->
    <div class="alert alert-danger">
        <strong>Whoops! Something went wrong!</strong>

        <br><br>

        <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach
        </ul>
    </div> @endif

展现已有的tasks:

//routes.php中
Route::get('/', function () { $tasks = Task::orderBy('created_at', 'asc')->get(); return view('tasks', [ 'tasks' => $tasks ]); }); //对应的views中:
@extends('layouts.app') @section('content') <!-- Create Task Form... -->

    <!-- Current Tasks --> @if (count($tasks) > 0) <div class="panel panel-default">
            <div class="panel-heading">
                Current Tasks </div>

            <div class="panel-body">
                <table class="table table-striped task-table">

                    <!-- Table Headings -->
                    <thead>
                        <th>Task</th>
                        <th>&nbsp;</th>
                    </thead>

                    <!-- Table Body -->
                    <tbody> @foreach ($tasks as $task) <tr>
                                <!-- Task Name -->
                                <td class="table-text">
                                    <div>{{ $task->name }}</div>
                                </td>

                                <td>
                                     <form action="{{ url('task/'.$task->id) }}" method="POST"> {!! csrf_field() !!} {!! method_field('DELETE') !!} <button type="submit" class="btn btn-danger">
                                             <i class="fa fa-trash"></i> Delete </button>
                                     </form>
                                </td>
                            </tr> @endforeach
                    </tbody>
                </table>
            </div>
        </div> @endif @endsection

用于删除task的路由:

//这里使用了隐式对象绑定:https://laravel.com/docs/5.2/routing#route-model-binding
Route::delete('/task/{task}', function (Task $task) { $task->delete(); return redirect('/'); });

4.中级操做

laravel自带了users表。

增长string类型的字段$table->string('name');

增长int类型的字段$table->integer('user_id')->index(); //这个是用来设置索引的?

创建用户、任务之间的1对多关系,能够直接使用$user->tasks进行调用

//在User类中:
public function tasks() { return $this->hasMany(Task::class); }
//在Task类中:
public function user() { return $this->belongsTo(User::class); }

全部的TaskController中的方法都须要登录的用户才能执行,使用auth中间件进行指定:

class TaskController extends Controller { /** * Create a new controller instance. * * @return void */
    public function __construct() { $this->middleware('auth'); } }

对输入数据进行validate:

/** * Create a new task. * * @param Request $request * @return Response */
public function store(Request $request) { $this->validate($request, [ 'name' => 'required|max:255', ]); //此处若是验证失败了,就自动重定向回/tasks,包含旧的input和遇到的errors // Create The Task...
}

建立新Task:

/** * Create a new task. * * @param Request $request * @return Response */
public function store(Request $request) { $this->validate($request, [ 'name' => 'required|max:255', ]); $request->user()->tasks()->create([//自动填充了task表的user_id字段
        'name' => $request->name, ]); return redirect('/tasks'); }

依赖注入。建立app/Repositories文件夹,而且建立TaskRepository类(repository的做用是将一些共有的查询代码进行共享)

<?php namespace App\Repositories; use App\User; use App\Task; class TaskRepository { /** * Get all of the tasks for a given user. * * @param User $user * @return Collection */
    public function forUser(User $user) { return Task::where('user_id', $user->id) ->orderBy('created_at', 'asc') ->get(); } }

注入这个Repository。使用type-hint,在Task控制器的构造方法中注入,Lavarel使用容器解析全部的controller类,因此这个依赖能够被自动注入到控制器的实例当中:

<?php namespace App\Http\Controllers; use App\Task; use App\Http\Requests; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use App\Repositories\TaskRepository; class TaskController extends Controller { /** * The task repository instance. * * @var TaskRepository */
    protected $tasks; /** * Create a new controller instance. * * @param TaskRepository $tasks * @return void */
    public function __construct(TaskRepository $tasks) { $this->middleware('auth'); $this->tasks = $tasks; } /** * Display a list of all of the user's task. * * @param Request $request * @return Response */
    public function index(Request $request) { return view('tasks.index', [ 'tasks' => $this->tasks->forUser($request->user()), ]); } }

删除Task时的验证,只容许用户删除本身的Task,不容许删除他人的。这里使用policy:

php artisan make:policy TaskPolicy
//在新生成的TaskPolicy中添加代码
<?php namespace App\Policies; use App\User; use App\Task; use Illuminate\Auth\Access\HandlesAuthorization; class TaskPolicy { use HandlesAuthorization; /** * Determine if the given user can delete the given task. * * @param User $user * @param Task $task * @return bool */
    public function destroy(User $user, Task $task) { return $user->id === $task->user_id; } }

而后,将Model和Policy联系起来:

//文件位于app/Providers/AuthServiceProvider.php //增长一行键值对:

/** * The policy mappings for the application. * * @var array */
protected $policies = [ 'App\Task' => 'App\Policies\TaskPolicy', ];

在Model中应用该验证。说明:这里运用authorize方法,指定policy名称为destroy,传入实例$task,验证若是失败,会自动返回403错误页面:

/** * Destroy the given task. * * @param Request $request * @param Task $task * @return Response */
public function destroy(Request $request, Task $task) { $this->authorize('destroy', $task); $task->delete(); return redirect('/tasks'); }

5.路由Routing

位于app/Http/routes.php中,基本的路由写法为url加一个闭包构成:

Route::get('foo', function () { return 'Hello World'; });

路由规则位于web中间件的group中,以使用sessions和CSRF保护(实践中发现,若是不位于此,将没法使用$errors变量):

Route::group(['middleware' => ['web']], function () { // });

路由接受的请求的类型:

Route::match(['get', 'post'], '/', function () { //接受多种请求类型的路由
}); Route::any('foo', function () { //接受全部请求类型的路由
});

路由能够接受参数,用大括号括起来。参数后面带一个问号,标明该参数是可选的(这种状况下,须要在函数传参时,给它一个默认值):

Route::get('user/{id}', function ($id) { return 'User '.$id; }); Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) { // }); Route::get('user/{name?}', function ($name = null) { return $name; }); Route::get('user/{name?}', function ($name = 'John') { return $name; });

 

能够对某个路由规则进行命名,指定其name,这样在重定向时将十分方便:

Route::get('profile', ['as' => 'profile', function () { // }]); Route::get('profile', [ 'as' => 'profile', 'uses' => 'UserController@showProfile' ]); Route::get('user/profile', 'UserController@showProfile')->name('profile');

其余几种命名路由的使用方式:

Route::group(['as' => 'admin::'], function () { Route::get('dashboard', ['as' => 'dashboard', function () { // Route named "admin::dashboard"
 }]); }); // Generating URLs...
$url = route('profile'); // Generating Redirects...
return redirect()->route('profile'); Route::get('user/{id}/profile', ['as' => 'profile', function ($id) { // }]); $url = route('profile', ['id' => 1]);//route函数的第二个参数做为路由规则的对应参数传入

路由组Route groups的概念,容许设定多个路由的共同属性,这些共有属性做为Route::group方法的第一个参数,以数组形式传入。如下为使用的几种方式:

//(1)指定路由规则使用的中间件,中间件的执行顺序与此处定义顺序相同
Route::group(['middleware' => ['auth']], function () { Route::get('/', function () { // Uses Auth Middleware
 }); Route::get('user/profile', function () { // Uses Auth Middleware
 }); }); //(2)指定控制器的命名空间,这里只须要指定App\Http\Controllers\后面路径名便可
Route::group(['namespace' => 'Admin'], function() { // Controllers Within The "App\Http\Controllers\Admin" Namespace
 Route::group(['namespace' => 'User'], function() { // Controllers Within The "App\Http\Controllers\Admin\User" Namespace
 }); }); //(3)指定子域的路由规则: //这个试了下,要指定hosts文件中IP qxxx.myapp.com条目,那么在访问qxxx.myapp.com:端口号/user/{id}时,便可匹配到此路由。
Route::group(['domain' => '{account}.myapp.com'], function () { Route::get('user/{id}', function ($account, $id) { //  }); }); //(4)指定路由url的前缀:
Route::group(['prefix' => 'accounts/{account_id}'], function () { Route::get('detail', function ($accountId) { // Matches The "/accounts/{account_id}/detail" URL
 }); });

CSRF跨站请求伪造的防范:

//在表单内部提供csrf token隐藏域 // Vanilla PHP
<?php echo csrf_field(); ?>

// Blade Template Syntax
{{ csrf_field() }} //生成了以下标签:
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">

web中间件中的VerifyCsrfToken中间件将自动的验证这类token是否与session中存储的token一致(这里是怎么个原理呢?为何就能防范)

若是不想使某些url进行这种防范,第一种方法是将路由规则写在web中间件以外,第二种是修改VerifyCsrfToken类的except数组变量:

<?php namespace App\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier; class VerifyCsrfToken extends BaseVerifier { /** * The URIs that should be excluded from CSRF verification. * * @var array */
    protected $except = [//再也不验证此数组中指定的url的csrf token
        'stripe/*', ]; }

路由与模型的自动绑定,若是路由的action函数的参数中包含type-hint的类,lavarel自动使用url中的参数获取到对应的类型:

//默认地,获取的类型实例是以ID字段查出来的
Route::get('api/users/{user}', function (App\User $user) { return $user->email; }); //经过重写model类的getRouteKeyName方法,能够改变对应的字段 /** * Get the route key for the model. * * @return string */
public function getRouteKeyName() { return 'slug'; }

上述为隐式绑定,也能够进行显示绑定,即人工指定绑定的方式:

//在RouteServiceProvider::boot方法中,指明这种绑定
public function boot(Router $router) { parent::boot($router); $router->model('user', 'App\User'); } //如下这些都是写在上述的方法中的。 //还能够自定义这种解析逻辑:
$router->bind('user', function($value) { return App\User::where('name', $value)->first(); }); //当这种绑定失败时,即查询不到参数对应的数据时,默认的返回404,也能够对这种行为进行定制:
$router->model('user', 'App\User', function() { throw new NotFoundHttpException; });

表单的提交方式指定:

//指定为PUT方式提交:
{{ method_field('PUT') }} //生成的html以下:
<input type="hidden" name="_method" value="PUT">

获取当前路由的name和Action(路由请求类型):

$route = Route::current(); $name = $route->getName(); $actionName = $route->getActionName(); //或使用如下方法:
$name = Route::currentRouteName(); $action = Route::currentRouteAction();

6.中间件Middleware

中间件提供了一种方便的过滤http请求的机制,例如,中间件能够验证用户,若用户未登陆,则重定向至login,不然,就会继续容许用户的访问。其余中间件也能够完成各类各样的任务,CORS负责为全部的响应添加合适的Headers、LOGGing会记录下全部的请求状况。Laravel中包含了maintenance、authentication、CSRF等多种中间件。

建立一个新中间件,中间件位于app/Http/Middleware中

php artisan make:middleware AgeMiddleware

下列的中间件限定了只有在输入的age大于200时,才能够继续访问应用(将中间件想象成一个层,http请求须要通过一个个这样的层,以到达应用的核心处理函数。其中的$next方法意味着将该请求继续向深层传递):

<?php namespace App\Http\Middleware; use Closure; class AgeMiddleware { /** * Run the request filter. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */
    public function handle($request, Closure $next) { if ($request->input('age') <= 200) { return redirect('home'); } return $next($request); } }

中间件被调用的时机,包括在请求处理前请求处理后两种:

//在请求被处理前使用,对$request对象进行处理
<?php namespace App\Http\Middleware; use Closure; class BeforeMiddleware { public function handle($request, Closure $next) { // Perform action

        return $next($request); } } //在请求处理后使用的中间件,此处对$response对象进行处理
<?php namespace App\Http\Middleware; use Closure; class AfterMiddleware { public function handle($request, Closure $next) { $response = $next($request); // Perform action

        return $response; } }

中间件的使用,注册并使用中间件:

//(1)若想要对全部的请求使用中间件,请更改app/Http/Kernel.php中的$middleware变量 //(2)若想要在路由规则中使用中间件,须要首先在app/Http/Kernel.php中修改$routeMiddleware变量,加入本身的中间件、而且命名:
protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, ]; // 其次,在路由规则中进行指定:
Route::get('/', ['middleware' => ['first', 'second'], function () { //中间件传入一个变量,或一个数组
}]); // 或使用:
Route::get('/', function () { // })->middleware(['first', 'second']); // 甚至也能够直接使用类名:
use App\Http\Middleware\FooMiddleware; Route::get('admin/profile', ['middleware' => FooMiddleware::class, function () { // }]); //(3)中间件组:为了方便将多个中间件“集合”到一个中,方便进行使用和分配,依旧是更改app/Http/Kernel.php中的以下变量: /** * The application's route middleware groups. * * @var array */
protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, ],

    'api' => [ 'throttle:60,1',
        'auth:api', ], ]; // 在进行分配时,方法是同样的。

中间件也能够接收参数,从第三个变量以后,为传入的参数:

//中间件的定义,使用了$role参数,限定用户的角色
<?php namespace App\Http\Middleware; use Closure; class RoleMiddleware { /** * Run the request filter. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string $role * @return mixed */
    public function handle($request, Closure $next, $role) { if (! $request->user()->hasRole($role)) { // Redirect...
 } return $next($request); } } //在进行分配使用时,中间件名称与参数经过冒号分割,多个参数使用逗号进行分割:
Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) { // }]);

收尾中间件,Terminable Middleware,在响应被返回到浏览器后,作一些收尾工做,好比说lavarel的session中间件将会把会话数据写入存储中。要实现收尾中间件,须要在中间件中定义terminate方法,并且,这种中间件必须被定义为全局中间件:

<?php namespace Illuminate\Session\Middleware; use Closure; class StartSession { public function handle($request, Closure $next) { return $next($request); } public function terminate($request, $response) { // Store the session data...
 } } //深层次地,当调用terminate中间件方法时,laravel从service container中从新实例化一个中间件类。若想要在使用handle和terminate时使用同一个实例,则须要在注册该中间件到container中时,使用container的singleton方法。(具体如何操做这里还没讲到)

7.控制器Controllers

先看一个例子:

<?php namespace App\Http\Controllers; use App\User; use App\Http\Controllers\Controller; class UserController extends Controller { /** * Show the profile for the given user. * * @param int $id * @return Response */
    public function showProfile($id) { return view('user.profile', ['user' => User::findOrFail($id)]); } }

控制器的命名空间,在指定route对应的控制器动做时,只需指定App\Http\Controllers以后的路径名,由于默认地,RouteServiceProvider将会把routes文件载入到一个包含上述命名空间的路由组中。

在controller中分配中间件(这种方式比在路由中指定要更方便):

class UserController extends Controller { /** * Instantiate a new UserController instance. * * @return void */
    public function __construct() { $this->middleware('auth'); //全部方法均适用

        $this->middleware('log', ['only' => [//只限于下列方法适用
            'fooAction',
            'barAction', ]]); $this->middleware('subscribed', ['except' => [//排除如下方法
            'fooAction',
            'barAction', ]]); } }

RESTful资源访问控制器,使用命令php artisan make:controller PhotoController --resource新建一个控制器:

//向该类控制器指定路由规则
Route::resource('photo', 'PhotoController');
//另外可使用下列方法限定该种路由表的范围:
Route::resource('photo', 'PhotoController', ['only' => [ 'index', 'show' ]]); Route::resource('photo', 'PhotoController', ['except' => [ 'create', 'store', 'update', 'destroy' ]]);
Route::resource('photo', 'PhotoController', ['names' => [ 'create' => 'photo.build'//能够经过names数组从新定义路由规则的名称 ]]);
 
//这条路由规则默认地创建一下路由表:

对资源路由规则的参数的命名:

//默认地,lavarel将根据resource第一个参数,即资源名对参数进行命名 //好比资源名叫作user,那么参数名就叫作user //若是想更改这种行为,使用如下方式:
Route::resource('user', 'AdminUserController', ['parameters' => [ 'user' => 'admin_user' ]]); //下面这个方式将参数名改成单数形式,而非资源名的复数形式
Route::resource('users.photos', 'PhotoController', [ 'parameters' => 'singular' ]); //或者用如下的方法,全局地设定参数名规则:
Route::singularResourceParameters(); Route::resourceParameters([ 'user' => 'person', 'photo' => 'image' ]); //注意以上几种方式的优先级: //1.显示地传入resource的参数。2.全局设定的参数名。3.singular设置。4.默认值

注意:请将自定义的路由规则放于resource规则之上,由于可能会被resource规则覆盖掉。

对控制器的依赖注入,服务容器service container被用来解析全部的controller,因此在controller中可使用type-hint方式指定方法所需的依赖类实例,这个依赖会自动被解析,而且注入到控制器类的实例中:

<?php namespace App\Http\Controllers; use App\Repositories\UserRepository; class UserController extends Controller { /** * The user repository instance. */
    protected $users; /** * Create a new controller instance. * * @param UserRepository $users * @return void */
    public function __construct(UserRepository $users)//在构造函数中的依赖注入,repository参见:这里
 { $this->users = $users; } **
     * Store a new user.
     *
     * @param  Request  $request
     * @return Response */
    public function store(Request $request)//在方法中的依赖注入
 { $name = $request->input('name'); //  } /** * Update the specified user. * * @param Request $request * @param string $id * @return Response */
    public function update(Request $request, $id)//依赖注入的同时,还能够接收路由规则传进来的参数
 { //  } }

路由规则的缓存,请使用命令php artisan route:cache,将极快的提升注册应用路由的速度(可是开发中若是更改了路由规则,请从新运行这个命令。若想删除路由缓存,使用php artisan route:clear

8.请求对象Request

Request类的基本方法:

//对于http://domain.com/foo/bar,返回foo/bar
$uri = $request->path(); //url()和fullUrl()返回彻底的网址: // Without Query String...
$url = $request->url(); // With Query String...
$url = $request->fullUrl(); $url = $request->fullUrlWithQuery(['bar' => 'baz']); //对于http://domain.com/foo返回http://domain.com/foo?bar=baz //is方法返回是否匹配某个uri模式:
if ($request->is('admin/*')) { // } //取请求的method:
$method = $request->method(); if ($request->isMethod('post')) { // } //取用户的表单输入:
$name = $request->input('name'); $name = $request->input('name', 'Sally');//第二个参数为默认值
$name = $request->input('products.0.name');//这个和下面那个适用于forms with array inputs,这是什么???
$names = $request->input('products.*.name'); //取json格式的输入(请求头必须有Content-Type:application/json):
$name = $request->input('user.name');//点号能够取json的下层结构
if ($request->has('name')) {//判断是否存在某输入字段 //
} $input = $request->all();//取出全部的输入参数,返回一个数组
$input = $request->only(['username', 'password']);//下面这四个是取输入的一部分参数
$input = $request->only('username', 'password'); $input = $request->except(['credit_card']); $input = $request->except('credit_card'); $name = $request->name;//也能够这么取name字段,顺序是先以route规则中的参数,其次以请求体中的参数 //旧有的输入,在表单出错时,复如今用户页面上
$request->flash();//将输入flash到session里,在用户下一次的请求中仍可访问
$request->flashOnly(['username', 'email']); $request->flashExcept('password'); //重定向加flash:
return redirect('form')->withInput(); return redirect('form')->withInput($request->except('password')); //使用上一个请求中的old输入:
$username = $request->old('username');//代码里使用
<input type="text" name="username" value="{{ old('username') }}">//blade模板中使用 //cookie:全部的lavarel的cookie都是加密的,而且用受权码签名
$value = $request->cookie('name'); $response = new Illuminate\Http\Response('Hello World');//新建一个cookie
$response->withCookie('name', 'value', $minutes); return $response; $response->withCookie(cookie()->forever('name', 'value'));//新建一个永久cookie,五年 //文件类操做
$file = $request->file('photo');//获取一个上传的文件对象UploadedFile的实例
if ($request->hasFile('photo')) {//判断请求对象中是否包含一个文件 //
} if ($request->file('photo')->isValid()) {//判断是否已经成功上传该文件 //
} $request->file('photo')->move($destinationPath);//移动文件,从临时上传位置移走(这位置是根据php的配置决定的)
$request->file('photo')->move($destinationPath, $fileName);//移动文件而且重命名

9.响应对象Response

//相比于return一个字符串来讲,响应对象可以提供更多的控制响应体的操做
use Illuminate\Http\Response; Route::get('home', function () { return (new Response($content, $status)) ->header('Content-Type', $value); }); Route::get('home', function () {//response是其工厂函数
    return response($content, $status) ->header('Content-Type', $value); }); //response对象的大部分方法是能够级联调用的
return response($content) ->header('Content-Type', $type) //使用header方法设置响应头
            ->header('X-Header-One', 'Header Value') ->header('X-Header-Two', 'Header Value'); return response($content) ->withHeaders([//使用withHeaders方法设置多个响应头域
                'Content-Type' => $type,
                'X-Header-One' => 'Header Value',
                'X-Header-Two' => 'Header Value', ]); //使用cookie方法添加新的cookie值 //cookie方法的原型:cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly)
return response($content) ->header('Content-Type', $type) ->cookie('name', 'value'); //lavarel生成的cookie都是加密的,能够将其关掉: //位于App\Http\Middleware\EncryptCookies中 /** * The names of the cookies that should not be encrypted. * * @var array */
protected $except = [//此数组中的cookie值是不加密的。
    'cookie_name', ]; //当response方法不带参数调用时,产生一个implementation of the Illuminate\Contracts\Routing\ResponseFactory contract //在同时须要返回视图和控制response的状态和头时,使用下列方法:
return response() ->view('hello', $data) ->header('Content-Type', $type); //返回json数据,并自动设置Content-Type:application/json
return response()->json(['name' => 'Abigail', 'state' => 'CA']); //使浏览器下载一个文件:
return response()->download($pathToFile);//第一个参数是文件的路径
return response()->download($pathToFile, $name, $headers);//第二个是用户看到的文件名,第三个是控制响应的header域 //直接在浏览器展现一个文件,而无需下载
return response()->file($pathToFile); return response()->file($pathToFile, $headers); //重定向的response
Route::get('dashboard', function () { return redirect('home/dashboard');//最简单的方式,使用redirect方法
}); //在表单验证失败后,重定向至前一个页面(注意,使用back的路由规则必须已经使用了web中间件
Route::post('user/profile', function () { // Validate the request...
    return back()->withInput(); }); //重定向至某个路由规则
return redirect()->route('login', ['id' => 1]);//第二个参数为路由url参数 //重定向至某个控制器方法
return redirect()->action('UserController@profile', ['id' => 1]); //重定向,而且把参数放进session中:
Route::post('user/profile', function () { // Update the user's profile...
    return redirect('dashboard')->with('status', 'Profile updated!'); }); @if (session('status')) <div class="alert alert-success"> {{ session('status') }} </div> @endif

//响应请求宏macro //若想要自定义一个响应对象以便route和controller共用、重用,可使用Response facade:
<?php namespace App\Providers; use Response; use Illuminate\Support\ServiceProvider; class ResponseMacroServiceProvider extends ServiceProvider { /** * Perform post-registration booting of services. * * @return void */
    public function boot() { Response::macro('caps', function ($value) { return Response::make(strtoupper($value)); }); } } //这样,在route中就能够用相应的函数名返回响应对象:
return response()->caps('foo');

10.视图views

//决定view是否存在:
if (view()->exists('emails.customer')) { // } //传参:
return view('greetings', ['name' => 'Victoria']); return view('greeting')->with('name', 'Victoria'); //在全部的views中共享一个变量(在AppServiceProvider的service provider的boot方法中调用view()->share(' ', ' ');)
<?php namespace App\Providers; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */
    public function boot() { view()->share('key', 'value'); } /** * Register the service provider. * * @return void */
    public function register() { //  } } //view composer的使用场景:当view视图被渲染时,它所绑定的类或者闭包函数将会被调用。当某个视图须要每次在渲染时都要使用一个参数时,这种方式比较有效,在一个地方就能够进行控制。 //首先提供一个service provider,在其中指明view composer:
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class ComposerServiceProvider extends ServiceProvider { /** * Register bindings in the container. * * @return void */
    public function boot() { // Using class based composers...
        view()->composer( 'profile', 'App\Http\ViewComposers\ProfileComposer' ); // Using Closure based composers...
        view()->composer('dashboard', function ($view) { //  }); } /** * Register the service provider. * * @return void */
    public function register() { //  } } //其次,创建一个文件夹App\Http\ViewComposers,保存composer类:
<?php namespace App\Http\ViewComposers; use Illuminate\View\View; use Illuminate\Users\Repository as UserRepository; class ProfileComposer { /** * The user repository implementation. * * @var UserRepository */
    protected $users; /** * Create a new profile composer. * * @param UserRepository $users * @return void */
    public function __construct(UserRepository $users) { // Dependencies automatically resolved by service container...
        $this->users = $users; } /** * Bind data to the view. * * @param View $view * @return void */
    public function compose(View $view)//该方法在每次profile视图被渲染时,都会调用
 { $view->with('count', $this->users->count()); } } //其余:绑定一个composer到多个视图上:
view()->composer( ['profile', 'dashboard'],
    'App\Http\ViewComposers\MyViewComposer' ); view()->composer('*', function ($view) { // }); //最后还提到了一个叫作View Creators的东西,不知道啥意思:View creators are very similar to view composers; however, they are fired immediately when the view is instantiated instead of waiting until the view is about to render.(view什么时候初始化,什么时候渲染?区别是什么) //To register a view creator, use the creator method:
 view()->creator('profile', 'App\Http\ViewCreators\ProfileCreator');

11.blade模板引擎

blade模板能够编译为原声php文件而且缓存起来,因此不会形成性能损失。

//layout模板文件
<!-- Stored in resources/views/layouts/master.blade.php -->

<html>
    <head>
        <title>App Name - @yield('title')</title>
    </head>
    <body> @section('sidebar') This is the master sidebar. @show <div class="container"> @yield('content') </div>
    </body>
</html>

//子视图模板文件:
<!-- Stored in resources/views/child.blade.php --> @extends('layouts.master') @section('title', 'Page Title') //注意作这个section的用法
 @section('sidebar')//这里可使得父模板运用子模板的section,即在父模板的基础上扩展父模板的section
 @parent <p>This is appended to the master sidebar.</p> @endsection @section('content') <p>This is my body content.</p> @endsection //变量显示方面:{{ }}能够阻止XSS攻击 //某些js框架使用{{ }}号,向前面添加@号能够告诉blade不要解析这块内容
<h1>Laravel</h1> Hello, @{{ name }}.

//某些变量可能不存在或者没定义,使用下列方式
{{ $name or 'Default' }} //非转义输出
Hello, {!! $name !!} //注释:
{{-- This comment will not be present in the rendered HTML --}} //栈功能:
@push('scripts') <script src="/example.js"></script> @endpush //调用栈:
<head>
    <!-- Head Contents --> @stack('scripts') </head>

//service inject:
@inject('metrics', 'App\Services\MetricsService') <div> Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>

//移除view缓存
php artisan view:clear //【高级】还能够自定义blade中使用的指令,好比定义一个@datetime($var):
<?php namespace App\Providers; use Blade; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Perform post-registration booting of services. * * @return void */
    public function boot() { Blade::directive('datetime', function($expression) { return "<?php echo with{$expression}->format('m/d/Y H:i'); ?>"; }); //Laravel's with helper function was used in this directive. The with helper simply returns the object / value it is given, allowing for convenient method chaining.
 } /** * Register bindings in the container. * * @return void */
    public function register() { //  } }
相关文章
相关标签/搜索