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){
}
}
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"
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
~~~
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);