• 二 笔记片段


    路由:

             会员列表页面:/admin/member/index                           get类型

             会员的添加页面:/admin/member/add                          any类型

             异步头像上传地址:/admin/uploader/webuploader                     post类型

             异步四级联动数据获取:/admin/member/getAreaById             get类型

    添加路由

    Route::group(['prefix'=>'admin'],function () {
        Route::get('public/login',  'Admin\PublicController@login')->name('login');
        Route::post('public/check', 'Admin\PublicController@check');
        Route::get('public/logout', 'Admin\PublicController@logout');
    });
    Route::group(['prefix'=>'admin','middleware'=>['auth:admin','checkrbac']],function () {
        Route::get('index/index','Admin\IndexController@index');
        Route::get('index/welcome','Admin\IndexController@welcome');
        Route::get('manager/index','Admin\Managercontroller@index');
        Route::get('auth/index','Admin\AuthController@index');
        Route::any('auth/add','Admin\AuthController@add');
        Route::get('role/index','Admin\RoleController@index');
        Route::any('role/assign','Admin\RoleController@assign');
        Route::any('member/index','Admin\MemberController@index');
        Route::any('member/add','Admin\MemberController@add');
        Route::any('member/getAreaById','Admin\MemberController@getAreaById');
        Route::any('uploader/webuploader','Admin\UploaderController@webuploader');
    
    });

    控制器文件:

    添加控制器   php artisan make:controller Admin/MemberController

    模型文件:

    创建命令: php artisan make:model Admin/Member

    定义模型规范

    protected $table = 'member'; //绑定模型关联的表 member

    ①创建index方法,获取数据,展示视图

    public function index(){
            $data = Member::get();
            return view('admin.member.index',compact('data'));
        }

    ②创建需要的视图文件  目录 resources\views\admin\member

    文件名 index.blade.php

    模板调用

     @foreach($data as $val)
                <tr class="text-c">
                    <td><input type="checkbox" value="1" name=""></td>
                    <td>{{$val->id}}</td>
                    <td>{{$val->username}}</td>
                    <td><img src="{{$val->avatar}}" width="60" /></td>
                    <td>@if($val->gender=='1')男@elseif($val->gender=='2')女@else保密@endif</td>
                    <td>{{$val->mobile}}</td>
                    <td >{{$val->email}}</td>
                    <td>{{$val->created_at}}</td>
                    <td class="td-status">
                        @if($val->status=='1')
                        <span class="label label-danger radius">已停用</span></td>
                    @else
                        <span class="label label-success radius">已启用</span></td>
                    @endif
                    <td class="td-status">@if($val->type==1)学生@else 老师 @endif</th>
                    <td class="td-manage"><a style="text-decoration:none" onClick="member_stop(this,'10001')" href="javascript:;" title="停用"><i class="Hui-iconfont">&#xe631;</i></a> <a title="编辑" href="javascript:;" onclick="member_edit('编辑','member-add.html','4','','510')" class="ml-5" style="text-decoration:none"><i class="Hui-iconfont">&#xe6df;</i></a> <a style="text-decoration:none" class="ml-5" onClick="change_password('修改密码','change-password.html','10001','600','270')" href="javascript:;" title="修改密码"><i class="Hui-iconfont">&#xe63f;</i></a> <a title="删除" href="javascript:;" onclick="member_del(this,'1')" class="ml-5" style="text-decoration:none"><i class="Hui-iconfont">&#xe6e2;</i></a></td>
                </tr>
                @endforeach

     调用其他数据表内容

    $country=DB::table('area')->where('pid',0)->get();

    post数据
     if(Input::method() =='POST'){
                $result = Member::insert([
                    'username'        =>        Input::get('username'),
                    'password'        =>        bcrypt('password'),
                    'gender'        =>        Input::get('gender'),
                    'mobile'        =>        Input::get('mobile'),
                    'email'            =>        Input::get('email'),
                    'avatar'        =>        '/statics/avatar.jpg',
                    'country_id'    =>        Input::get('country_id'),
                    'province_id'    =>        Input::get('province_id'),
                    'city_id'        =>        Input::get('city_id'),
                    'county_id'        =>        Input::get('county_id'),
                    'type'            =>        Input::get('type'),
                    'status'        =>        Input::get('status'),
                    'created_at'    =>        date('Y-m-d H:i:s')
                ]);
                //返回输出
                return $result ? '1' : '0';
     
    知识点
    {{ route('users.edit', Auth::id()) }} //模型文件调用资源路由示范  /users/1/edit
    {{ route('users.show', Auth::id()) }} //模型文件调用资源路由示范 /users/1

    路由文件
    Route::resource('users', 'UsersController', ['only' => ['show', 'update', 'edit']]);

    
    

     数据表中添加单独的字段

    php artisan make:migration add_avatar_and_introduction_to_users_table --table=users
    public function up()
     {
     Schema::table('users', function (Blueprint $table) {
     $table->string('avatar')->nullable();
     $table->string('introduction')->nullable();
     });
     }
    

     php artisan migrate

     知识点

    public function show(User $user)
     {
     return view('users.show', compact('user'));
     }

    User 是User模型

     Laravel 会自动解析定义在控制器方法(变量名匹配路由片段)中的 Eloquent 模型类型声明。在上面代码中,由于 show() 方法传参时声明了类型 —— Eloquent 模型 User ,对应的变量名 $user 会匹配路由片段中的 {user} ,这样,Laravel 会自动注入与请求 URI 中传入的 ID 对应的用户模型实例。 此功能称为 ,是『约定优于配置』设计范式的体现,同时满足以下两种情况,此功能即会自动启 用:

    1). 路由声明时必须使用 Eloquent 模型的单数小写格式来作为 路由片段参数,User 对应 {user} :

    Route::get('/users/{user}', 'UsersController@show')->name('users.show');
    

     上面路由部分讲过,在使用资源路由 Route::resource('users', 'UsersController'); 时,默认已经包含了上面的声 明。

    2). 控制器方法传参中必须包含对应的 Eloquent 模型类型 提示,并且是有序的:

    public function show(User $user)
    {
     return view('users.show', compact('user'));
    }

    当请求 http://larabbs.test/users/1 并且满足以上两个条件时,Laravel 将会自动查找 ID 为 1 的用户并赋值到变量 $user 中,如果数据库中找不到对应的模型实例,会自动生成 HTTP 404 响应,例如此刻我们只注册了 Summer 和 Monkey 用 户,数据库里只有两条数据,当我们访问 http://larabbs.test/users/3 ID 为 3 的用户时:

    则会返回404

    3. 继续看 show() 方法里的代码:

    return view('users.show', compact('user'));

    我们将用户对象变量 $user 通过 方法转化为一个关联数组,并作为第二个参数传递给 view 方法,将 变量数据传递到视图中。 show 方法添加完成之后,在视图中,我们即可直接使用 $user 变量来获取 view 方法传递给视图的用户数据。

    重点
     php artisan make:request UserRequest
    
    
    <?php
    namespace App\Http\Requests;
    use Illuminate\Foundation\Http\FormRequest;
    class UserRequest extends FormRequest
    {
     public function authorize()
     {
     return true;
     }
     public function rules()
     {
     return [
     //
     ];
     }
    }
    

    表单请求验证(FormRequest)的工作机制,是利用 Laravel 提供的依赖注入功能,在控制器方法,如上面我们的 update() 方法声明中,传参 UserRequest。这将触发表单请求类的自动验证机制,验证发生在 UserRequest 中,并使 用此文件中方法 rules() 定制的规则,只有当验证通过时,才会执行 控制器 update() 方法中的代码。否则抛出异 常,并重定向至上一个页面,附带验证失败的信息。 authorize() 方法是表单验证自带的另一个功能 —— 权限验证,本课程中我们不会使用此功能,关于用户授权,我们 将会在后面章节中使用更具扩展性的方案,此处我们 return true; ,意味所有权限都通过即可。 接下来我们需要定制 rules() 方法,如下:

    app/Http/Requests/UserRequest.php
    <?php
    namespace App\Http\Requests;
    use Illuminate\Foundation\Http\FormRequest;
    use Auth;
    class UserRequest extends FormRequest
    {
     public function authorize()
     {
     return true;
     }
     public function rules()
     {
     return [
     'name' => 'required|between:3,25|regex:/^[A-Za-z0-9\-\_]+$/|unique:users,name,' . Auth::id(),
     'email' => 'required|email',
     'introduction' => 'max:80',
     ];
     }
    }

     /5、头像上传

    <div class="form-group mb-4">
     <label for="" class="avatar-label">用户头像</label>
     <input type="file" name="avatar" class="form-control-file">
     @if($user->avatar)
     <br>
     <img class="thumbnail img-responsive" src="{{ $user->avatar }}" width="200" />
     @endif
     </div>

    在 Laravel 中,我们可直接通过请求对象 (Request) 来获取用户上传的文件,如以下两种方法:

    $file = $request->file('avatar');
    // 第二种方法,可读性更高
    $file = $request->avatar;
    在控制器中 测试
    dd($request->avatar);

    打印出来是图片文件名称的字符串,与我们的预期不符,图片上传后通过 $request 取到的应是图片对象。 经过一番仔细检查后,发现是因为我们忘记为表单添加 enctype="multipart/form-data" 声明了。请记住,在图片或 者文件上传时,为表单添加此句声明是必须的。

    6、 存储用户上传图片

    我们可以将『图片上传』核心操作做成一个工具类:

    app/Handlers/ImageUploadHandler.php

    <?php
    namespace App\Handlers;
    class ImageUploadHandler
    {
     // 只允许以下后缀名的图片文件上传
     protected $allowed_ext = ["png", "jpg", "gif", 'jpeg'];
     public function save($file, $folder, $file_prefix)
     {
     // 构建存储的文件夹规则,值如:uploads/images/avatars/201709/21/
     // 文件夹切割能让查找效率更高。
     $folder_name = "uploads/images/$folder/" . date("Ym/d", time());
     // 文件具体存储的物理路径,`public_path()` 获取的是 `public` 文件夹的物理路径。
     // 值如:/home/vagrant/Code/larabbs/public/uploads/images/avatars/201709/21/
     $upload_path = public_path() . '/' . $folder_name;
     // 获取文件的后缀名,因图片从剪贴板里黏贴时后缀名为空,所以此处确保后缀一直存在
     $extension = strtolower($file->getClientOriginalExtension()) ?: 'png';
     // 拼接文件名,加前缀是为了增加辨析度,前缀可以是相关数据模型的 ID
     // 值如:1_1493521050_7BVc9v9ujP.png
     $filename = $file_prefix . '_' . time() . '_' . str_random(10) . '.' . $extension;
     // 如果上传的不是图片将终止操作
     if ( ! in_array($extension, $this->allowed_ext)) {
     return false;
     }
    $file->move($upload_path, $filename);
    return [
    'path' => config('app.url') . "/$folder_name/$filename"
    ];
    }
    }

    我们将使用 app/Handlers 文件夹来存放本项目的工具类,『工具类(utility class)』是指一些跟业务逻辑相关性不强 的类, Handlers 意为 处理器 ,ImageUploadHandler 意为图片上传处理器,简单易懂。 接下来我们需要在 UsersController 里调用(注意顶部 use 引入):

    app/Http/Controllers/UsersController.php

     
    use App\Handlers\ImageUploadHandler;
     
    public function update(UserRequest $request, ImageUploadHandler $uploader, User $user){
            $data = $request->all();
            //dd($data);
            if($request->avatar){
                $result = $uploader->save($request->avatar, 'avatars', $user->id);
                if($result){
                    $data['avatar'] = $result['path'];
                }else{
                    //上传有错误  withErrors可以携带回错误信
                    return back()->withErrors(['上传图片格式只支持png, jpg, gif, jpeg这四种格式']);
                }
            }
            $user->update($data);
            return redirect()->route('users.show', $user->id)->with('success', '个人资料更新成功');
        }
    
    
    

    1. 因为我们使用了命名空间,所以需要在顶部加载 use App\Handlers\ImageUploadHandler; ; 2. $data = $request->all(); 赋值 $data 变量,以便对更新数据的操作; 3. 以下代码处理了图片上传的逻辑,注意 if ($result) 的判断是因为 ImageUploadHandler 对文件后缀名做 了限定,不允许的情况下将返回 falseif ($request->avatar) { $result = $uploader->save($request->avatar, 'avatars', $user->id); if ($result) { $data['avatar'] = $result['path']; } }

     7、 图片验证

    app/Http/Requests/UserRequest.php

    public function rules()
     {
     return [
     'name' => 'required|between:3,25|regex:/^[A-Za-z0-9\-\_]+$/|unique:users,name,' . Auth::id(),
     'email' => 'required|email',
     'introduction' => 'max:80',
     'avatar' => 'mimes:jpeg,bmp,png,gif|dimensions:min_width=208,min_height=208',
     ];
     }
    public function messages()
     {
     return [
     'avatar.mimes' =>'头像必须是 jpeg, bmp, png, gif 格式的图片',
     'avatar.dimensions' => '图片的清晰度不够,宽和高需要 208px 以上',
     'name.unique' => '用户名已被占用,请重新填写',
     'name.regex' => '用户名只支持英文、数字、横杆和下划线。',
     'name.between' => '用户名必须介于 3 - 25 个字符之间。',
     'name.required' => '用户名不能为空。',
     ];
     }

    1. rules() 方法中新增了图片比例验证规则 ,仅允许上传宽和高都大于 208px 的图片;

    2. messages() 方法中新增了头像出错时的提示信息。

     8、裁剪图片

    1、

     composer require intervention/image

    2、配置信息

    php artisan vendor:publish --provider=Intervention\Image\ImageServiceProviderLaravelRecent

    3. 开始裁剪

    我们将裁切的逻辑写在 ImageUploadHandler 中,请将以下代码替换: app/Handlers/ImageUploadHandler.php

    <?php
    namespace App\Handlers;
    use Image;
    class ImageUploadHandler
    {
     protected $allowed_ext = ["png", "jpg", "gif", 'jpeg'];
     public function save($file, $folder, $file_prefix, $max_width = false)
     {
     // 构建存储的文件夹规则,值如:uploads/images/avatars/201709/21/
     // 文件夹切割能让查找效率更高。
     $folder_name = "uploads/images/$folder/" . date("Ym/d", time());
     // 文件具体存储的物理路径,`public_path()` 获取的是 `public` 文件夹的物理路径。
     // 值如:/home/vagrant/Code/larabbs/public/uploads/images/avatars/201709/21/
     $upload_path = public_path() . '/' . $folder_name;
     // 获取文件的后缀名,因图片从剪贴板里黏贴时后缀名为空,所以此处确保后缀一直存在
     $extension = strtolower($file->getClientOriginalExtension()) ?: 'png';
     // 拼接文件名,加前缀是为了增加辨析度,前缀可以是相关数据模型的 ID
     // 值如:1_1493521050_7BVc9v9ujP.png
     $filename = $file_prefix . '_' . time() . '_' . str_random(10) . '.' . $extension;
     // 如果上传的不是图片将终止操作
     if ( ! in_array($extension, $this->allowed_ext)) {
     return false;
     }
     // 将图片移动到我们的目标存储路径中
     $file->move($upload_path, $filename);
     // 如果限制了图片宽度,就进行裁剪
     if ($max_width && $extension != 'gif') {
     // 此类中封装的函数,用于裁剪图片
     $this->reduceSize($upload_path . '/' . $filename, $max_width);
     }
     return [
     'path' => config('app.url') . "/$folder_name/$filename"
     ];
     }
     public function reduceSize($file_path, $max_width)
     {
     // 先实例化,传参是文件的磁盘物理路径
     $image = Image::make($file_path);
     // 进行大小调整的操作
     $image->resize($max_width, null, function ($constraint) {
     // 设定宽度是 $max_width,高度等比例双方缩放
     $constraint->aspectRatio();
     // 防止裁图时图片尺寸变大
     $constraint->upsize();
     });
     // 对图片修改后进行保存
     $image->save();
     }
    }

     此次新增 reduceSize() 方法,以及此方法的调用。

    以上的 save() 方法中,我们新增了 $max_width 参数,用来指定最大图片宽度,我们修改 UsersController 的 update() 方法中的调用,修改为:

    $result = $uploader->save($request->avatar, 'avatars', $user->id, 416);

    9 授权访问

    存在两个问题

    1、未登录用户可以访问 edit 和 update 动作

    2、 登录用户可以更新其它用户的个人信息,登录 Summer 用户然后访问 Monkey 用户的编辑资料页面

    限制游客访问

    我们使用 Laravel 提供身份验证(Auth)中间件来过滤未登录用户的 edit , update 动作:

    app/Http/Controllers/UsersController.php

    public function __construct()
     {
     $this->middleware('auth', ['except' => ['show']]);
     }

    __construct 是 PHP 的构造器方法,当一个类对象被创建之前该方法将会被调用。我们在 __construct 方法中调 用了 middleware 方法,该方法接收两个参数,第一个为中间件的名称,第二个为要进行过滤的动作。我们通过 except 方法来设定 指定动作 不使用 Auth 中间件进行过滤,意为 —— 除了此处指定的动作以外,所有其他动作都必 须登录用户才能访问,类似于黑名单的过滤机制。相反的还有 only 白名单方法,将只过滤指定动作。我们提倡在控制 器 Auth 中间件使用中,首选 except 方法,这样的话,当你新增一个控制器方法时,默认是安全的,此为最佳实践。 Laravel 提供的 Auth 中间件在过滤指定动作时,如该用户未通过身份验证(未登录用户),将会被重定向到登录页面:

    用户只能编辑自己的资料

    使用以下命令来生成一个名为 UserPolicy 的授权策略类文件,用于管理用户模型的授权

     php artisan make:policy UserPolicy

    所有生成的授权策略文件都会被放置在 app/Policies 文件夹下。 让我们为默认生成的用户授权策略添加 update 方法,用于用户更新时的权限验证。

    app/Policies/UserPolicy.php

    public function update(User $currentUser, User $user)
     {
     return $currentUser->id === $user->id;
     }
    update 方法接收两个参数,第一个参数默认为当前登录用户实例,第二个参数则为要进行授权的用户实例。当两个 id
    相同时,则代表两个用户是相同用户,用户通过授权,可以接着进行下一个操作。如果 id 不相同的话,将抛出 403 异常
    信息来拒绝访问。
    使用授权策略需要注意以下两点:
    1. 我们并不需要检查 $currentUser 是不是 NULL。未登录用户,框架会自动为其 所有权限 返回 false2. 调用时,默认情况下,我们 不需要 传递当前登录用户至该方法内,因为框架会自动加载当前登录用户(接着看下
    去,后面有例子);
    接下来我们还需要在 AuthServiceProvider 类中对授权策略进行注册。 AuthServiceProvider 包含了一个
    policies 属性,该属性用于将各种模型对应到管理它们的授权策略上。我们需要为用户模型 User 指定授权策略
    UserPolicy 。

    app/Providers/AuthServiceProvider.php

    protected $policies = [
     'App\Model' => 'App\Policies\ModelPolicy',
     \App\Models\User::class => \App\Policies\UserPolicy::class,
     ];

    授权策略定义完成之后,我们便可以在控制器中使用 authorize 方法来检验用户是否授权。默认的 App\Http\Controllers\Controller 控制器基类包含了 Laravel 的 AuthorizesRequests trait。此 trait 提供了 authorize 方法,它可以被用于快速授权一个指定的行为,当无权限运行该行为时会抛出 HttpException。 authorize 方法接收两个参数,第一个为授权策略的名称,第二个为进行授权验证的数据。 我们需要为 edit 和 update 方法加上这行:

    $this->authorize('update', $user);

    这里 update 是指授权类里的 update 授权方法, $user 对应传参 update 授权方法的第二个参数。正如 上面定义 update 授权方法时候提起的,调用时,默认情况下,我们 不需要 传递第一个参数,也就是当前登录用 户至该方法内,因为框架会 自动 加载当前登录用户。

    书写的位置如下: app/Http/Controllers/UsersController.php

    public function edit(User $user)
     {
     $this->authorize('update', $user);
     return view('users.edit', compact('user'));
     }
     public function update(UserRequest $request, ImageUploadHandler $uploader, User $user)
     {
     $this->authorize('update', $user);
     $data = $request->all();

     10 git相关

    laravel数据回滚 

     php artisan migrate:rollback

    还原修改文件到原始状态:

    git checkout .
    git clean -f -d

    命令 git clean 作用是清理项目, -f 是强制清理文件的设置, -d 选项命令连文件夹一并清除。

    
    
  • 相关阅读:
    https://pingcap.com/blog-cn/flame-graph/
    https://software.intel.com/sites/landingpage/pintool/docs/97998/Pin/html/
    http://boostorg.github.io/stacktrace/stacktrace/getting_started.html#stacktrace.getting_started.how_to_print_current_call_stack
    线程局部存储
    slice 切片实现 Slice object interface
    网络分裂 redis 集群
    vscode-sftp
    Sizes of integer types 整形字节长度 系统字节
    学件中心
    源码 版本
  • 原文地址:https://www.cnblogs.com/linzenews/p/12576772.html
Copyright © 2020-2023  润新知