Laravel 笔记 持续更新

安装

1
composer create-project --prefer-dist laravel/laravel blog 5.5.*

路由

基本形式 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Route::get('/','控制器@方法');
Route::get('/post','\App\Http\Controllers\PostController@index');
/*
对应html代码
<form action = "/post" methot = "GET">
</form>
*/
Route::put('/post','\App\Http\Controllers\PostController@index');
/*
对应html代码
<form action = "/post" methot = "POST">
{{method_filed("PUT)}}
</form>
*/
Route::any('/post','\App\Http\Controllers\PostController@index');//支持所有提交方法
Route::match(('POST','GET'),'/post','\App\Http\Controllers\PostController@index');//支持POST和GET方法
1
2
Route::get('/posts',['as'=>'posts','uses'=>'PostController@index']);
// posts路由,as是给这个路由重命名为posts,这样就可以通过route('posts',parameter)来访问这个路由,parameter是路由中的参数,可以是数组,uses对应的是默认控制器方法

路由参数:

1
2
3
4
Route::get('/post{id}','\App\Http\Controllers\PostController@index');//传进来参数id
function index($id){
//从对应的控制器的方法里接收
};

路由分组:

1
2
3
4
5
Route::group(['prefix'=>'post'],function(){
Route::get('/','\App\Http\Controllers\PostController@index');//对应'/post'
Route::post('/','\App\Http\Controllers\PostController@index');//同上
Route::post('/creat','\App\Http\Controllers\PostController@index');//对应'/post/create'
})
  • url()

    url 辅助函数可用于为应用生成任意 URL,并且生成的 URL 会自动使用当前请求的 scheme(HTTP or HTTPS) 和 host 属性

  • asset

    asset()方法用于引入 CSS/JavaScript/images 等文件,文件必须存放在public文件目录下。

渲染

基本与CI相似

1
2
3
4
5
public function index($value='')
{
return view("post/index",$data);//渲染view/post/index.blade.php文件,$data为数组
//或者 return view("post/index")->with(['post'=>$post]);
}

blade模板

if语句

1
2
3
4
5
6
7
@if ($bool == false)
<h2 class="blog-post-title">{{$bool}}</h2>
@elseif
···
@else
···
@endif

循环

1
2
3
@for ($i=0;$i<10;$i++)
<h2 class="blog-post-title">{{$bool}}</h2>
@endfor
1
2
3
4
@foreach ($users as $k => $v)
<p>此用户为 {{$k.'--'.$v}}</p>
//$loop->iteration 从1开始循环计数 $loop->index 从0开始计数
@endforeach
1
2
3
@while (true)
<p>我永远都在跑循环。</p>
@endwhile

引用与调用

将相同的部分全部写出来,将不同的部分用@yield('content')代替,然后放在view/layout/main.blade.php下,引用的时候:

1
2
3
4
@extends('layout.main')
@section('content')
// code....
@endsection

渲染为html {!! $content !!}

migration

  • 作用:记录对数据库的操作,实现对数据库的迁移

  • 在命令行输入php artisan make:migration create_posts_table +(名字,一般命名为creat_表名_table)

  • 用migration建表:在migration的up(创建函数)里写

    1
    2
    3
    4
    5
    6
    7
    Schema::create('posts', function (Blueprint $table) {
    $table->increments('id');//自增id
    $table->string('title',100)->default('');//vachar类型的标题,最大长度100
    $table->text('content');//text类型的content
    $table->integer('user_id')->default(0);
    $table->timestamps();//自动创建create_at update_at字段
    });// 如果想更新,把create换成table

    设置字段的默认长度在\App\Providers\AppServiceProvider.php的boot里面设置

    1
    2
    3
    4
    use Illuminate\Support\Facades\Schema;
    ···
    //默认mb4string 类型长度
    Schema::defaultStringLength(191);

    然后运行 php artisan migrate就会自动建表了

  • 回滚

    1
    Schema::dropIfExists('posts');

文章模型

模型使用ORM来创建模型,使用class来表示一个表,每一个表都有一个类来来提供给上层使用,可以通过对模型的查询,增加,删除操作,来对数据表操作,这样就将数据表抽象化

创建模型

在命令行输入以下代码:php artisan make:model Post默认对应表posts

1
2
3
4
5
class Post extends Model
{
//默认对应的表=>posts
//指定表名 protected $table = "posts2";
}

默认行为

Eloquent 默认每张表的主键名为id,你可以在模型类中定义一个$primaryKey属性来覆盖该约定。

此外,Eloquent默认主键字段是自增的整型数据,这意味着主键将会被自动转化为int类型,如果你想要使用非自增或非数字类型主键,必须在对应模型中设置$incrementing属性为false

默认情况下,Eloquent 期望created_atupdated_at已经存在于数据表中,如果你不想要这些 Laravel 自动管理的列,在模型类中设置$timestamps属性为false

在控制器使用模型

$post = \App\Post;由于模型经常使用,可以在控制器上方加use \App\Post;在方法里面可以直接写。返回的是collection对象

1
$post = Post::orderBy('create_at','desc')->get();//获取posts表单额所有数据,并按照时间降序排列   

模型关联

belongsTo

1
2
3
4
5
6
7
class Post extends Model
{
public function user()
{
return $this->belongsTo('App\user','user_id','id');
}
}

此方法会从关联模型(App\user)中,查询此模型(Post)的外键(user_id)为关联模型的主键(id)的数据

使用: Post::find($id)->get()[0]->name用来获取id为$id的文章的user的姓名

hasMany

1
2
3
4
5
6
class Member extends Model
{
public function blogs(){
return $this->hasMany('App\Blog',"member_id","id");
}
}

此方法会从关联模型(App\Blog)中,查找关联模型的外键(member_id)为此模型(Member)的主键(id)的数据

belongsTomany

1
2
3
4
5
6
7
class Member extends Model
{
public function projects()
{
return $this->belongsToMany('App\Project','member_project','member_id','project_id');
}
}

此方法会从关联模型(App\Project)cha数据,条件为:先在表(member_project)找到此模型(member)主键为(member_id)数据,找到对应的project_id,然后在project表中找主键为project的数据

数据填充

database/factories里写

1
2
3
4
5
6
$factory->define(App\Post::class, function (Faker\Generator $faker) {
return [
'title' => $faker->sentence(6),//6个单词
'content' => $faker->paragraph(10),//10句话
];
});

然后再命令框运行 php artisan tinker ->factory(App\Post::class,20)->create();

简单分页

控制器里写

1
2
$post = Post::orderBy('create_at','desc')->paginate(10);//每页显示的条数
return view("post/index",array('posts'=>$posts,));

blade里写

1
{{$post->links()}}

字符截断

blade页面写

1
{{str_limit($post->content,100,'...')}}//显示100字符,超出部分显示...

文章的增删改查

文章详情页

路由时用的是模型绑定:

1
Route::get('/posts/{post}','\App\Http\Controllers\PostController@show')->where(['post' => '[0-9]+']);//绑定post模型

控制器里面写

1
2
3
4
5
public function show(Post $post)
{
$data['post'] = $post;
return view('post/show',$data);
}

创建文章

  • post提交时,必须使用一个函数{{csrf_field()}}

  • 接收参数request()->all();或者request(['title','content']);特定字段名

  • 使用post的crate方法时,需要在post模型里面添加两个属性

    1
    2
    protected $guarded = [];//不可以注入的字段
    protected $fillable = ['title','content'];//可以注入的数据字段
  • 利用模型存数据库

    Post::create([数组]);//此方法会同时插入created_at 和 upadated_at字段

  • 表单验证

    1
    2
    3
    4
    5
    6
    $this->validate(request(), [
    'title' => 'required|string|max:100|min:5', //title的验证规则:必填,字符串,长度大于5小于100
    'content' => 'required|string|min:10',
    ],[
    'title.min' =>'文章标题过短',//自定义错误提示
    ]);

    返回错误时会可以在前端blade模板中直接写

    1
    2
    3
    4
    5
    6
    7
    @if(count($errors)>0)
    <div class="alert-danger alert">
    @foreach($errors->all() as $error)
    <li>{{$error}}</li>
    @endforeach
    </div>
    @endif

    如果验证失败后想进行什么操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    use Validator;
    ·
    ·
    ·
    $validator = Validator::make($request->all(),[
    'title' => 'required|string|max:100|min:5', //title的验证规则:必填,字符串,长度大于5小于100
    'content' => 'required|string|min:10',
    ],[
    'title.min' =>'文章标题过短',//自定义错误提示
    ]);

    //如果验证失败
    if ($validator->fails()) {
    $request->session()->flash('tab', '2'); //闪存信息到session
    return redirect()
    ->back()
    ->withErrors($validator);
    }

    *如果显示错误想变成中文,可以resource/lang/下新建一个文件夹/zh,将en下的文件复制到这里面,然后参考linkdesu写的复制下来,覆盖到validation。然后在config/app.php里面将locale改为zh

    • laravel的表单验证自带重复确认验证confirmed:

      具体用法为:验证字段必须有一个匹配字段foo_confirmation,例如,如果验证字段是password,必须输入一个与之匹配的password_confirmation字段

    • unique:table,column,except,idColumn

      此验证规则会在table表(除去idColumn/主键为except的项)中检查column字段中有没有与之重复的值。

      1
      'email' => 'unique:users,email_address,'.$user->id.',user_id',

修改文章

1
2
3
4
5
6
7
public function update(Post $post)
{
$post->title = request('title');
$post->content = request('content');
$post->save();
return redirect("posts/$post->id");
}

删除文章

1
2
3
4
5
public function delete(Post $post)
{
post->delete();
return view('');
}

Auth门脸类

配置流程

  • 将所要应用Auth的模型(比如User这个model)继承 Authenticate

  • 具体在config/auth里面修改

  • 方法

    • 登录

      1
      2
      3
      4
      if(Auth::attempt(['email'=>$email,'password'=>$password],$remember))
      {
      //此数组会和对应模型的数据库进行匹配,匹配正确会进入到此分支语句中
      }
    • 登出

      1
      Auth::logout();
    • 获取当前已通过认证的用户

      1
      $user = Auth::user()
    • 获取当前已认证用户的id

      1
      $id = Auth::id();

Policy策略类(用于权限验证)

创建

1
php artisan make:policy Postpolicy

引入模型,添加方法

1
2
3
4
5
6
7
8
9
use App\Post;  //文章
use App\User; //用户

//修改权限
//判断用户的id和文章的id是否相等,相等返回true,不相等返回false
public function update(User $user,Post $post)
{
return $user->id == $post->user_id;
}

将策略类和模型关联起来

app/Policies/AuthServiceProvideer.php

1
2
3
4
protected $policies = [
//'App\Model' => 'App\Policies\ModelPolicy',
'App\Post' => 'App\Policies\PostPolicy',
];

策略判断

  • 在要进行权限验证的控制器的方法里写

    1
    $this->authorize('update',$post);

    此时会获取登录的用户Auth::user()来判断是否有权限,如果通过权限验证会继续,不通过会返回错误页面

    也可以这样:

    1
    2
    3
    if($user->can('update',$post)){
    ***************
    }

    如果有权限更新,会继续进行,否则,会报错

  • 在要进行权限验证的blade模板里面写

    1
    2
    3
    @can('update',$post)
    *****************
    @endcan

    此时会获取登录的用户Auth::user()来判断是否有权限

辅助类

文件上传

建立软连接

首先建立 storage/app/public -> public/storage 的符号软连接:

1
php artisan storage:link

存储文件

在存储文件时,就可以写:

1
2
3
//$path = $request->file('image')->storage('文件夹名','存储磁盘');
//若希望文件可以被访问,需要放在public磁盘下
$path = $request->file('image')->storage('image','public');

具体配置在config/filesystem.php里面修改

访问上传的图片

1
<img src="{{asset('storage')}}/{{$item->img}}" alt="">

flash—session

有时候你仅想在下一个请求之前在 Session 中存入数据,你可以使用 flash 方法。使用这个方法保存在 session 中的数据,只会保留到下个 HTTP 请求到来之前,然后就会被删除。闪存数据主要用于短期的状态消息:

1
$request->session()->flash('success',"更新商品【{$request->name}】成功!");

在前端页面可以这样写(bootstrap)

1
2
3
4
5
6
@if(session('success'))
<div class="alert alert-success alert-dismissable">
<button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
{{session('success')}}
</div>
@endif

其他

修改时区

在\App\config\app.php 里修改 timezone =>'Aisa/Shanghai'

修改时间格式:

$post->created_at->toFormattedDateString()

评论