php 用来处理动态性的网页的, laravelphp 的工具集,扩展了功能。

特点: 所有的 URL 访问必须先定义路由规则。

基础功能

配置

  • 配置文件都在 /config 目录里面

  • 目录权限 /storage/bootstrap/cache 目录都要可写

  • APP_KEY 设置随机秘钥 php artisan key: generate

  • 运行 php artisan serve 或者 apache (推荐)

  • app.php 配置

    • app.php aliases 段可定义别名

    • 'debug' => env('APP_DEBUG', true) 调试模式

    • 'log' => env('APP_LOG', 'daily') 日志记录 ingle, daily, syslog, errorlog

    • 'log_level' => env('APP_LOG_LEVEL', 'error') 错误等级 debug, info, notice, warning, error, critical, alert, emergency

手工路由

别的框架都不用你管路由,这个 laravel 却要你手动配置路由。

/routes/web.php 路由配置文件

基本结构
1
2
3
4
5
6
  Route::get($url, $callback);
  Route::post($url, $callback);
  Route::put($url, $callback);
  Route::patch($url, $callback);
  Route::delete($url, $callback);
  Route::option($url, $callback);
多个请求
1
2
  Route::get(['get', post], '/', function () { });
  Route::any('/', function () { });
路由参数
  • 必选参数 Route::get('/test/{id}', function ($id) { });

  • 可选参数 Route::get('/test/{id?}', function ($id) { });

命名路由
  • name(NAME) 给路由定义起个名字,在以后的程序中可以用 route(NAME) 的形式调用

路由群组
  • Route::group 把路由条目归归类,好区分

控制器

路由做好了路由的事情了,你不会把给用户的逻辑响应的事情也交给它做吧,它估计要累死, 在 laravel 中交给 控制器 来做这件事。

控制器把要做的事分门别类放到单独的文件中,所以一个 web 站点有那么多的功能,而且容易整理。

  • app/Http/Controllers 控制器定义目录

控制器结构
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  <?php

  namespace App\Http\Controllers;

  use Illuminate\Http\Request;

  class UserController extends Controller
  {
      public function __construct() {}
  }
  • 控制器文件名为驼峰结构 如:UserController

  • 控制器路由方法 Route::get('路由表达式', '控制器类名@方法');

单一行为控制器

如果类中只有一个方法,就可以用 __invoke 定义一个单一行为。

1
2
  // 路由中不用指定类名
  Route::get('user/{id}', 'ShowProfile');
中间件

连续的操作可以用中间件表示,一般定义在 __construct 里面。

1
2
3
4
5
6
  public function __construct()
  {
      $this->middleware('auth');
      $this->middleware('log')->only('index');
      $this->middleware('subscribed')->except('store');
  }
资源控制器

就是对图片那些东西,我们不想单独路由,就可以创建一个通用的路由

1
  php artisan make:controller PhotoController --resource

路由方式

1
2
3
4
5
6
7
8
  // 注册单个
  Route::resource('photos', 'PhotoController');

  // 注册多个
  Route::resources([
      'photos' => 'PhotoController',
      'posts' => 'PostController'
  ]);
Verb URI Action Route Name
GET /photos index photos.index
GET /photos/create create photos.create
POST /photos store photos.store
GET /photos/{photo} show photos.show
GET /photos/{photo}/edit edit photos.edit
PUT/PATCH /photos/{photo} update photos.update
DELETE /photos/{photo} destroy photos.destroy

获取 URL 参数

Input

使用 * Illuminate§upport\Facades\Input* 方法获取 url 参数

  • URL 结构 test1?id=232

  • Input::get()

  • Input::all()

  • Input::only([])

  • Input::except([]) 除了

  • Input::has() 是否存在

Request

跟 Input 用法一样

门面( Facades )

门面提供了静态方法,定义在 Illuminate§upport\Facades 中(在 laravel 内部) 。

对数据库操作

支持四个数据库 MySQL , PostgreSQL, SQLite, SQL Server

配置
  • config/database.php 配置文件

  • .env 环境变量配置文件

  • use DB; 使用 DB 类

对 SQLite 的配置
DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite
读写连接

对数据库的不同功能使用不同的配置

1
2
3
4
5
6
7
8
9
  'mysql' => [
      'read' => [
          'host' => ['192.168.1.1'],
      ],
      'write' => [
          'host' => ['196.168.1.2'],
      ],
      'sticky'    => true,
  ]...
sticky 选项

sticky 可用于允许立即读取在当前请求周期中写入数据库的记录,为了安全一般关闭。

使用多个连接
  • 通过连接方法 $users = DB::connection('foo')->select(…);

  • 通过底层 PDO $pdo = DB::connection()->getPdo();

原生操作
增删改查
  • 查(参数绑定) DB::select('select * from users where active = ?', [1]);

  • 查(命名绑定) $results = DB::select('select * from users where id = :id', ['id' => 1]);

  • 增 DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);

  • 改 $affected = DB::update('update users set votes = 100 where name = ?', ['John']);

  • 删 $deleted = DB::delete('delete from users');

  • 执行语句 DB::statement('drop table users');

数据库事务
1
2
3
4
5
  DB::transaction(function () {
      DB::table('users')->update(['votes' => 1]);

      DB::table('posts')->delete();
  });
处理死锁 (设定重新尝试的次数)
1
2
3
4
5
  DB::transaction(function () {
      DB::table('users')->update(['votes' => 1]);

      DB::table('posts')->delete();
  }, 5);
手动使用事务
1
2
3
4
5
  DB::beginTransaction();

  // 回滚
  DB::rollBack();
  DB::commit();
laravel 骚操作

thinkphp 一样的方式

DB::table(表名)->insert()->update()->delete()->get()->where()->orwhere()->
first()->value()->orderBy()->limit()->offset();

视图

视图就是你在浏览器看到的外观, laravel 基于 MVC 的设计方法,把它们概念化成视图 。关于外观所使用到的技术就不讲了,这里讲下 laravel 如何将外观技术与视图技术合起来的。

  • resources/views 视图存储目录

视图结构
1
2
3
4
5
6
7
  <!-- 文件名为 blade.php 后缀 -->
  <!-- View stored in resources/views/greeting.blade.php -->
  <html>
    <body>
      <h1>Hello, {{ $name }}</h1>
    </body>
  </html>

blade 结构可以识别 {{}} 语法

循环分支
@foreach ($expression as $key=>$value) 
循环体
 @endforeach
@if()
@elseif()
@endif
继承 (公共页)
@include()
@extends('')
@section(区块名称)
@endsection

调用

@yield('')
引入外部静态文件

原生(简单)

1
  <link rel="stylesheet" href="/css/app.css}" type="text/css" media="screen" />

asset() 处理网站目录

1
  <link rel="stylesheet" href="{{asset('css)}/app.css}" type="text/css" media="screen" />
连接视图

view 会去找 blade.php 后缀视图文件,找不到再找 'php' 后缀的

1
2
3
4
5
  Route::get('/', function () {
      return view('greeting', ['name' => 'James']);
  });
  // 视图在  admin目录下,用 ‘/’ 分割木兰也可以
  return view('admin.profile', $data);
视图是否存在
1
2
3
4
5
  use Illuminate\Support\Facades\View;

  if (View::exists('emails.customer')) {
      //
  }
第一个可用视图
1
  return view()->first(['custom.admin', 'admin'], $data);
与所有视图共享数据

使用 AppServiceProvider 服务提供者

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;

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()
{
   //
}
}
视图作曲家

artisan

  • 显示路由列表 php artisan route:list

  • 创建控制器 php artisan make:controller [ [ 目录名/ ]控制器名 + Controller ]

    • –resource 资源

调试

格式化输出

dump+die 的作用

1
  dd();

安全

CSRF (跨站请求伪造攻击)

表单数据提交 的验证 (session)

获取 csrf_token

1
  csrf_token();

表单中推介使用,因为默认开启了

1
2
3
4
  <input type="hidden" name="_token" value="{{csrf_token()}}" />

  <!-- 简化 -->
  {{csrf_field()}}

排除路由 app/Http/Middleware/VerifyCsrfToken.php 白名单

单个

1
2
3
  protected $except = [
     '/home/test/test7',
  ];

全部

1
2
3
protected $except = [
   '*',
];

教程

新建路由和控制器

laravel 的路由配置文件是:LaravelStudy/routes/web.php

我们重新定义路由:

1
2
3
Route::get('/', 'SiteController@index');
Route::get('login', 'SiteController@login');
Route::get('register', 'SiteController@register');

路由指向的控制器是 SiteController,需要生成控制器

终端执行:

☁ laravelStudy [master] ⚡ php artisan make:controller SiteController Controller created successfully. laravel 自动为我们生成了控制器:LaravelStudy/app/Http/Controllers/SiteController.php

渲染页面

在 LaravelStudy/app/Http/Controllers/SiteController.php 添加以下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public function index()
{
    return view('site/index');
}

public function login()
{
    return view('site/login');
}

public function register()
{
    return view('site/register');
}

创建相应的视图文件

LaravelStudy/resources/views/site/index.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    我是主页
</body>
</html>

LaravelStudy/resources/views/site/login.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    登录页
</body>
</html>

LaravelStudy/resources/views/site/register.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    注册页
</body>
</html>

这三个视图的代码有大量的重复,我们可以定义一个公共的模板文件,再让视图文件共享模板

定义公共模板文件

新建文件:LaravelStudy/resources/views/layouts/default.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
    <title>@yield('title', 'Laravel 实战')--跟章鱼喵学 laravel</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.1.0/css/bootstrap.min.css">
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/popper.js/1.12.5/umd/popper.min.js"></script>
    <script src="https://cdn.bootcss.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="container-fluid">
        @yield('content')
    </div>
</body>
</html>

使用 bootstrap4 作为前端框架

修改原来的视图文件:

1
2
3
4
  LaravelStudy/resources/views/site/index.blade.php
  @extends('layouts.default')
  @section('content')
  @stop

LaravelStudy/resources/views/site/login.blade.php

1
2
3
4
5
  @extends('layouts.default')
      @section('title', '登录')
      @section('content')
      <h3>登录页<h3>
  @stop

LaravelStudy/resources/views/site/index.blade.php

1
2
3
  @extends('layouts.default')
      @section('content')
      @stop

LaravelStudy/resources/views/site/login.blade.php

1
2
3
  @extends('layouts.default')
      @section('title', '登录')
      @section('content')

LaravelStudy/resources/views/site/register.blade.php

1
2
3
4
5
  @extends('layouts.default')
  @section('title', '注册')
  @section('content')
      <h3>注册页<h3>
  @stop

公共头部和底部

网站需要有公共的头部和底部,同样,作为公共的模板文件,依然是放在 layouts 目录下

新建头部导航:LaravelStudy/resources/views/layouts/_header.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
    <h3 class="text-light text-center col-md-10">laravel 教程实战</h3>
    <ul class="navbar-nav col-md-2">
        <li class="nav-item">
            <!--使用命名路由-->
            <a class="nav-link text-info" href="{{ route('login') }}">登录</a>
        </li>
        <li class="nav-item">
            <a class="nav-link text-light" href="{{ route('register') }}">注册</a>
        </li>
    </ul>
</nav>

头部导航中的 a 标签链接使用了命名路由,可以理解为给路由起了个别名,这个便于扩展, 比如,现在登录业务对应的是 SiteController@login,以后可能随着业务的改变,要改为 UserControoler@login,如果是以硬编码的形式写路由,要修改就很麻烦。

使用命名路由只需要改路由配置文件即可。

LaravelStudy/routes/web.php

1
2
Route::get('login', 'SiteController@login')->name('login'); // 命名路由
Route::get('register', 'SiteController@register')->name('register');

新建底部导航:LaravelStudy/resources/views/layouts/_footer.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<nav class="navbar navbar-expand-sm bg-light navbar-light fixed-bottom">
    <a class="navbar-brand" href="https://www.jianshu.com/u/f9338eda7dda" target="_blank">
        <img src="https://upload.jianshu.io/users/upload_avatars/1864602/07f1bc01-66e5-4ff4-b683-79681856dad3.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/40/h/40" alt="">
    </a>
    <ul class="navbar-nav">
        <li class="nav-item">
            来简书跟着章鱼喵一起学 laravel...
        </li>
    </ul>
</nav>

由于头部和底部是局部视图,以下划线作为开头命名,便于区分

在公共模板中引入头部和底部:

LaravelStudy/resources/views/layouts/default.blade.php

1
2
3
4
5
@include('layouts._header')
<div class="container-fluid">
    @yield('content')
    @include('layouts._footer')
</div>