Laravel 缓存类原子锁
在后端开发中,关于锁的问题,也是经常能遇到的。为了防止程序并行所导致的数据破坏,或者系统故障,在开发中合理的运用锁,可以带来更好的效果。Cache::lock用法:if (Cache::lock('foo', 10)->get()) { // 锁住这个key 10秒的时间 // 然后我们可以接着自己实际项目中的相关操作 Cache::lock('foo')->release();//一定要在结尾处释放锁,不然会导致别的并行或后续请求一直无法获取锁而停滞 }例如最常见我们在处理用户余额的时候需要用到锁utils工具中封装方法: /** * 获取一个原子锁 * @param string $name * @param int $seconds * @return Lock */ public static function acquireLock(string $name, int $seconds = 60): Lock { return Cache::lock($name, $seconds); } /** * 释放一个原子锁 * @param Lock $lock * @return void */ public static function releaseLock(Lock $lock): void { $released = optional($lock)->release(); if (!$released) { optional($lock)->forceRelease(); } }调用:/** * 增加用户余额 * @param int $userId * @param int $amountInCents * @param int $changeType * @param string $description * @return UserAccountBalance|null */ public function increaseUserBalance( int $userId, int $amountInCents, int $changeType, string $description = '', ): ?UserAccountBalance { $lock = Utils::acquireLock('user_balance_' . $userId); try { $lock->block(10); $balance = $this->getBalance($userId); if (empty($balance)) { $balance = $this->createBalance([ 'user_id' => $userId, 'total_balance_in_cents' => 0, 'withdrawn_balance_in_cents' => 0, 'remaining_balance_in_cents' => 0, ]); } if (empty($balance)) { throw new Exception('创建用户余额失败'); } if ($amountInCents == 0) { return $balance; } $change = $this->createBalanceChange([ 'user_id' => $userId, 'changed_amount_in_cents' => $amountInCents, 'change_type' => $changeType, 'change_detail' => ['description' => $description], ]); if (empty($change)) { throw new Exception('余额变更记录保存失败'); } $this->updateBalance($balance, [ 'total_balance_in_cents' => $balance->total_balance_in_cents + $amountInCents, 'remaining_balance_in_cents' => $balance->remaining_balance_in_cents + $amountInCents, ]); return $balance; } catch (Exception $error) { Log::error('用户余额更新失败', [ 'userId' => $userId, 'amount_in_cents' => $amountInCents, 'code' => $error->getCode(), 'message' => $error->getMessage(), 'file' => $error->getFile(), 'line' => $error->getLine(), ]); return null; } finally { Utils::releaseLock($lock); } }
查看详情点赞1评论收藏浏览332023-03-29 11:09:41Laravel 拖拽式建站中如何给字符串模板中传入数据并在视图中展示
问题:在我们网站开发中,会遇到这样的问题,我们渲染模板、生成静态页过程或者拖拽式建站中,如何给字符串模板中传入数据并在视图中展示问题?下面我测试了2中方法,一种是通过JS插入数据,另外一种是在后台程序中就把数据和模板处理好,统一给view渲染。目前用的后台框架是laravel,其实只要了解了思路,什么语言,什么框架都一样处理。1、后台程序处理Controller:public function index(Request $request){ $data = ["你好!","早晨","很高兴和你","相遇!"]; $html = '<ul class="ulSection">temple</ul>'; $li = ""; foreach ($data as $v){ $li .= '<li>'.$v.'</li>'; } $newHtml = str_replace("temple",$li,$html,$i); return view("index",compact("newHtml")); }View:<div>{!! $newHtml !!} </div>结果:网页源代码中:2、JS处理Controllerpublic function index(Request $request){ $data = [1,2,3,4]; $json_data = json_encode($data); $html = '<ul class="ulSection"></ul>'; return view("index",compact("json_data","html")); }View<head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>全球搜C端</title> <script src="http://www.alingfeng.cn/js/jquery.min.js"></script> </head> <body> <div>欢迎访问-全球搜C端-首页</div> <div>{!! $html !!} </div> </body>JS<script> const data = {{ $json_data }}; console.log(data); var ulSection = $(".ulSection"); var html = ''; for (var i= 0; i < data.length ; i++){ html += '<li>'+data[i]+'</li>'; } ulSection.html(html); </script>结果:网页源代码中:总结:由此可以看出,两种方法都能页面效果上达到效果。数据都成功放到html结构中。但是,做网站开发的都知道。我们开发网站不一定全是用来做SEM的,我们很多网站都会用来做SEO,特别是官网和移动端网站,所以我们要考虑到我们的网站是能够被搜索引擎爬取收录的。所以,我们最好用后台模板渲染,然后再把html输出到我们的页面中。
查看详情点赞1评论收藏浏览442023-05-18 11:26:56PHP Laravel框架blade模板无限级处理
我们在工作研发中,不论哪一门语言,前端还是后端,经常都会处理无限级数据或者模板的时候,例如菜单,分类数据无限级,模板无限极,Vue组件无限极等等。今天用到的是Laravel框架无限级blade模板处理。blade模板中引用一个无限级blade模板:<ul class="side-nav" data-module="6" data-unable="demo1-sidenav"> @if(!empty($nav)) @include('side_nav.product_side_nav', ['nav' => $nav]) @endif </ul>无限级blade模板product_side_nav.blade.php,这里需要注意的事,在这个模板里需要引入模板自己。@foreach($nav as $item) <li data-page="{{$item->route}}"><a href="/{{$item->route == 'index' ? '/' : $item->route}}">{{$item->title}}</a> @if(isset($item->_child) && !empty($item->_child)) <ul> @include('side_nav.product_side_nav', ['nav' => $item->_child]) </ul> @endif </li> @endforeach 现在就可以了。我们看一下实际效果:这里只建了三级菜单分类。
查看详情点赞1评论收藏浏览1832023-10-27 16:08:54laravel+layui后台文件上传到本地
上传图片PHP控制器//文件上传 public function upload(Request $request) { //上传文件最大大小,单位M $maxSize = 1; //支持的上传图片类型 $allowed_extensions = ["png", "jpg", "gif"]; //返回信息json $data = ['code'=>1, 'msg'=>'上传失败', 'data'=>'']; $file = $request->file('file'); $filename = $request->all('filename')['filename']; //检查文件是否上传完成 if ($file->isValid()){ //检测图片类型 $ext = $file->getClientOriginalExtension(); if (!in_array(strtolower($ext),$allowed_extensions)){ $data['msg'] = "请上传".implode(",",$allowed_extensions)."格式的图片"; return response()->json($data); } //检测图片大小 if ($file->getSize() > $maxSize*1024*1024){ $data['msg'] = "图片大小限制".$maxSize."M"; return response()->json($data); } }else{ $data['msg'] = $file->getErrorMessage(); return response()->json($data); } $year = date('Y'); $date = date('m-d'); $newFile = md5(uniqid()).".".$file->getClientOriginalExtension(); $disk = Storage::disk('uploads'); $res = $disk->put('/'.$filename.'/'.$year.'/'.$date.'/'.$newFile,file_get_contents($file->getRealPath())); if($res){ $data = [ 'code' => 0, 'msg' => '上传成功', 'data' => $newFile, 'url' => '/uploads/'.$filename.'/'.$year.'/'.$date.'/'.$newFile, ]; }else{ $data['data'] = $file->getErrorMessage(); } return response()->json($data); }js://普通图片上传 $(".uploadPic").each(function (index,elem) { upload.render({ elem: $(elem) ,url: '{{ route("api.upload") }}' ,multiple: false ,data:{"_token":"{{ csrf_token() }}","filename":'links'} ,done: function(res){ //如果上传失败 if(res.code == 0){ var _li = $(elem).parent('.layui-upload').find('.layui-upload-box .li_thumb_'+index+''); _li.show(); layer.msg(res.msg,{icon:1}); _li.html('<div><img title="点击删除" src="'+res.url+'" /></div><p>上传成功</p>'); $(elem).parent('.layui-upload').find('.thumb_'+index+'').val(res.url); }else { layer.msg(res.msg,{icon:2}); } } }); });html:<div class="layui-form-item"> <label for="" class="layui-form-label">缩略图</label> <div class="layui-input-block"> <div class="layui-upload"> <button type="button" class="layui-btn layui-btn-sm uploadPic"><i class="layui-icon"></i>图片上传</button> <div class="layui-upload-list" > <ul class="layui-upload-box layui-clear"> <li class="li_thumb_0" id="thumb_0" style="@if(isset($links->thumb)) display: block; @else display: none; @endif"><div><img title="点击删除" src="{{$links->thumb??old('thumb')}}" /></div><p>上传成功</p></li> </ul> <input type="hidden" name="thumb" class="layui-upload-input thumb_0" value="{{$links->thumb??old('thumb')}}"> </div> </div> </div> </div>
查看详情点赞评论收藏浏览202023-02-27 19:48:46laravel 连续where查询
laravel 连续查询:$data = $request->all('page_type','page_port','page_domian','is_promote'); $pagelist = PageList::where(function ($query) use ($data) { foreach ($data as $k => $v) { if ($k == 'page_type') { if (!empty($v)) { $query->where('page_type','=',$v); } }elseif ($k == 'page_port'){ if (!empty($v)) { $query->where('page_port','like','%'.$v.'%'); } }elseif ($k == 'page_domian'){ if (!empty($v)) { $query->where('page_domian','like','%'.$v.'%'); } }elseif ($k == 'is_promote'){ if (!empty($v)) { $query->where('is_promote', $v); } } } })->get()->toArray();
查看详情点赞评论收藏浏览412023-02-28 19:30:24Laravel 任务调度 ( Console )
在以前, 开发者需要为每一个需要调度的任务编写一个 Cron 条目, 这是很让人头疼的事. 你的任务调度不在源码控制中, 你必须使用 SSH 登录到服务器然后添加这些 Cron 条目. Laravel 命令调度器允许你平滑而又富有表现力地在 Laravel 中定义命令调度, 并且服务器上只需要一个 Cron 条目即可, 任务调度又是我们俗称的 “计划任务”。任务调度定义在app/Console/Kernel.php文件的schedule方法中,该方法中已经包含了一个示例。你可以自由地添加你需要的调度任务到Schedule对象开启调度//在linux环境中执行 * * * * * root php /var/www/laravel/artisan schedule:run/var/www/laravel为你的项目目录该 Cron 将会每分钟调用Laravel命令调度,然后,Laravel评估你的调度任务并运行到期的任务。定义调度在 项目根目录 下创建定时任务所需要进行的操作创建命令(Laravel 5.1):php artisan make:console Stat_Test创建命令(Laravel 5.3):php artisan make:command Stat_Test该操作会在app/Console/Commands下生成一个Stat_Test.php下面打开该文件 给大家展示一个简单而又完整的代码例子 <?php namespace App\Console\Commands; use Illuminate\Console\Command; class Stat_Test extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'stat:test'; /** * The console command description. * * @var string */ protected $description = 'stat:test'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { $this->addData(); } // 例子 public function addData() { $time = time(); $rand = rand(1, 1000); $id = \DB::table('data_test')->insertGetId(['uuid' => $time, 'uuid' => $rand]); if ($id) { \Log::info('定时/数据插入成功', $id); } else { \Log::error('定时/数据插入失败', $time); } } }值得注意的是 这个文件中的 $signature = 'stat:test' 这个签名在 Kernel.php 中也要相应用到, 下面是附上 Kernel.php 的完整代码<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ \App\Console\Commands\Inspire::class, '\App\Console\Commands\Stat_Test', ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // 为测试方便 每分钟执行一次 $schedule->command('stat:test')->everyMinute(); } }再强调一次 $schedule->command('stat:test') 里面的 stat:test 必须和上面的签名 $signature = 'stat:test' 对应上protected $commands = [ \App\Console\Commands\Inspire::class, '\App\Console\Commands\Stat_Test', ];也要把引入你的调度文件// 每周星期六11:00运行一次... $schedule->command('stat:test')->weekly()->saturdays()->at('11:00'); // 每周星期一:00运行一次... $schedule->command('stat:test')->weekly()->->mondays()->at('01:00');调度常用选项当然,你可以分配多种调度到任务->cron('* * * * *'); 在自定义 Cron 调度上运行任务 ->everyMinute(); 每分钟运行一次任务 ->everyFiveMinutes(); 每五分钟运行一次任务 ->everyTenMinutes(); 每十分钟运行一次任务 ->everyThirtyMinutes(); 每三十分钟运行一次任务 ->hourly(); 每小时运行一次任务 ->daily(); 每天凌晨零点运行任务 ->dailyAt('13:00'); 每天 13:00运行任务 ->twiceDaily(1, 13); 每天 1:00 & 13:00 运行任务 ->weekly(); 每周运行一次任务 ->monthly(); 每月运行一次任务下面是额外的调度约束列表:->weekdays(); 只在工作日运行任务 ->sundays(); 每个星期天运行任务 ->mondays(); 每个星期一运行任务 ->tuesdays(); 每个星期二运行任务 ->wednesdays(); 每个星期三运行任务 ->thursdays(); 每个星期四运行任务 ->fridays(); 每个星期五运行任务 ->saturdays(); 每个星期六运行任务 ->when(Closure); 基于特定测试运行任务原文出处: https://www.jianshu.com/p/91bbdf9ddbf5
查看详情点赞评论收藏浏览292023-03-29 13:46:48laravel任务调度定时任务时间设置
时间设置举例:$schedule->command(‘CommandTask’)->dailyAt("5:20");->cron(’* * * * * *’); //在自定义的 Cron 时间表上执行该任务 ->everyMinute(); //每分钟执行一次任务 ->everyFiveMinutes(); //每五分钟执行一次任务 ->everyTenMinutes(); //每十分钟执行一次任务 ->everyFifteenMinutes(); //每十五分钟执行一次任务 ->everyThirtyMinutes(); //每半小时执行一次任务 ->hourly(); //每小时执行一次任务 ->hourlyAt(18); //每小时的第 18 分钟执行一次任务 ->daily(); //每天午夜执行一次任务 ->dailyAt('13:00'); //每天的 13:00 执行一次任务 ->twiceDaily(2, 14); //每天的 2:00 和 14:00 分别执行一次任务 ->weekly(); //每周执行一次任务 ->monthly(); //每月执行一次任务 ->monthlyOn(5, '20:00'); //在每个月的第5天的 20:00 执行一次任务 ->quarterly(); //每季度执行一次任务 ->yearly(); //每年执行一次任务 ->timezone('America/New_York'); //设置时区
查看详情点赞评论收藏浏览452023-04-21 11:11:57