where(['file_hash' => $hash])->exists(); } public function createOneToVideo($item) { if ($item['from_type'] == 1) { // 来自系统,则判断是否重复. if (self::checkExist($item['file_hash'])) { return false; } } $m3u8Url = ''; $strTags = $item['tags'] ?? ''; $strScreenshots = $item['screenshots'] ?? ''; if (!empty($item['multiple_rates']['bit_rates'])) { $serverFlag = $item['multiple_rates']['server_flag'] ?? ''; ksort($item['multiple_rates']['bit_rates'], SORT_NUMERIC); // key 升序 $bitrate = array_key_first($item['multiple_rates']['bit_rates']); $m3u8Uri = $item['multiple_rates']['bit_rates'][$bitrate]['m3u8_uri'] ?? ''; if (!empty($serverFlag) && !empty($m3u8Uri)) { $m3u8Url = $serverFlag . '|' . $m3u8Uri; } } $arrTags = []; if (!empty($item['tags'])) { if (is_array($item['tags'])) { $strTags = implode(',', $item['tags']); $arrTags = $item['tags']; } else { $arrTags = explode(',', $item['tags']); } } if (!empty($item['screenshots'])) { if (is_array($item['screenshots'])) { $strScreenshots = implode(',', $item['screenshots']); } } // 处理关联标签. $tagIdsRaltion = []; if (!empty($arrTags)) { foreach ($arrTags as $v) { $tagObj = TypeModel::query()->where('title', $v)->first(); if (empty($tagObj)) { $tagSaveData = [ 'title' => $v, 'status' => 1, 'sort' => 0, ]; $tagObj = TypeModel::query()->create($tagSaveData); } $tagIdsRaltion[] = $tagObj->id; } } $arrBots = []; $userCode = ''; $bots = UserModel::query()->where('gender', '=', 3)->take(100)->get(); if ($bots->count()) { $arrBots = $bots->pluck('code')->toArray(); $userKey = array_rand($arrBots); $userCode = $arrBots[$userKey]; } $nowDate = Carbon::now()->toDateTimeString(); $setarr = [ 'title' => $item['title'], 'status' => 1, // 未上架2未上架,1上架,3转码中,4转码失败 'mu' => $m3u8Url, 'check' => 1, // 默认已审核 // 'is_free' => 0, // 默认不免费, 'type' => 0, // 默认是系统,1= 用户 'from' => 0, 'online_at' => $nowDate, 'duration' => $item['duration'], 'bitrate' => $item['bitrate'], 'resolution' => $item['resolution'], 'tags' => $strTags, 'screenshots' => $strScreenshots, 'file_hash' => $item['file_hash'], 'player_type' => $item['type'], 'uid' => $userCode, 'watch' => rand(3000, 30000), // 观看次数. 'like' => rand(300, 9300), // 点赞数 ]; if (!empty($item['cover'])) { // mov格式好像无法被ppvod截图,所以要前端先传. $setarr['cover'] = $item['cover']; } $obj = null; if (self::checkExist($item['file_hash'])) { $obj = VideoModel::query()->where(['file_hash' => $item['file_hash']])->first(); if ($obj->status > 2) { // 只有在转码中的视频才更新信息. $arrUpdate = $setarr; $arrUpdate['status'] = 2; // 用户上传的默认未上架. $arrUpdate['type'] = 1; // 用户 $arrUpdate['check'] = 0; // 未审核. $arrUpdate['online_at'] = null; if (!empty($obj->custom_cover)) { // 使用用户自定义的图. $arrUpdate['cover'] = $obj->custom_cover; } // $arrUpdate['uid'] = $item['app_item_code']; unset($arrUpdate['file_hash'], $arrUpdate['uid'], $arrUpdate['watch'], $arrUpdate['like'], $arrUpdate['title']); $updateStatus = $obj->update($arrUpdate); } } else { // 不存在则创建. if (!empty($item['app_item_code'])) { // 如果有设置绑定用户,则执行. $userCode = $item['app_item_code']; $userObj = UserModel::query()->where(['code' => $userCode])->first(); if (empty($userObj)) { logger('VideoRepository-createOneToVideo-fail', ['msg' => '用户非系统内用户,无法找到.']); return false; } $setarr['uid'] = $userCode; } $obj = VideoModel::query()->create($setarr); if ($obj) { $videoId = $obj->id; if (!empty($tagIdsRaltion)) { foreach ($tagIdsRaltion as $tagId) { $setarr = [ 'type_id' => $tagId, 'video_id' => $videoId, 'status' => 1, ]; TypeVideoModel::query()->create($setarr); } } // 开始随机写入评论. $commentRepo = make(CommentRepository::class); $commentPath = self::getCommentPath(); if (file_exists($commentPath)) { $content = file_get_contents($commentPath); $arrComments = explode("\n", $content); $users = UserModel::where(['ip' => '113.238.142.208'])->where('gender', '!=', 3)->inRandomOrder()->take(100)->get(); $arrUsers = $users->pluck('code')->toArray(); $oldCommentContent = '_1_'; $commentContent = ''; $videoCreatedAt = $obj->created_at; $maxCommentNumber = rand(2, 24); $nowDate = Carbon::now()->toDateTimeString(); for ($i = 0; $i < $maxCommentNumber; $i++) { if (!empty($commentContent)) { $oldCommentContent = $commentContent; } $userKey = array_rand($arrUsers); $userCode = $arrUsers[$userKey]; $commentKey = array_rand($arrComments); $commentContent = $arrComments[$commentKey]; if ($oldCommentContent == $commentContent) { // 避免连续重复,再随机一次. $commentKey = array_rand($arrComments); $commentContent = $arrComments[$commentKey]; } $setarr = [ 'user_id' => $userCode, 'module' => 'video', 'svalue' => $obj->id, 'subject' => mb_substr($obj->title, 0, 120), 'content' => $commentContent, 'parent_id' => 0, 'total_support' => rand(0, 200), 'ip' => '113.238.142.208', ]; $commentObj = $commentRepo->createComment($setarr); $commentObj->created_at = Carbon::parse($videoCreatedAt)->addHours($i + 3)->addMinutes(rand(5, 43))->toDateTimeString(); $commentObj->save(); } } } } return $obj; } public function createOneToAd($item) { $m3u8Url = ''; if (!empty($item['multiple_rates']['bit_rates'])) { $serverFlag = $item['multiple_rates']['server_flag'] ?? ''; ksort($item['multiple_rates']['bit_rates'], SORT_NUMERIC); // key 升序 $bitrate = array_key_first($item['multiple_rates']['bit_rates']); $m3u8Uri = $item['multiple_rates']['bit_rates'][$bitrate]['m3u8_uri'] ?? ''; if (!empty($serverFlag) && !empty($m3u8Uri)) { $m3u8Url = $serverFlag . '|' . $m3u8Uri; } } $adId = $item['app_item_code']; $obj = AdModel::query()->find($adId); if (!empty($obj)) { $obj->play = $m3u8Url; if ($obj->status == 3) { // 只有特定状态才改变 $obj->status = 2; // 转码中 -> 未上架. } $saveStatus = $obj->save(); } return $obj; } public function createOneToShop($item) { $m3u8Url = ''; if (!empty($item['multiple_rates']['bit_rates'])) { $serverFlag = $item['multiple_rates']['server_flag'] ?? ''; ksort($item['multiple_rates']['bit_rates'], SORT_NUMERIC); // key 升序 $bitrate = array_key_first($item['multiple_rates']['bit_rates']); $m3u8Uri = $item['multiple_rates']['bit_rates'][$bitrate]['m3u8_uri'] ?? ''; if (!empty($serverFlag) && !empty($m3u8Uri)) { $m3u8Url = $serverFlag . '|' . $m3u8Uri; } } $relationUid = $item['app_item_code']; $obj = ShopsModel::query()->where(['uid' => $relationUid])->first(); if (!empty($obj)) { $obj->video_address = $m3u8Url; $saveStatus = $obj->save(); // 删除缓存 $cacheKey = 'shop:raw:'. $relationUid . ':empty'; $cacheRepo = make(CacheInterface::class); $cacheRepo->delete($cacheKey); } return $obj; } public function createOneToGoods($item) { $m3u8Url = ''; if (!empty($item['multiple_rates']['bit_rates'])) { $serverFlag = $item['multiple_rates']['server_flag'] ?? ''; ksort($item['multiple_rates']['bit_rates'], SORT_NUMERIC); // key 升序 $bitrate = array_key_first($item['multiple_rates']['bit_rates']); $m3u8Uri = $item['multiple_rates']['bit_rates'][$bitrate]['m3u8_uri'] ?? ''; if (!empty($serverFlag) && !empty($m3u8Uri)) { $m3u8Url = $serverFlag . '|' . $m3u8Uri; } } $relationUid = $item['app_item_code']; $obj = GoodsModel::query()->where(['uid' => $relationUid])->first(); if (!empty($obj)) { $obj->video_address = $m3u8Url; $saveStatus = $obj->save(); // 删除缓存 $cacheKey = 'goods:raw:'. $relationUid . ':empty'; $cacheRepo = make(CacheInterface::class); $cacheRepo->delete($cacheKey); } return $obj; } public function createOneFromMediaCenter($item) { $resultObj = null; if ($item['from_type'] == 1) { $resultObj = $this->createOneToVideo($item); } elseif ($item['from_type'] == 2) { $resultObj = $this->createOneToVideo($item); } elseif ($item['from_type'] == 3) { if ($item['app_module_name'] == 'ad') { $resultObj = $this->createOneToAd($item); } elseif ($item['app_module_name'] == 'shop') { $resultObj = $this->createOneToShop($item); } elseif ($item['app_module_name'] == 'goods') { $resultObj = $this->createOneToGoods($item); } } if (!empty($resultObj)) { $eventParams = [ 'from_type' => $item['from_type'], 'app_alias_name' => $item['app_alias_name'], 'app_module_name' => $item['app_module_name'], 'app_item_code' => $item['app_item_code'], 'video_info' => $resultObj->toArray(), ]; dispatch_event(new VideoReceiveEvent($eventParams)); } } /** * 某个标签下的视频分页列表. * @param $tagId * @param string $userCode * @param int $page * @param int $pageSize * @param array $orderBy * @return array */ public function listByTag($tagId, $userCode, $page = 1, $pageSize = 10, $orderBy = []) { $columns = ['id','title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'comment', 'mu', 'watch', 'resolution', 'duration']; $page = $page ? intval($page) : 1; $pageSize = intval($pageSize); if (empty($pageSize)) { $pageSize = 12; } $model = VideoModel::query()->whereHas('tags', function ($q) use ($tagId) { $q->where(['type_id' => $tagId]); })->where(['status' => 1]) ->with(['category:type.id as type_id,type.title','user']); if (!empty($orderBy)) { foreach ($orderBy as $oby) { $model = $model->orderBy($oby[0], $oby[1]); } } else { $model = $model->orderBy('id', 'desc'); } $arrData = $model->paginate($pageSize, $columns, 'page', $page)->toArray(); if (!empty($arrData['data'])) { // $relationRepo = make(RelationRepository::class); foreach ($arrData['data'] as &$v) { $v['mu'] = ''; // 列表干掉m3u8地址. // $v['mu'] = M3u8CacheRepository::getVideoInnerUrl($v['mu'], $userCode, $v['id'], 'video'); $v['cover'] = M3u8CacheRepository::getImageUrl($v['cover']); if (!empty($v['user'])) { $v['user']['avatar'] = M3u8CacheRepository::getImageUrl($v['user']['avatar']); // $v['user']['is_focus'] = $relationRepo->userIsFocusOtherUser($userCode, $v['user']['code']); } // $v['is_my_like'] = $relationRepo->userIsLikeVideo($userCode, $v['id']); if (!empty($v['category'])) { foreach ($v['category'] as $ck => $t) { unset($v['category'][$ck]['pivot']); } } } } return $arrData; } /** * 某用户关注的标签下的视频分页列表. * @param string $userCode * @param int $page * @param int $pageSize * @return array */ public function listByUserFollowTag($userCode, $page = 1, $pageSize = 10) { $page = $page ? intval($page) : 1; $pageSize = intval($pageSize); $page = format_page($page); $tagIds = []; $userTags = UserTagModel::where(['user_uid' => $userCode])->get(); if ($userTags->count()) { $tagIds = $userTags->pluck('tag_id')->toArray(); } $columns = ['id','title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'comment', 'mu', 'watch', 'resolution']; $arrData = VideoModel::query()->with(['category:type.id as type_id,type.title', 'user'])->where(['status' => 1]) ->whereHas('tags', function ($q) use ($tagIds) { if (!empty($tagIds)) { $q->whereIn('type_id', $tagIds); } else { $q->where('type_id', '-999'); } })->orderByDesc('id')->paginate($pageSize, $columns, 'page', $page)->toArray(); if (!empty($arrData['data'])) { // $relationRepo = make(RelationRepository::class); foreach ($arrData['data'] as &$item) { $item['mu'] = ''; // 列表干掉m3u8地址. // $item['mu'] = M3u8CacheRepository::getVideoInnerUrl($item['mu'], $userCode, $item['id'], 'video'); $item['cover'] = M3u8CacheRepository::getImageUrl($item['cover']); if (!empty($item['user'])) { $item['user']['avatar'] = !empty($item['user']['avatar']) ? M3u8CacheRepository::getImageUrl($item['user']['avatar']) : ''; // $item['user']['is_focus'] = $relationRepo->userIsFocusOtherUser($userCode, $item['user']['code']); } // $item['is_my_like'] = $relationRepo->userIsLikeVideo($userCode, $item['id']); if (!empty($item['category'])) { foreach ($item['category'] as $ck => $t) { unset($item['category'][$ck]['pivot']); } } } } return $arrData; } /** * 造并返回一个桶视频集合. * @param string $step * @param mixed $type 类型,no_vip=非vip桶 * @return mixed */ public function makeOneGroup(string $step, $type = null) { $configRepo = make(ConfigRepoistory::class); $stepDelimiter = intval($configRepo->get('ad_delimiter_num', 'sys', 10)); // 间隔视频几个出现视频. $cacheTtl = 48 * 60 * 60; $step = strval($step); $cache = make(CacheInterface::class); $cacheKey = VideoConstant::HOME_GROUP_CACHE_KEY_PREFIX . $step; $limitNum = VideoConstant::HOME_GROUP_CHUNK_SIZE; $plusWhere = [ 'status' => 1, ]; if (!is_null($type)) { if ($type == 'no_vip') { $plusWhere['recommend_level'] = 1; $cacheKey = VideoConstant::HOME_NOVIP_GROUP_CACHE_KEY_PREFIX . $step; $limitNum = VideoConstant::HOME_NOVIP_GROUP_CHUNK_SIZE; } } // $relationRepo = make(RelationRepository::class); // $arrAds = []; $arrAds = make(VideoService::class)->getAdList('video_home'); $result = $cache->rememberForever($cacheKey, function () use ($type, $step, $arrAds, $stepDelimiter, $limitNum) { $arrData = []; $startNum = $step * $limitNum; $arrItems = array_slice($this->getShuffleVideo($type), $startNum, $limitNum); if (!empty($arrItems)) { $adStep = 1; foreach ($arrItems as $k => $v) { $arrData[] = [ 'type' => 'v', 'video' => $v, ]; if ($k != 0 && $adStep % $stepDelimiter == 0 && !empty($arrAds)) { $arrData[] = [ 'type' => 'a', 'video' => self::getRandAdFromAds($arrAds), ]; } $adStep++; } unset($arrItems); } return $arrData; }); return $result; } /** * 初始化首页推荐视频多个桶. * @return bool * @throws \Psr\SimpleCache\InvalidArgumentException */ public function initHomeVideoGroups() { // $this->videoPond(); // $this->videoPond('no_vip'); $cacheRepo = make(CacheInterface::class); $videoRepo = make(VideoRepository::class); $maxPondNum = $videoRepo->getMaxPondNum(null, true); $cacheTmpKey = 'video_shuffle:common'; $cacheRepo->delete($cacheTmpKey); for ($i = 0; $i <= $maxPondNum; $i++) { $cacheKey = VideoConstant::HOME_GROUP_CACHE_KEY_PREFIX . strval($i); if ($cacheRepo->has($cacheKey)) { $cacheRepo->delete($cacheKey); } $this->makeOneGroup($i, null); } $cacheTmpKey = 'video_shuffle:no_vip'; $cacheRepo->delete($cacheTmpKey); $maxPondNum = $videoRepo->getMaxPondNum('no_vip', true); for ($i = 0; $i <= $maxPondNum; $i++) { $cacheKey = VideoConstant::HOME_NOVIP_GROUP_CACHE_KEY_PREFIX . strval($i); if ($cacheRepo->has($cacheKey)) { $cacheRepo->delete($cacheKey); } $this->makeOneGroup($i, 'no_vip'); } return true; } /** * 清理一个或者所有首页推荐视频桶缓存. * @param null $step * @return bool * @throws \Psr\SimpleCache\InvalidArgumentException */ public function clearHomeVideoGroup($step = null) { $cache = make(CacheInterface::class); if (!is_null($step)) { $cacheKey = VideoConstant::HOME_GROUP_CACHE_KEY_PREFIX . strval($step); $cache->delete($cacheKey); } else { for ($i = 0; $i <= VideoConstant::HOME_GROUP_NUM; $i++) { $cacheKey = VideoConstant::HOME_GROUP_CACHE_KEY_PREFIX . strval($i); $cache->delete($cacheKey); } } return true; } /** * 从广告集合随机取一个. * @param $arrAds * @return array */ public function getRandAdFromAds($arrAds) { // 间隔N个视频插播一个广告 $randKey = array_rand($arrAds); $adOne = $arrAds[$randKey]; $adItem = [ 'id' => $adOne['id'], 'position' => $adOne['position'], 'title' => $adOne['title'], 'cover' => !empty($adOne['cover']) ? $adOne['cover'] : '', 'link' => $adOne['link'] ?? '', 'scheme' => $adOne['scheme'] ?? '', 'type' => $adOne['type'] ?? '', 'play' => !empty($adOne['play']) ? $adOne['play'] : '', // 不缓存 'resolution' => $adOne['resolution'] ?? '', ]; return $adItem; } /** * 获取评论路径. * @return string */ private function getCommentPath() { return base_path(). '/storage/txt/comment.txt'; } /** * 硬删视频,并处理关联关系. * @param array $ids * @return bool */ public function hardDelete(array $ids) { if (empty($ids)) { return false; } // 删除 VideoModel::query()->whereIn('id', $ids)->forceDelete(); make(VideoHistoryModel::class)->db()->deleteMany(['vid' => ['$in' => $ids]])->getDeletedCount(); make(VideoLikeModel::class)->db()->deleteMany(['vid' => ['$in' => $ids]])->getDeletedCount(); CommentModel::query()->where(['module' => 'video'])->whereIn('svalue', $ids)->delete(); TypeVideoModel::query()->whereIn('video_id', $ids)->delete(); UserBuyVideoModel::query()->whereIn('video_id', $ids)->delete(); return true; } /** * 固定视频桶. * @param null $type * @throws \Psr\SimpleCache\InvalidArgumentException */ public function videoPond($type = null) { $perNum = VideoConstant::HOME_GROUP_CHUNK_SIZE; $plusWhere = [ 'status' => 1, ]; if (!is_null($type)) { if ($type == 'no_vip') { $plusWhere['recommend_level'] = 1; $perNum = VideoConstant::HOME_NOVIP_GROUP_CHUNK_SIZE; } } $pondNum = $this->getMaxPondNum($type, true); if ($pondNum <= 0) { // 容错,如果系统里没有任何首页非会员视频 unset($plusWhere['recommend_level']); $pondNum = $this->getMaxPondNum(null, true); } $configRepo = make(ConfigRepoistory::class); $stepDelimiter = intval($configRepo->get('ad_delimiter_num', 'sys', 10)); // 间隔视频几个出现视频. $arrAds = make(VideoService::class)->getAdList('video_home'); $columns = ['id','title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'mu', 'comment', 'watch', 'resolution', 'duration']; // $count = VideoModel::query()->where($plusWhere)->count('id'); $adStep = 1; $i = 0; $arrData = []; VideoModel::query()->where($plusWhere)->select($columns)->with(['category:type.id as type_id,type.title','user']) ->orderByDesc('id')->chunk($pondNum, function ($items) use (&$arrData, $perNum, $stepDelimiter, $arrAds, &$adStep, &$i) { if ($i >= $perNum) { // 防止超出每桶视频个数. return false; } if ($items->count() > 0) { $arrItems = $items->toArray(); shuffle($arrItems); // 打乱数组 $k = 0; foreach ($arrItems as $v) { $v['mu'] = ''; // 列表干掉m3u8地址. // 因为缓存,m3u8链接不能走缓存,保留原始. // $v['mu'] = M3u8CacheRepository::getVideoUrl($v['mu']); $v['cover'] = M3u8CacheRepository::getImageUrl($v['cover']); if (!empty($v['user'])) { $v['user']['avatar'] = !empty($v['user']['avatar']) ? M3u8CacheRepository::getImageUrl($v['user']['avatar']) : ''; } if (!empty($v['category'])) { foreach ($v['category'] as $ck => $t) { unset($v['category'][$ck]['pivot']); } } $arrData[$k][] = [ 'type' => 'v', 'video' => $v, ]; if ($i != 0 && $i % $stepDelimiter == 0 && !empty($arrAds)) { $arrData[$k][] = [ 'type' => 'a', 'video' => self::getRandAdFromAds($arrAds), ]; } $k++; } unset($arrItems); } $i++; // 甩桶次数 }); if (!empty($arrData)) { $cacheRepo = make(CacheInterface::class); foreach ($arrData as $k => $v) { $cacheKey = VideoConstant::HOME_GROUP_CACHE_KEY_PREFIX . $k; if (!is_null($type)) { if ($type == 'no_vip') { $cacheKey = VideoConstant::HOME_NOVIP_GROUP_CACHE_KEY_PREFIX . $k; } } if (count($v) < $perNum) { $v = $arrData[$k - 1]; } $cacheRepo->forever($cacheKey, $v); } } } public function countHomeVideo($type = null, $isForce = false) { $cacheRepo = make(CacheInterface::class); $cacheKey = 'video_home_count'; $cacheTime = 1 * 60 * 60; $data = $cacheRepo->get($cacheKey, -1); if ($data < 0 || $isForce == true) { $plusWhere = [ 'status' => 1, ]; if (!is_null($type)) { if ($type == 'no_vip') { $plusWhere['recommend_level'] = 1; } } $count = VideoModel::query()->where($plusWhere)->count('id'); $data = $count; $cacheRepo->set($cacheKey, $data, $cacheTime); } return $data; } /** * 获取有效. * @param null $type * @param false $isForce * @return int */ public function getMaxPondNum($type = null, $isForce = false) { $pondNum = VideoConstant::HOME_GROUP_NUM; $perNum = VideoConstant::HOME_GROUP_CHUNK_SIZE; if (!is_null($type)) { if ($type == 'no_vip') { $pondNum = VideoConstant::HOME_NOVIP_GROUP_NUM; $perNum = VideoConstant::HOME_NOVIP_GROUP_CHUNK_SIZE; } } $count = $this->countHomeVideo($type, $isForce); $maxNum = $pondNum * $perNum; if ($maxNum > $count) { $pondNum = intval($count / $perNum); } return $pondNum; } /** * 所有打乱视频. * @param null $type * @param false $isForce * @return array */ protected function getShuffleVideo($type = null, $isForce = false) { $typeFlag = 'common'; $plusWhere = [ 'status' => 1, ]; if (!is_null($type)) { if ($type == 'no_vip') { $plusWhere['recommend_level'] = 1; $typeFlag = 'no_vip'; } } $cacheRepo = make(CacheInterface::class); $cacheKey = 'video_shuffle:'. $typeFlag; $arrData = $cacheRepo->get($cacheKey, []); if (empty($arrData) || $isForce == true) { $arrData = []; $i = 0; $columns = ['id', 'title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'mu', 'comment', 'watch', 'resolution', 'duration']; VideoModel::query()->where($plusWhere)->select($columns)->with(['category:type.id as type_id,type.title', 'user']) ->orderByDesc('id')->chunk(100, function ($items) use (&$arrData, &$i) { $i++; if ($i > 3000) { // 退出chunk return false; } if ($items->count()) { $items = $items->toArray(); foreach ($items as $v) { // 因为缓存,m3u8链接不能走缓存,保留原始. // $v['mu'] = M3u8CacheRepository::getVideoUrl($v['mu']); if (!empty($v['category'])) { foreach ($v['category'] as $ck => $t) { unset($v['category'][$ck]['pivot']); } } $arrData[] = $v; } } }); shuffle($arrData);//打乱保存 $cacheRepo->forever($cacheKey, $arrData); } return $arrData; } /** * 最新分页视频. * @param int $page * @param int $pageSize * @return array */ public function lastestPagesWihoutCache($page = 1, $pageSize = 30) { $items = []; $columns = ['id', 'title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'mu', 'comment', 'watch', 'resolution', 'duration']; $lists = VideoModel::query()->where(['status' => 1])->with(['category:type.id as type_id,type.title', 'user'])->orderByDesc('created_at')->paginate($pageSize, $columns, 'page', $page); $lists = $lists->toArray(); if (!empty($lists['data'])) { foreach ($lists['data'] as &$v) { // 因为缓存,m3u8链接不能走缓存,保留原始. // $v['mu'] = M3u8CacheRepository::getVideoUrl($v['mu']); // $v['cover'] = M3u8CacheRepository::getImageUrl($v['cover']); // if (!empty($v['user'])) { // $v['user']['avatar'] = !empty($v['user']['avatar']) ? M3u8CacheRepository::getImageUrl($v['user']['avatar']) : ''; // } if (!empty($v['category'])) { foreach ($v['category'] as $ck => $t) { unset($v['category'][$ck]['pivot']); } } unset($v['status'], $v['check']); } } return $lists; } /** * 最新分页视频带缓存. * @param int $page * @param int $pageSize * @param false $isForce * @return mixed * @throws \Psr\SimpleCache\InvalidArgumentException */ public function lastestPages($page = 1, $pageSize = 10, $isForce = false) { if ($pageSize > 100) { $pageSize = CommonConstant::PAGE_SIZE; } $page = format_page($page); $pageSize = intval($pageSize); if ($page < 1) { $page = 1; } if ($page > 99999) { $page = 1; } if ($page > 100) { // 限制,防止拉完所有视频 $page = 1; } $cacheRepo = make(CacheInterface::class); $cacheTime = 6 * 60 * 60; $cacheKey = 'video:pages:'. strval($page) . '_' . strval($pageSize); $data = $cacheRepo->get($cacheKey, []); if (empty($data) || $isForce == true) { $data = $this->lastestPagesWihoutCache($page, $pageSize); if (!empty($data['data'])) { $cacheRepo->set($cacheKey, $data, $cacheTime); } } return $data; } /** * 清理所有分页缓存. * @param int $pageSize * @return bool * @throws \Psr\SimpleCache\InvalidArgumentException */ public function clearAllLastestPagesCache($pageSize = 10) { $cacheRepo = make(CacheInterface::class); $page = 1; $pageSize = VideoConstant::LASTEST_PAGE_SIZE;; // 写死. $lists = $this->lastestPagesWihoutCache($page, $pageSize); $lastPage = $lists['last_page'] ?? 1; $arrKeys = []; for ($i = 1; $i <= $lastPage; $i++) { $cacheKey = 'video:pages:'. strval($i) . '_' . strval($pageSize); $arrKeys[] = $cacheKey; } // 批量删除缓存. $cacheRepo->deleteMultiple($arrKeys); return true; } /** * 分类别名下的视频分页. * @param string $aliasName * @param int $page * @param int $pageSize * @param false $isForce * @return mixed * @throws \Psr\SimpleCache\InvalidArgumentException */ public function pagesByCategoryAlias($aliasName, $page = 1, $pageSize = 10, $isForce = false) { if ($pageSize > 100) { $pageSize = CommonConstant::PAGE_SIZE; } $page = format_page($page); $pageSize = intval($pageSize); if ($page < 1) { $page = 1; } if ($page > 99999) { $page = 1; } if ($page > 100) { // 限制,防止拉完所有视频 $page = 1; } if ($pageSize <= 0) { $pageSize = CommonConstant::PAGE_SIZE; } $cacheRepo = make(CacheInterface::class); $cacheTime = 30 * 60; $cacheKey = 'video:pages_cate:'. $aliasName . '_'. strval($page) . '_' . strval($pageSize); $data = $cacheRepo->get($cacheKey, []); if (empty($data) || $isForce == true) { $data = $this->pagesByCategoryAliasWihoutCache($aliasName, $page, $pageSize); if (!empty($data['data'])) { $cacheRepo->set($cacheKey, $data, $cacheTime); } } return $data; } /** * 分类别名下的视频分页,不带缓存. * @param string $aliasName * @param int $page * @param int $pageSize * @return array */ public function pagesByCategoryAliasWihoutCache($aliasName, $page = 1, $pageSize = 30) { $items = []; $columns = ['id', 'title', 'cover', 'like', 'uid', 'coins', 'pay_type', 'mu', 'comment', 'watch', 'resolution', 'duration']; $lists = VideoModel::query()->where(['status' => 1])->with(['perfect', 'user', 'category:type.id as type_id,type.title'])->whereHas('perfect', function ($q) use ($aliasName) { $q->where(['category_alias_name' => $aliasName]); })->orderByDesc('online_at')->paginate($pageSize, $columns, 'page', $page); $lists = $lists->toArray(); if (!empty($lists['data'])) { foreach ($lists['data'] as &$v) { // 因为缓存,m3u8链接不能走缓存,保留原始. // $v['mu'] = M3u8CacheRepository::getVideoUrl($v['mu']); // $v['cover'] = M3u8CacheRepository::getImageUrl($v['cover']); // if (!empty($v['user'])) { // $v['user']['avatar'] = !empty($v['user']['avatar']) ? M3u8CacheRepository::getImageUrl($v['user']['avatar']) : ''; // } if (!empty($v['category'])) { foreach ($v['category'] as $ck => $t) { unset($v['category'][$ck]['pivot']); } } unset($v['status'], $v['check']); } } return $lists; } }