Laravel队列使用案例

1、配置数据库和Redis
	//编辑config/database.php
	'mysql' => [
            'driver' => 'mysql',
            'host' => 'localhost',
            'port' => 3306,
            'database' => 'demo_laravel',
            'username' => 'demo',
            'password' => '123456',
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => '',
            'strict' => false,
            'engine' => null,
        ],
	'queue' => [
            'host' => '192.168.56.101',
            'password' => null,
            'port' => 6379,
            'database' => 0,
        ],
	//config/queue.php
	'default' => 'redis',
	'connections' => [
        'redis' => [
            'driver' => 'redis',
            'connection' => 'queue',
            'queue' => 'default',
            'expire' => 3600,//队列有效期
        ],

    ],
	'failed' => [
        'database' => 'mysql',
        'table' => 'failed_jobs',
    ],
2、添加failed-table
执行:php artisan queue:failed-table
执行:php artisan migrate:install
执行:php artisan migrate
3、生产者
将数据丢入队列
执行:php artisan make:console Demo/Test
<?php

namespace App\Console\Commands\Demo;

use App\Jobs\Demo\HandleTest;
use Illuminate\Console\Command;
use Illuminate\Foundation\Bus\DispatchesJobs;

class Test extends Command
{
    use DispatchesJobs;
    /**
     * 将数据丢入队列
     */
    protected $signature = 'demo:test {--num=}';
    protected $description = '将数据丢入队列';
    public function __construct()
    {
        parent::__construct();
    }
    public function handle()
    {
        $num = $this->option('num');
        for($i = 0; $i <= $num; $i++) {
            $queueName = 'demo_1';//这里可以按照业务取模之后启动多个队列
            $job = (new HandleTest($i))->onConnection('redis')->onQueue($queueName);
            $this->dispatch($job);
        }
    }
}


4、消费者
将消费队列内容
php artisan make:job Demo/HandleTest
app/Jobs/Demo/HandleTest.php
<?php

namespace App\Jobs\Demo;

use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class HandleTest extends Job implements ShouldQueue
{
    use InteractsWithQueue, SerializesModels;
    //初始化数据
    public function __construct($data)
    {
        $this->data = $data;
    }
    public function handle()
    {
        echo $this->data . PHP_EOL;
    }
}
5、启动生产者
php artisan demo:test --num=2
//这样可以看到redis的queues:demo_1
在redis执行:LRANGE queues:demo_1 0 -1
可以看到3个元素
6、启动消费队列(可以使用supervisor管理消费队列)
php artisan queue:work redis --queue=demo_1 --daemon --tries=10
7、队列失败
如果队列执行失败则会将任务存入failed_jobs表
重试JOB可以执行 php artisan queue:retry	1

Laravle Queue命令

php artisan queue:work --help
Usage:
  queue:work [options] [--] [<connection>]

Arguments:
  connection             队列连接redis、database等

Options:
      --queue[=QUEUE]    队列任务
      --daemon           后台执行
      --delay[=DELAY]    任务执行失败之后延迟多久重试
      --force            Force the worker to run even in maintenance mode
      --memory[=MEMORY]  The memory limit in megabytes [default: 128]
      --sleep[=SLEEP]    队列无可用任务休息时间间隔,默认3s
      --tries[=TRIES]    失败任务最多重试次数 [default: 0]
  -h, --help             输出帮助信息
  -q, --quiet            不输出信息
  -V, --version          Display this application version
      --ansi             Force ANSI output
      --no-ansi          Disable ANSI output
  -n, --no-interaction   Do not ask any interactive question
      --env[=ENV]        The environment the command should run under.
  -v|vv|vvv, --verbose   Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
使用案例
php artisan queue:work redis --queue=recommend --daemon --tries=1
备注:
queue:work 默认只执行一次队列请求, 当请求执行完成后就终止;
queue:listen 监听队列请求, 只要运行着, 就能一直接受请求, 除非手动终止;
queue:work --daemon 同 listen 一样, 只要运行着, 就能一直接受请求, 不一样的地方是在这个运行模式下, 当新的请求到来的时候, 不重新加载整个框架, 而是直接 fire 动作.
能看出来, queue:work --daemon 是最高级的, 一般推荐使用这个来处理队列监听.

注意: 使用 queue:work --daemon , 当更新代码的时候, 需要停止, 然后重新启动, 这样才能把修改的代码应用上.
因此开发环境建议用queue:listen


php artisan queue:listen --help
Usage:
  queue:listen [options] [--] [<connection>]

Arguments:
  connection               The name of connection

Options:
      --queue[=QUEUE]      The queue to listen on
      --delay[=DELAY]      Amount of time to delay failed jobs [default: 0]
      --memory[=MEMORY]    The memory limit in megabytes [default: 128]
      --timeout[=TIMEOUT]  Seconds a job may run before timing out [default: 60]
      --sleep[=SLEEP]      Seconds to wait before checking queue for jobs [default: 3]
      --tries[=TRIES]      Number of times to attempt a job before logging it failed [default: 0]
  -h, --help               Display this help message
  -q, --quiet              Do not output any message
  -V, --version            Display this application version
      --ansi               Force ANSI output
      --no-ansi            Disable ANSI output
  -n, --no-interaction     Do not ask any interactive question
      --env[=ENV]          The environment the command should run under.
  -v|vv|vvv, --verbose     Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Laravel 权限控制基础之Gate 和Policy

policy和Gate
php artisan make:policy PostPolicy –model=Post //特定model
//AuthServiceProvider.php在定义权限
//Gate::define(‘view-post’, ‘ClassName@methodOne’);
Gate::define(‘show-info’, function ($test, $post) {
return $test->owns($post);
});
//user.php
public function owns($post)
{
return $this->id == $post->user_id;
}
//控制器
use Gate;
auth()->loginUsingId(1);
$test = TestModel::findOrFail(1);
//Gate::allows();//判断是否允许
if(Gate::denies(‘show-info’,$test)) {
echo ‘禁止访问’;
} else {
echo ‘允许访问’;
}
//可以用policy替换Gate
//AuthServiceProvider.php
protected $policies = [
‘app\Models\TestModel’ => ‘app\Policies\PostPolicy’,
];
$user = auth()->loginUsingId(1);
$test = TestModel::findOrFail(1);
echo $user->id;
echo $test->user_id;
if ($user->cannot(‘show-info’, $test)) {
echo ‘禁止访问’;
} else {
echo ‘允许访问’;
}
对于Gate来定义和policy替换, 在一个项目中通常两种方式都使用,如果访问控制的逻辑非常简单,且只需用到一个方法,那么直接写成Gate的闭包即可,如果比较复杂,且需要对模型进行多个方法的权限控制,那么就写成policy

Laravel :notification使用笔记

php artisan make:notification PayFinish
php artisan notifications:table 创建通知表
//TestModel
namespace app\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
class TestModel extends Model
{
use Notifiable;
protected $table = ‘test’;
}
//PayFinish
public function via($notifiable)
{
return [‘database’];
}
//toDatabase和toArray格式化消息内容
public function toArray($notifiable)
{
return [
‘test_id’ => $this->id,
‘name’ => $this->data->name,
];
}
//使用
$user = TestModel::find(1);
//$user->notify(new PayFinish($user));
foreach ($user->notifications as $notification) {
print_r($notification->data);
}
foreach ($user->unreadNotifications as $notification) {
print_r($notification->data);
//$notification->markAsRead();//标记已读
}
//Notification::send($user, new PayFinish());

Laravel middleware中间件

Laravel Middleware 中间件

php artisan make:middleware TestMiddleware

public function handle($request, Closure $next)
{
if($request->input(‘id’) > 1) {
die( ‘hello world’ );
}
return $next($request);
}
注册中间件
app/Http/Kernel.php$middleware添加

控制器当中
$this->middleware(‘Test’);
路由器
Route::get(‘/’,’Test\\TestController@index’, [‘middleware’ => ‘Test’]);

Laravel Event和Listener

make:event TestEvent 创建一个新事件类
php artisan make:listener TestListener –event TestEvent 创建一个listener类
注册事件TestEvent
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($str)
{
$this->data = $str;
}

/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
public function broadcastOn()
{
return [];
}
监听时间TestListener
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}

/**
* Handle the event.
*
* @param TestEvent $event
* @return void
*/
public function handle(TestEvent $event)
{
file_put_contents(‘/data/tmp/test.log’, $event->data, FILE_APPEND);
}
注册应用关联事件EventServiceProvider.php
protected $listen = [

‘app\Events\TestEvent’ => [
‘app\Listeners\TestListener’,
],
];
触发事件
$str = ‘test….’;
Event::fire(new TestEvent($str));
event(new TestEvent($str));

php artisan event:generate 批量生成event和listen 编辑EventServiceProvider.php

备注:事件可以广播,通过websocket服务,依赖Redis的pub和sub模式

Laravel笔记

1、路由示例
Route::get(‘demo/{id}’, ‘Demo\IndexController@index’);
匹配/demo/123格式
执行如下代码位置:app/Http/Controllers/Demo/IndexController.php当中index方法
注意: 路由参数不能包含”-“字符。使用下划线替代”_”
2、CSRF 保护
可以使用csrf_token()方法
使用示例:
<input type=”hidden” name=”_token” value=”<?php echo csrf_token(); ?>”>
3、方法欺骗
<input type=”hidden” name=”_method” value=”PUT”>
4、abort()辅助函数只是简单抛出带有特定状态代码的
5、HTTP 中间件提供一个方便的机制来过滤进入应用程序的 HTTP 请求
建立中间件
php artisan make:middleware OldMiddleware
注册中间件(全局和局部)
kernel.php添加$middleware属性可以注册全局;
Route::get(‘demo’,[‘middleware’ => ‘test’,’uses’ => ‘Demo\IndexController@index’]);//局部
6、创建控制器
php artisan make:controller Demo/TestController
隐式路由Route::controller(‘test’, ‘Demo\TestController’);
7、视图
return view(‘greeting’, [‘name’ => ‘James’]);
return view(‘admin.greeting’, [‘name’ => ‘James’]); //resources/views/admin/profile.blade.php

Laravel 辅助函数

array_add() 如果给定的键不在数组中,会把给定的键值对加到数组中.否则则不加入
array_divide() 函数返回两个数组,一个包含原本数组的键,另一个包含原本数组的值。
array_dot() 函数把多维数组扁平化成一维数组,并用”.”符号表示深度
array_except() 从数组当中移除指定键值对
array_fetch() 函数返回包含被选择的嵌套元素的扁平化数组
array_first() 函数返回数组中第一个通过给定的测试为真的元素
array_last() 函数返回数组中最后一个通过给定的测试为真的元素
array_flatten() 函数将会把多维数组扁平化成一维
array_forget() 函数将会用”.”符号从深度嵌套数组移除给定的键值对
array_get() 函数将会使用”.”符号从深度嵌套数组取回给定的值
array_only() 函数将会只从数组返回给定的键值对
array_pluck 函数将会从数组拉出给定键值对的清单
array_pull 函数将会从数组返回给定的键值对,并移除它
array_set 函数将会使用”.”符号在深度嵌套数组中指定值
array_sort 函数通过给定闭包的结果来排序数组
array_where 使用给定的闭包过滤数组
app_path 取得 app 文件夹的完整路径
base_path 取得应用程序安装根目录的完整路径
config_path 获取 config 目录的完整路径。
public_path 取得 public 文件夹的完整路径
storage_path 取得 app/storage 文件夹的完整路径
camel_case 把给定的字串转换成 驼峰式命名
class_basename 取得给定类的类名称,不含任何命名空间的名称
e 对给定字串执行 htmlentities,并支持 UTF-8
ends_with 判断句子结尾是否有给定的字串
snake_case 把给定的字串转换成 蛇形命名(下划线连接)
str_limit 限制字串的字符数量(一个中文2个字符)
starts_with 判断句子是否开头有给定的字串
str_contains 判断句子是否有给定的字串
str_finish 加一个给定字串到句子结尾。多余一个的给定字串则移除
str_is 判断字串是否符合给定的模式。星号可以用来当作通配符
str_random 产生给定长度的随机字串
action 产生给定控制器行为的网址
route 产生给定路由名称的网址
asset 产生资源的网址
secure_asset 产生给定资源的 HTTPS HTML 链接
secure_url 产生给定路径的 HTTPS 完整网址
url 产生给定路径的完整网址
csrf_token 返回 取得现在 CSRF token 的值
dd 打印给定变量并结束脚本执行
elixir 获取带版本号的 Elixir 文件的路径
env 获取一个环境变量的值,如果没有则返回一个默认值
event 触发一个事件
value 如果给定的值是个 闭包,返回 闭包 的返回值。不是的话,则返回值
view 用给定的视图路径取得一个视图实例
with 返回给定对象

PHP Storm 支持Laravel语法提示

1、在composer.json文件当中require段添加
“barryvdh/laravel-ide-helper”: “dev-master”
2、执行composer update
3、providers数组添加(注意5.2版本是在app/config/app.php文件)
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class
4、执行php artisan ide-helper:generate命令生成_ide_helper.php
5、测试是否生效,如果没生效可以重启PHPstorm