“系统服务”的版本间的差异
(→加入参数到分页链接) |
(→使用示例) |
||
(未显示同一用户的16个中间版本) | |||
第1行: | 第1行: | ||
+ | ==认证== | ||
+ | |||
+ | ===解决问题:No supported encrypter found=== | ||
+ | |||
+ | 刚部署好Laravel 5.1,打开首页的时候提示错误,开启debug模式以后,就看到具体错误信息:No supported encrypter found. The cipher and / or key length are invalid. | ||
+ | |||
+ | 问题原因是config/app.php中有一个关于秘钥类型的配置,默认设置为AES-256-CBC,也就是对应的秘钥必须是32个字符,而默认配置中写的是SomeRandomString,只有16个字符。当然我们可以通过将cipher设置为AES-128-CBC来解决这个问题。 | ||
+ | |||
+ | 但是,毕竟SomeRandomString也不是个像样的秘钥,我们可以生成一个。只需要下面这个代码: | ||
+ | |||
+ | <source lang='bash'> | ||
+ | php artisan key:generate | ||
+ | Application key [xlhF31NeOlibJcoOW9tvZg7TkHcAZI3a] set successfully. | ||
+ | </source> | ||
+ | |||
+ | 这个时候我们将生成的秘钥,修改到config/app.php的key字段中,替换掉SomeRandomString就好了。 | ||
+ | |||
+ | ===Route::auth();是什么用的?=== | ||
+ | |||
+ | Route::auth()其实是调用Illuminate/Routing/Router类的auth方法: | ||
+ | |||
+ | <source lang='php'> | ||
+ | public function auth() { | ||
+ | // Authentication Routes... | ||
+ | $this->get('login', 'Auth\AuthController@showLoginForm'); | ||
+ | $this->post('login', 'Auth\AuthController@login'); | ||
+ | $this->get('logout', 'Auth\AuthController@logout'); | ||
+ | |||
+ | // Registration Routes... | ||
+ | $this->get('register', 'Auth\AuthController@showRegistrationForm'); | ||
+ | $this->post('register', 'Auth\AuthController@register'); | ||
+ | |||
+ | // Password Reset Routes... | ||
+ | $this->get('password/reset/{token?}', 'Auth\PasswordController@showResetForm'); | ||
+ | $this->post('password/email', 'Auth\PasswordController@sendResetLinkEmail'); | ||
+ | $this->post('password/reset', 'Auth\PasswordController@reset'); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | ===认证流程=== | ||
+ | |||
+ | # php artisan make:auth | ||
+ | # Route::auth() | ||
+ | # 注册表单出错提示出不来,要新建postRegister()才行。 | ||
+ | # email邮箱唯一性检查在validate rules里定义。 | ||
+ | |||
+ | ===自定义auth=== | ||
+ | |||
+ | Laravel的认证是使用guard与provider配合完成: | ||
+ | * guard负责认证的业务逻辑,认证信息的服务端保存等。系统自带session和token。 | ||
+ | * provider负责提供认证信息的持久化数据提供。系统自带eloquent和database。 | ||
+ | |||
+ | <source lang='php'> | ||
+ | /** | ||
+ | * config/auth.php | ||
+ | */ | ||
+ | return [ | ||
+ | 'defaults' => [ | ||
+ | 'guard' => 'web', | ||
+ | 'passwords' => 'users', | ||
+ | ], | ||
+ | 'guards' => [ | ||
+ | 'web' => [ | ||
+ | 'driver' => 'session', | ||
+ | 'provider' => 'users', | ||
+ | ], | ||
+ | |||
+ | 'api' => [ | ||
+ | 'driver' => 'token', | ||
+ | 'provider' => 'users', | ||
+ | ], | ||
+ | ], | ||
+ | 'providers' => [ | ||
+ | 'users' => [ | ||
+ | 'driver' => 'eloquent', | ||
+ | 'model' => App\User::class, | ||
+ | ], | ||
+ | |||
+ | // 'users' => [ | ||
+ | // 'driver' => 'database', | ||
+ | // 'table' => 'users', | ||
+ | // ], | ||
+ | ], | ||
+ | 'passwords' => [ | ||
+ | 'users' => [ | ||
+ | 'provider' => 'users', | ||
+ | 'email' => 'auth.emails.password', | ||
+ | 'table' => 'password_resets', | ||
+ | 'expire' => 60, | ||
+ | ], | ||
+ | ], | ||
+ | ]; | ||
+ | </source> | ||
+ | |||
+ | 请求提交给guard,guard从provider里取出数据(类似用户名、密码等),验证输入数据与服务器端存储的数据是否吻合。如果提交的数据正确,再做session等业务的处理(如有需要)。 | ||
+ | |||
+ | 系统提供了方法可以添加自己定义的guard和provide。 | ||
+ | |||
+ | <source lang='php'> | ||
+ | // AuthManager.php | ||
+ | // Register a custom driver creator Closure. | ||
+ | public function extend($driver, Closure $callback) | ||
+ | { | ||
+ | $this->customCreators[$driver] = $callback; | ||
+ | |||
+ | return $this; | ||
+ | } | ||
+ | |||
+ | // Register a custom provider creator Closure. | ||
+ | public function provider($name, Closure $callback) | ||
+ | { | ||
+ | $this->customProviderCreators[$name] = $callback; | ||
+ | |||
+ | return $this; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | ==授权== | ||
+ | |||
+ | 对一些方法绑定条件,符合条件的人员才允许操作。 | ||
+ | |||
+ | ==Elixir== | ||
+ | |||
+ | Laravel Elixir提供了简洁流畅的API,让你能够在你的Laravel应用程序中定义基本的Gulp任务。 | ||
+ | |||
+ | ===安装=== | ||
+ | |||
+ | 默认情况下,Laravel Homestead会包含你所需的一切。在每一份新安装的Laravel代码里,你会发现根目录有个名为package.json的文件。想像它就如同你的composer.json文件,只不过它定义的是Node的依赖扩展包,而不是PHP的。 | ||
+ | |||
+ | <source lang='bash'> | ||
+ | #检查是否安装有node | ||
+ | node -v | ||
+ | |||
+ | #全局安装Gulp的NPM扩展包 | ||
+ | npm install --global gulp-cli | ||
+ | |||
+ | #安装依赖扩展包 | ||
+ | npm install | ||
+ | </source> | ||
+ | |||
+ | ===elixir任务=== | ||
+ | |||
+ | 默认目录resources/assets,目标目录public/build。 | ||
+ | |||
+ | <source lang='php'> | ||
+ | elixir(function (mix) { | ||
+ | mix.styles([ | ||
+ | '../bootstrap/css/bootstrap.min.css' | ||
+ | ]); | ||
+ | }); | ||
+ | |||
+ | elixir(function (mix) { | ||
+ | mix.scripts([ | ||
+ | 'jquery.min.js', | ||
+ | '../bootstrap/js/bootstrap.min.js' | ||
+ | ]); | ||
+ | }); | ||
+ | |||
+ | elixir(function (mix) { | ||
+ | mix.version(['css/all.css', 'js/all.js']); | ||
+ | }); | ||
+ | </source> | ||
+ | |||
+ | <source lang='bash'> | ||
+ | #运行所有任务... | ||
+ | gulp | ||
+ | |||
+ | #运行所有任务并压缩所有CSS及JavaScript... | ||
+ | gulp --production | ||
+ | </source> | ||
+ | |||
+ | ===模板引用=== | ||
+ | |||
+ | <source lang='html4strict'> | ||
+ | <link href="{{ elixir('css/all.css') }}" rel="stylesheet"> | ||
+ | |||
+ | <script src="{{ elixir('js/all.js') }}"></script> | ||
+ | </source> | ||
+ | |||
+ | ;No such file or directory | ||
+ | |||
+ | <source lang='text'> | ||
+ | 1. In your gulpfile.js add this line: mix.version(['public/css/app.css']); if you want to version your css file. | ||
+ | 2. change <link href="{{ elixir('css/app.css') }}" rel="stylesheet"> | ||
+ | to <link href="{{ asset('css/app.css') }}" rel="stylesheet"> | ||
+ | if you don't want to version your css file. | ||
+ | </source> | ||
+ | |||
+ | 在模板中使用elixir(),程序会在build目录中寻找文件,而那时我还没有使用mix.version()来生成版本文件,就发生找不到文件报错了。 | ||
+ | |||
==事件== | ==事件== | ||
第78行: | 第268行: | ||
{{ $users->links() }} | {{ $users->links() }} | ||
+ | </source> | ||
+ | |||
+ | ===单独使用=== | ||
+ | |||
+ | <source lang='php'> | ||
+ | $articles = new LengthAwarePaginator($result['data'], $result['total'], $count, $page, ['path' => '/article/article-list']); | ||
</source> | </source> | ||
第156行: | 第352行: | ||
'name.max' => '姓名不能超过:max个字符', | 'name.max' => '姓名不能超过:max个字符', | ||
'old.required' => '我们需要知道你的年龄', | 'old.required' => '我们需要知道你的年龄', | ||
+ | ], [ | ||
+ | 'name' => '姓名', | ||
+ | 'old' => '年龄' | ||
]); | ]); | ||
2017年1月25日 (三) 01:52的最后版本
目录
认证
解决问题:No supported encrypter found
刚部署好Laravel 5.1,打开首页的时候提示错误,开启debug模式以后,就看到具体错误信息:No supported encrypter found. The cipher and / or key length are invalid.
问题原因是config/app.php中有一个关于秘钥类型的配置,默认设置为AES-256-CBC,也就是对应的秘钥必须是32个字符,而默认配置中写的是SomeRandomString,只有16个字符。当然我们可以通过将cipher设置为AES-128-CBC来解决这个问题。
但是,毕竟SomeRandomString也不是个像样的秘钥,我们可以生成一个。只需要下面这个代码:
php artisan key:generate Application key [xlhF31NeOlibJcoOW9tvZg7TkHcAZI3a] set successfully.
这个时候我们将生成的秘钥,修改到config/app.php的key字段中,替换掉SomeRandomString就好了。
Route::auth();是什么用的?
Route::auth()其实是调用Illuminate/Routing/Router类的auth方法:
public function auth() { // Authentication Routes... $this->get('login', 'Auth\AuthController@showLoginForm'); $this->post('login', 'Auth\AuthController@login'); $this->get('logout', 'Auth\AuthController@logout'); // Registration Routes... $this->get('register', 'Auth\AuthController@showRegistrationForm'); $this->post('register', 'Auth\AuthController@register'); // Password Reset Routes... $this->get('password/reset/{token?}', 'Auth\PasswordController@showResetForm'); $this->post('password/email', 'Auth\PasswordController@sendResetLinkEmail'); $this->post('password/reset', 'Auth\PasswordController@reset'); }
认证流程
- php artisan make:auth
- Route::auth()
- 注册表单出错提示出不来,要新建postRegister()才行。
- email邮箱唯一性检查在validate rules里定义。
自定义auth
Laravel的认证是使用guard与provider配合完成:
- guard负责认证的业务逻辑,认证信息的服务端保存等。系统自带session和token。
- provider负责提供认证信息的持久化数据提供。系统自带eloquent和database。
/** * config/auth.php */ return [ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], 'passwords' => [ 'users' => [ 'provider' => 'users', 'email' => 'auth.emails.password', 'table' => 'password_resets', 'expire' => 60, ], ], ];
请求提交给guard,guard从provider里取出数据(类似用户名、密码等),验证输入数据与服务器端存储的数据是否吻合。如果提交的数据正确,再做session等业务的处理(如有需要)。
系统提供了方法可以添加自己定义的guard和provide。
// AuthManager.php // Register a custom driver creator Closure. public function extend($driver, Closure $callback) { $this->customCreators[$driver] = $callback; return $this; } // Register a custom provider creator Closure. public function provider($name, Closure $callback) { $this->customProviderCreators[$name] = $callback; return $this; }
授权
对一些方法绑定条件,符合条件的人员才允许操作。
Elixir
Laravel Elixir提供了简洁流畅的API,让你能够在你的Laravel应用程序中定义基本的Gulp任务。
安装
默认情况下,Laravel Homestead会包含你所需的一切。在每一份新安装的Laravel代码里,你会发现根目录有个名为package.json的文件。想像它就如同你的composer.json文件,只不过它定义的是Node的依赖扩展包,而不是PHP的。
#检查是否安装有node node -v #全局安装Gulp的NPM扩展包 npm install --global gulp-cli #安装依赖扩展包 npm install
elixir任务
默认目录resources/assets,目标目录public/build。
elixir(function (mix) { mix.styles([ '../bootstrap/css/bootstrap.min.css' ]); }); elixir(function (mix) { mix.scripts([ 'jquery.min.js', '../bootstrap/js/bootstrap.min.js' ]); }); elixir(function (mix) { mix.version(['css/all.css', 'js/all.js']); });
#运行所有任务... gulp #运行所有任务并压缩所有CSS及JavaScript... gulp --production
模板引用
<link href="{{ elixir('css/all.css') }}" rel="stylesheet"> <script src="{{ elixir('js/all.js') }}"></script>
- No such file or directory
1. In your gulpfile.js add this line: mix.version(['public/css/app.css']); if you want to version your css file. 2. change <link href="{{ elixir('css/app.css') }}" rel="stylesheet"> to <link href="{{ asset('css/app.css') }}" rel="stylesheet"> if you don't want to version your css file.
在模板中使用elixir(),程序会在build目录中寻找文件,而那时我还没有使用mix.version()来生成版本文件,就发生找不到文件报错了。
事件
Laravel事件提供了简单的侦听器实现,允许你订阅和监听事件,事件类通常被保存在app/Events目录下,而它们的侦听器被保存在app/Listeners目录下。
错误与日志
//.env APP_DEBUG=true // bootstrap/app.php $app->withFacades(); //引用Log use Log; // 8个日志级别 Log::emergency($error); Log::alert($error); Log::critical($error); Log::error($error); Log::warning($error); Log::notice($error); Log::info($error); Log::debug($error);
测试
public function testTom() { $response = $this->call('get', '/userInfo'); $result = json_decode($response->original); $this->assertEquals( 'Tom', $result->name ); }
缓存
use Cache; if (Cache::has('key')) { $coupon_total = Cache::get('key'); } else { $rs = Coupon_api::instance()->total(); if ($rs['status']) { $coupon_total = $rs['data']['total_amount']; } Cache::put('key', $coupon_total, 5); //5 minutes }
分页
使用示例
use DB; public function index() { $users = DB::table('users')->paginate(15); return view('user.index', ['users' => $users]); } <div class="container"> @foreach ($users as $user) {{ $user->name }} @endforeach </div> {{ $users->links() }}
单独使用
$articles = new LengthAwarePaginator($result['data'], $result['total'], $count, $page, ['path' => '/article/article-list']);
加入参数到分页链接
//加入参数到分页链接 {{ $users->appends(['sort' => 'votes'])->links() }} //在分页链接中加入哈希片段。 {{ $users->fragment('foo')->links() }}
转换至JSON
Laravel的分页类实现了Illuminate\Contracts\Support\JsonableInterface的toJson方法,所以可以很容易的将你的分页结果转换成JSON,只需从一个路由或控制器中返回它即可。
Route::get('users', function () { return App\User::paginate(); });
session
- session使用
use Illuminate\Http\Request; function blade(Request $request) { //赋值 session(['name'=> 'Tom']); $request->session()->put('name', 'Tom'); $request->session()->push('students', 'Tom'); //取值 $name = session('name'); $request->session()->get('students'); }
- Session store not set on request.
// Kernel.php添加中间件 protected $middleware = [ //... \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, ];
表单验证
一个简单的例子
开始照着手册上的例子作练习,发现页面显示不了,猜想是不是代码没写全,补充了其它代码,也不行,后来发现页面不显示,浏览器报两种错误:
- 500:我糊乱把ajax验证的代码抄过来用,代码执行错误。
- too many redirects:validate验证不过,会直接返回一个reponse,表单和后台用一个控制器,就反复不断循环跳转到自己。
花了很久时间才终于弄明白,原来是我验证流程没弄明白,正确的代码也执行不了。
function input() { return view('input'); } function store(Request $request) { $request->flash(); $this->validate($request, [ 'name' => 'required|max:5', 'old' => 'required', ], [ 'name.required' => '请填写姓名', 'name.max' => '姓名不能超过:max个字符', 'old.required' => '我们需要知道你的年龄', ], [ 'name' => '姓名', 'old' => '年龄' ]); return 'validation is OK!'; }
注意事项
- 默认情况下,Laravel的基底控制器类使用了ValidatesRequests trait,其提供了一种便利的方法来使用各种强大的验证规则验证传入的HTTP请求。在控制器中,用$this->validate()来使用验证功能。
- $this->validate()如果验证失败,则会抛出异常错误消息并自动生成一个对应的响应。
- 所有的验证错误会被自动闪存至session。
- $errors变量在每次请求的所有视图中都可以被使用。
AJAX验证
use Validator; function store(Request $request) { $validator = Validator::make($request->all(), [ 'name' => 'required|max:5', 'old' => 'required', ]); return $validator->errors(); }
手动创建验证程序
如果你不想要使用ValidatesRequests trait的validate方法,你可以手动创建一个validator实例并通过Validator::make方法在facade生成一个新的validator实例。
function store(Request $request) { $validator = Validator::make($request->all(), [ 'name' => 'required|max:5', 'old' => 'required', ]); if ($validator->fails()) { return redirect('/input') ->withErrors($validator) ->withInput(); } return 'validation is OK!'; }
表单请求类
怎样才能较好的运行验证规则呢?
为了不使验证逻辑而把控制器弄得一团糟,也为了能应付更复杂的验证情境,你可能会想要创建一个form request,然后在在控制器方法中利用类型提示传入请求,这样传入的请求会在控制器方法被调用前进行验证。
- 1、生成表单请求类
php artisan make:request StoreBlogPostRequest
- 2、使用表单请求类
public function store(StoreBlogPostRequest $request){ // 传入的请求是有效的... }
- 3、表单请求类
//如果你打算在应用程序的其它部分处理授权逻辑,只需从authorize方法返回true。 public function authorize(){ $commentId = $this->route('comment'); return Comment::where('id', $commentId) ->where('user_id', Auth::id())->exists(); } //验证规则 public function rules(){ return [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]; } //错误消息 public function messages(){ return [ 'title.required' => '标题是必填的', 'body.required' => '消息是必填的', ]; }
复杂的条件验证
如果年纪大于100岁,一定要写长寿原因。这种验证条件,只能在控制器中验证,不能在表单请求类中写rules来实现。
function store(Request $request) { $validator = Validator::make($request->all(), [ 'name' => 'required|max:5', 'old' => 'required', ], [ 'name.required' => '请填写姓名', 'name.max' => '姓名不能超过:max个字符', 'old.required' => '我们需要知道你的年龄', 'reason.required' => '你为何如此长寿?' ]); $validator->sometimes(['reason'], 'required', function ($input) { return $input->old >= 100; }); if ($validator->fails()) { return redirect('/input') ->withErrors($validator) ->withInput(); } return 'validation is OK!'; }