laravel配置workerman以及日志存储相关配置

①配置日志文件

config/app.php中

# 日志模式,可选择参数有 "single", "daily", "syslog", "errorlog"
 'log' => env('APP_LOG', 'single'),
 # 错误等级,为 "RFC 5424" 中定义的八种日志级
 'log_level' => env('APP_LOG_LEVEL', 'debug'),
  #设置最大存储的文件数量
  'log_max_files' => env('LOG_MAX_FILES', '30'),
#具体其他详细介绍信息请参照
#https://segmentfault.com/a/1190000009619874

②时区配置

config/app.php中

  'timezone' => 'Asia/Shanghai',

③laravel-sql数据记录日志
1.在 app/Providers/EventServicePorvider.php 文件中 添加要注册的事件

use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
    protected $listen = [
        'Illuminate\Database\Events\QueryExecuted' => [
            'App\Listeners\QueryListener',
        ],
    ];
}

2.执行 命令 php artisan event:generate
3.在 App\Listeners\QueryListener 文件的 handle 方法中编写记录 sql 的业务逻辑,如

public function handle(QueryExecuted $event)
{
    try{
        if (env('APP_DEBUG') == true) {
            $sql = str_replace("?", "'%s'", $event->sql);
            foreach ($event->bindings as $i => $binding) {
                if ($binding instanceof DateTime) {
                    $event->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
                } else {
                    if (is_string($binding)) {
                        $event->bindings[$i] = "'$binding'";
                    }
                }
            }
            $log = vsprintf($sql, $event->bindings);
            $log = $log.'  [ RunTime:'.$event->time.'ms ] ';
            (new Logger('sql'))->pushHandler(new RotatingFileHandler(storage_path('logs/sql/sql.log')))->info($log);
        }
    }catch (Exception $exception){

    }
}

④laravel逆向生成迁移文件

1.composer require --dev "xethron/migrations-generator"
2.在 config/app.php中添加相应的服务提供者
// 省略之前内容
'providers'       => [
    // 省略之前内容
    Way\Generators\GeneratorsServiceProvider::class,
    Xethron\MigrationsGenerator\MigrationsGeneratorServiceProvider::class,
],
// 省略之后内容
3.注册服务,在app/Providers/AppServiceProvider.php中register()方法里添加

// 仅在开发环境中使用
if ($this->app->environment() !== 'production') {
    $this->app->register(\Way\Generators\GeneratorsServiceProvider::class);
    $this->app->register(\Xethron\MigrationsGenerator\MigrationsGeneratorServiceProvider::class);
}
4.执行迁移文件 
php artisan migrate:generate
一些确认项目需要手动执行下
Using connection: mysql
Generating migrations for: articles, password_resets, students, students_10000, users
 Do you want to log these migrations in the migrations table? [Y/n] :
 > Y
 Next Batch Number is: 2. We recommend using Batch Number 0 so that it becomes the "first" migration [Default: 0] :
 > 0
Setting up Tables and Index Migrations

Setting up Foreign Key Migrations
Finished!
此时就可以看到
database/migrations/生成的迁移文件

4-1  你也可以指定某张表生成迁移文件
     php artisan migrate:generate table1,table2,table3 
4-2  也可以反向忽略某些表
      php artisan migrate:generate --ignore="table3,table4,table5"

⑤laravel配置workerman实现wss或者ws

1.安装需要的扩展包

1. composer   require  workerman/gateway-worker

2.书写artisan 需要用到的代码 app/Console/Commands/WorkermanCommand

namespace App\Console\Commands;
use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use Illuminate\Console\Command;
use Workerman\Worker;
class WorkermanCommand extends Command
{
    //配置  wss  的方法
    //https://blog.csdn.net/weixin_42579642/article/details/85266997
    protected $signature = 'workman {action} {--d}';
    protected $description = 'Start a Workerman server.';

    public function handle()
    {
        global $argv;
        $action = $this->argument('action');

        $argv[0] = 'wk';
        $argv[1] = $action;
        $argv[2] = $this->option('d') ? '-d' : '';

        $this->start();
    }
    private function start()
    {
        $this->startGateWay();
        $this->startWorker();
        $this->startRegister();
        Worker::runAll();
    }
    private function startWorker()
    {
        $worker = new BusinessWorker();
        $worker->name = 'Worker';
        $worker->count = 1;
        $worker->registerAddress = '127.0.0.1:1236';
        $worker->eventHandler = \App\Workerman\Events::class;
    }

    private function startGateWay()
    {
        //http://doc.workerman.net/faq/secure-websocket-server.html
        // 证书最好是申请的证书
        $context = array(
            // 更多ssl选项请参考手册 http://php.net/manual/zh/context.ssl.php
            'ssl' => array(
                // 请使用绝对路径
               // 'local_cert' => '/www/wwwroot/cattle_car.com/public/ssl/4035525_niuniu.micropig.cn.pem', // 也可以是crt文件
                //'local_pk' => '/www/wwwroot/cattle_car.com/public/ssl/4035525_niuniu.micropig.cn.key',
                'local_cert' => '/www/server/panel/vhost/cert/cattle_car.com/fullchain.pem',
                'local_pk' => '/www/server/panel/vhost/cert/cattle_car.com/privkey.pem',
                'verify_peer' => false,
                'verify_peer_name' => false,
                // 'allow_self_signed' => true, //如果是自签名证书需要开启此选项
            )
        );
        //$gateway = new Gateway("websocket://0.0.0.0:2346", $context);
        $gateway = new Gateway("websocket://0.0.0.0:2346");
        $gateway->name = 'Gateway';
        //$gateway->transport = 'ssl';
        $gateway->count = 1;
        $gateway->lanIp = '127.0.0.1';
        $gateway->startPort = 2300;
        $gateway->pingInterval = 30;
        $gateway->pingNotResponseLimit = 0;
        $gateway->pingData = '{"type":"@heart@"}';
        $gateway->registerAddress = '127.0.0.1:1236';
    }
    private function startRegister()
    {
        new Register('text://0.0.0.0:1236');
    }
}

3.workerman处理接受到的消息app/Workerman/Events.php

namespace App\Workerman;
use \GatewayWorker\Lib\Gateway;
class Events
{
    public static function onWorkerStart($businessWorker)
    {

    }

    public static function onConnect($client_id)
    {

        Gateway::sendToClient($client_id, json_encode(array(
            'type' => 'init',
            'client_id' => $client_id
        )));

    }
    public static function onWebSocketConnect($client_id, $data)
    {
        if (isset($data['get']['user_id'])) {
            Gateway::bindUid($client_id, $data['get']['user_id']);
        }
      //  Gateway::sendToAll('{"type":"test","data":"有用户上线了"}');
    }

    public static function onMessage($client_id, $message)
    {
        $message_data = json_decode($message, true);
        if ($message_data && isset($message_data['type']) && $message_data['type']=='heart') {
            Gateway::sendToClient($client_id, '{"type":"heart","data":"heart","msg":"heart"}');
        }

    }

    public static function onClose($client_id)
    {
    }
}

4.进行对应的时间发送对应的数据 app/Observers/ImMessageObserver
此处只用关注ImMessage的数据创建就可以了,数据插入进来会自动创建

namespace App\Observers;
use App\Events\AfterSendMessageEvent;
use App\Http\Model\ImMessage;
use GatewayWorker\Lib\Gateway;
use Illuminate\Support\Facades\Log;
use  App\Http\Model\Order;
// creating, created, updating, updated, saving,
// saved,  deleting, deleted, restoring, restored
class ImMessageObserver
{
    public function created(ImMessage $im_message)
    {
        Log::debug('-------message-----------start------');
        // 发送消息 1.员工端消息, 2.用户端消息
        $message = json_encode([
            'type' => $im_message->type,
            'message' => $im_message->message,
            'get_user_id' => (int)$im_message->get_user_id,
            'timestamp' => (int)(strtotime($im_message->created_at) . '000')], JSON_UNESCAPED_UNICODE);
       //根据不同的角色发送不同的数据
        switch ($im_message->user_type) {
            case 1:
                $uid = 'user_id@' . $im_message->get_user_id;
                break;
            case 2:
                $uid = 'worker_id@' . $im_message->get_user_id;
                break;
            case 3:
                $uid = 'pc@' . $im_message->get_user_id;
                break;
            default:
                $uid = 'all@' . $im_message->get_user_id;
                break;
        }
        Log::info('==========发送消息给' . $uid . ', 内容:' . $message);
        Gateway::sendToUid($uid, $message);
        Log::info('============是否在线 ' . Gateway::isUidOnline($uid) . ' ====');
        Log::debug('-------message-----------end------');
    }
}

5.监听观察者配置–app/Providers/AppServiceProvider.php

 class AppServiceProvider extends ServiceProvider
 {

     public function boot()
     {
         //
         \App\Http\Model\ImMessage::observe(\App\Observers\ImMessageObserver::class);
     
     }
.....省略下面的
}

6.配置当前网站的nginx,从而实现wss

   #wss 转代理
    location /wss
    {
    proxy_pass http://127.0.0.1:2346;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header X-Real-IP $remote_addr;
   }

7.链接wss时

 域名/wss
#例如 www.wsstest.com/wss

8 即时通讯,workerman的开启以及停止,需要开启服务器 2346 ,1236 端口


启动workerman
~~~
 php artisan workman start --d
~~~
关闭workerman
~~~
 php artisan workman stop 
~~~

laravel有用的数据sql收集

1,多个字段数据库拼接

  $list = $this->where([
            // 'store_id' => $store_id,
            'user_id' => $user_id,
        ])->select('order.*', DB::raw("concat_ws('-',license_plate,car_brand,car_type) as car_info"))
            ->leftjoin('order_car as c', 'c.order_id', '=', 'order.id')->with([
                'store',
                'car',
                'worker.wechat',
                'service',
                'user.wechat',
            ])->orderBy('created_at', 'desc')
            ->paginate($limit);

2,根据不同的搜索字段显示不同的字段

      $shareMessage = $this->where(['type' => $type])
            ->when($type == 1, function ($query) {
                $query->select('imageUrl', 'title', 'path');
            }, function ($query) {
                $query->select('imageUrl  as  bgImgUrl', 'title', 'desc', 'path');
            })->first();

3,数据统计相关

  $_sql = 'SELECT  *,
   CONVERT (t.goods_evaluate / t.all_evaluate,
      DECIMAL (10, 2)
   ) AS goods_rate,
      CONVERT (t.add_comment / t.all_evaluate,
      DECIMAL (10, 2)
   ) AS add_comment_rate,
   CONVERT (
      t.middle_evaluate / t.all_evaluate,
      DECIMAL (10, 2)
   ) AS middle_rate,
   CONVERT (
      t.difference_evaluate / t.all_evaluate,
      DECIMAL (10, 2)
   ) AS difference_rate,
       CONVERT (
      t.replay_number / t.middle_bad_evaluate,
      DECIMAL (10, 2)
   ) AS middle_bad_evaluate_rate 
    FROM (
   SELECT ' . $groupfild . ',
count(*) AS all_evaluate,
sum(CASE WHEN comentResult = 1 then 1 else 0 end) AS goods_evaluate,
sum(CASE WHEN isAddComment = 1 then 1 else 0 end) AS add_comment,
sum(CASE WHEN comentResult = 2 then 1 else 0 end) AS middle_evaluate,
sum(CASE WHEN (comentResult=2 OR comentResult=3 ) then 1 else 0 end ) AS middle_bad_evaluate,
sum(CASE WHEN (replayStatus = 1 AND (comentResult=2 OR comentResult=3 ))then 1 else 0 end) AS replay_number,
sum(CASE WHEN comentResult = 3 then 1 else 0 end) AS difference_evaluate FROM ' . $db_prefix . 'comment'  . ' WHERE '.$sql .' group by ' . $groupfild . ' ) AS t';
$data = DB::select($_sql);

你可能感兴趣的:(PHP技术总结)