“系统服务”的版本间的差异

来自tomtalk
跳转至: 导航搜索
session
Tom讨论 | 贡献
使用示例
 
(未显示同一用户的18个中间版本)
第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()来生成版本文件,就发生找不到文件报错了。
 +
 
==事件==
 
==事件==
  
第59行: 第249行:
  
 
==分页==
 
==分页==
 +
 +
===使用示例===
 +
 +
<source lang='php'>
 +
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() }}
 +
</source>
 +
 +
===单独使用===
 +
 +
<source lang='php'>
 +
$articles = new LengthAwarePaginator($result['data'], $result['total'], $count, $page, ['path' => '/article/article-list']);
 +
</source>
 +
 +
===加入参数到分页链接===
 +
 +
<source lang='php'>
 +
//加入参数到分页链接
 +
{{ $users->appends(['sort' => 'votes'])->links() }}
 +
 +
//在分页链接中加入哈希片段。
 +
{{ $users->fragment('foo')->links() }}
 +
</source>
 +
 +
===转换至JSON===
 +
Laravel的分页类实现了Illuminate\Contracts\Support\JsonableInterface的toJson方法,所以可以很容易的将你的分页结果转换成JSON,只需从一个路由或控制器中返回它即可。
 +
 +
<source lang='php'>
 +
Route::get('users', function () {
 +
    return App\User::paginate();
 +
});
 +
</source>
  
 
==session==
 
==session==
第117行: 第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');
}

认证流程

  1. php artisan make:auth
  2. Route::auth()
  3. 注册表单出错提示出不来,要新建postRegister()才行。
  4. 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!';
}

注意事项

  1. 默认情况下,Laravel的基底控制器类使用了ValidatesRequests trait,其提供了一种便利的方法来使用各种强大的验证规则验证传入的HTTP请求。在控制器中,用$this->validate()来使用验证功能。
  2. $this->validate()如果验证失败,则会抛出异常错误消息并自动生成一个对应的响应。
  3. 所有的验证错误会被自动闪存至session。
  4. $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!';
}