This commit is contained in:
f4ilji
2025-01-15 15:31:37 +05:00
parent 45e73e27a0
commit bad611eb84
27 changed files with 815 additions and 124 deletions
+71 -48
View File
@@ -28,82 +28,103 @@ class ClientPostController extends Controller
{
public function index(Request $request)
{
$tagIds = DB::table('taggables')
->distinct()
->select('tag_id')
->where('taggable_type', Post::class)
->get()
->pluck('tag_id');
// Кешируем список тегов
$tagIds = Cache::remember('tag_ids', now()->addHours(1), function () {
return DB::table('taggables')
->distinct()
->select('tag_id')
->where('taggable_type', Post::class)
->get()
->pluck('tag_id');
});
$tags = \Spatie\Tags\Tag::whereIn('id', $tagIds)->get();
$posts = ClientPostListResource::collection(Post::query()
->with('category')
->select('title', 'slug', 'authors', 'category_id', 'preview', 'search_data', 'publish_at')
->where('status', '=', 'published')
->where('publish_at', '<', Carbon::now())
->when(request()->input('search'), function ($query, $search) {
$query->whereRaw('LOWER(title) like ?', ["%".strtolower($search)."%"]);
})
->when(request()->input('category'), function ($query) {
$slugs = request()->input('category');
if (is_array($slugs)) {
$query->whereHas('category', function ($query) use ($slugs) {
$query->whereIn('slug', $slugs);
});
}
})
->when(request()->input('tag'), function ($query, $slugs) {
if (is_array($slugs)) {
return $query->withAnyTags($slugs);
}
// Кешируем теги
$tags = Cache::remember('tags', now()->addHours(1), function () use ($tagIds) {
return \Spatie\Tags\Tag::whereIn('id', $tagIds)->get();
});
$slugsArray = explode(',', $slugs);
return $query->withAnyTags($slugsArray);
})
->orderBy('publish_at', request()->input('sort', 'desc'))
// Кешируем посты с учетом фильтров
$cacheKey = 'posts_' . md5(serialize($request->all()));
$posts = Cache::remember($cacheKey, now()->addHours(1), function () use ($request) {
return ClientPostListResource::collection(Post::query()
->with('category')
->select('title', 'slug', 'authors', 'category_id', 'preview', 'search_data', 'publish_at')
->where('status', '=', 'published')
->where('publish_at', '<', Carbon::now())
->when($request->input('search'), function ($query, $search) {
$query->whereRaw('LOWER(title) like ?', ["%".strtolower($search)."%"]);
})
->when($request->input('category'), function ($query) use ($request) {
$slugs = $request->input('category');
if (is_array($slugs)) {
$query->whereHas('category', function ($query) use ($slugs) {
$query->whereIn('slug', $slugs);
});
}
})
->when($request->input('tag'), function ($query, $slugs) {
if (is_array($slugs)) {
return $query->withAnyTags($slugs);
}
->paginate(6)
->withQueryString());
$slugsArray = explode(',', $slugs);
return $query->withAnyTags($slugsArray);
})
->orderBy('publish_at', $request->input('sort', 'desc'))
->paginate(6)
->withQueryString());
});
$categories = CategoryResource::collection(Category::has('posts')->get());
// Кешируем категории
$categories = Cache::remember('categories', now()->addHours(48), function () {
return CategoryResource::collection(Category::has('posts')->get());
});
// Кешируем контент категорий
$categoriesContent = [];
if (request()->input('category')) {
foreach (request()->input('category') as $item) {
$categoriesContent[$item] = new CategoryResource(Category::where('slug', $item)->first());
if ($request->input('category')) {
foreach ($request->input('category') as $item) {
$cacheKey = 'category_content_' . $item;
$categoriesContent[$item] = Cache::remember($cacheKey, now()->addHours(1), function () use ($item) {
return new CategoryResource(Category::where('slug', $item)->first());
});
}
}
// Кешируем контент тегов
$tagsContent = [];
if (request()->input('tag')) {
foreach (request()->input('tag') as $item) {
$tagsContent[$item] = new ClientTagResource(DB::table('tags')
->where(DB::raw("JSON_UNQUOTE(JSON_EXTRACT(slug, '$.ru'))"), $item)
->first());
if ($request->input('tag')) {
foreach ($request->input('tag') as $item) {
$cacheKey = 'tag_content_' . $item;
$tagsContent[$item] = Cache::remember($cacheKey, now()->addHours(1), function () use ($item) {
return new ClientTagResource(DB::table('tags')
->where(DB::raw("JSON_UNQUOTE(JSON_EXTRACT(slug, '$.ru'))"), $item)
->first());
});
}
}
$filters = [
'search_filter' => [
'type' => 'search',
'value' => request()->input('search'),
'value' => $request->input('search'),
'param' => 'search'
],
'category_filter' => [
'type' => 'category',
'value' => request()->input('category'),
'value' => $request->input('category'),
'param' => 'category',
'content' => $categoriesContent,
],
'tag_filter' => [
'type' => 'tag',
'value' => request()->input('tag'),
'value' => $request->input('tag'),
'param' => 'tag',
'content' => $tagsContent
],
'sortingBy_filter' => [
'type' => 'sort',
'value' => request()->input('sort'),
'value' => $request->input('sort'),
'param' => 'sort',
],
];
@@ -111,7 +132,10 @@ class ClientPostController extends Controller
$routeUrl = route('client.post.index');
$path = ltrim(parse_url($routeUrl, PHP_URL_PATH), '/');
$page = Page::where('path', '=', $path)->with('section.pages.section', 'section.mainSection')->first();
// Кешируем страницу
$page = Cache::remember('page_' . $path, now()->addHours(1), function () use ($path) {
return Page::where('path', '=', $path)->with('section.pages.section', 'section.mainSection')->first();
});
if (isset($page->section)) {
$breadcrumbs = [
@@ -123,7 +147,6 @@ class ClientPostController extends Controller
$breadcrumbs = null;
}
return Inertia::render('Client/Posts/Index', compact('filters', 'posts', 'categories', 'tags', 'breadcrumbs'));
}
@@ -29,9 +29,6 @@ class ClientWidgetFormController extends Controller
$messages = $this->generateValidationMessages($data['columns']);
$validateData = Validator::make($request->all(), $rules, $messages);
@@ -6,14 +6,21 @@ use App\Http\Resources\ClientPageNavigateResource;
use App\Http\Resources\PageResource;
use App\Models\Page;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class ClientWidgetPageController extends Controller
{
public function single(int $id)
{
$page = Page::query()
->with('section')
->find($id);
$cacheKey = 'page_' . md5($id);
// Пытаемся получить данные из кеша
$page = Cache::remember($cacheKey, now()->addHours(1), function () use ($id) {
return Page::where('id', '=', $id)
->with('section.pages.section', 'section.mainSection')
->first();
});
if (isset($page->section)) {
$breadcrumbs = [
'mainSection' => $page->section->mainSection->title,
@@ -7,27 +7,40 @@ use App\Http\Resources\ClientPostListResource;
use App\Http\Resources\PostThumbnailResource;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class ClientWidgetPostController extends Controller
{
public function index()
{
return PostThumbnailResource::collection(
Post::query()
->where('status', PostStatus::PUBLISHED)
->when(request()->input('category'), function ($query, $category_id) {
$query->where('category_id', $category_id);
})
->with('category')
->orderBy('publish_at', 'desc')
->take(request()->input('count', 5))
->get());
$category_id = request()->input('category');
$count = request()->input('count', 5);
$cacheKey = 'posts_' . $category_id . '_' . $count;
return Cache::remember($cacheKey, now()->addMinutes(10), function () use ($category_id, $count) {
return PostThumbnailResource::collection(
Post::query()
->where('status', PostStatus::PUBLISHED)
->when($category_id, function ($query, $category_id) {
$query->where('category_id', $category_id);
})
->with('category')
->orderBy('publish_at', 'desc')
->take($count)
->get()
);
});
}
public function single(int $id)
{
return new PostThumbnailResource(
Post::query()->with('category')->find($id)
);
$cacheKey = 'post_' . $id;
return Cache::remember($cacheKey, now()->addMinutes(10), function () use ($id) {
return new PostThumbnailResource(
Post::query()->with('category')->find($id)
);
});
}
}
@@ -0,0 +1,57 @@
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
class ImportUserController extends Controller
{
public function index()
{
return User::query()->whereHas('userDetail')->with('userDetail')->get();
}
public function test()
{
$response = Http::get('http://crawdad-fresh-bream.ngrok-free.app/api/import/users/')->object();
foreach ($response as $user) {
$userDetail = $user->user_detail;
unset($user->user_detail);
$user = User::create([
'name' => $user->name,
'slug' => $user->slug,
'email' => $user->email,
'email_verified_at' => $user->email_verified_at,
'password' => Md5(Str::random(15)),
'remember_token' => null,
'created_at' => $user->created_at,
'updated_at' => $user->updated_at,
]);
$user->userDetail()->create([
'user_id' => $user->id,
'is_only_worker' => $userDetail->is_only_worker,
'photo' => $userDetail->photo,
'academicTitle' => $userDetail->academicTitle,
'AcademicDegree' => $userDetail->AcademicDegree,
'education' => $userDetail->education,
'awards' => $userDetail->awards,
'professDisciplines' => $userDetail->professDisciplines,
'professionalRetraining' => $userDetail->professionalRetraining,
'professionalDevelopment' => $userDetail->professionalDevelopment,
'workExperience' => $userDetail->workExperience,
'attendedConferences' => $userDetail->attendedConferences,
'participationScienceProjects' => $userDetail->participationScienceProjects,
'publications' => $userDetail->publications,
'contactEmail' => $userDetail->contactEmail,
'contactPhone' => $userDetail->contactPhone,
'search_data' => $userDetail->search_data,
'other' => $userDetail->other,
'created_at' => $userDetail->created_at,
'updated_at' => $userDetail->updated_at,
]);
}
}
}
+2 -2
View File
@@ -22,13 +22,13 @@ use Inertia\Inertia;
class PageController extends Controller
{
public function render($path)
public function render(Request $request, $path)
{
// Генерируем уникальный ключ для кеширования
$cacheKey = 'page_' . md5($path);
// Пытаемся получить данные из кеша
$page = Cache::remember($cacheKey, now()->addHours(1), function () use ($path) {
$page = Cache::remember($cacheKey, now()->addHours(48), function () use ($path) {
return Page::where('path', '=', $path)
->with('section.pages.section', 'section.mainSection')
->first();
+4
View File
@@ -3,6 +3,7 @@
namespace App\Http;
use App\Http\Middleware\AccessCheck;
use App\Http\Middleware\InternalRequestOnly;
use App\Http\Middleware\RateLimitCheckMiddleware;
use App\Http\Middleware\RateLimitCounterMiddleware;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
@@ -81,5 +82,8 @@ class Kernel extends HttpKernel
'access-check' => AccessCheck::class,
'rate.limited.counter' => RateLimitCounterMiddleware::class,
'rate.limited.check' => RateLimitCheckMiddleware::class,
'ensure.browser' => InternalRequestOnly::class,
'superadmin' => \App\Http\Middleware\EnsureUserIsSuperadmin::class,
);
}
@@ -0,0 +1,26 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class EnsureUserIsSuperadmin
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next)
{
// Проверяем, что пользователь аутентифицирован и имеет роль superadmin
if (!Auth::check() || !Auth::user()->hasRole('super_admin')) {
return response('Access denied. You do not have permission to access this route.', 403);
}
return $next($request);
}
}
@@ -0,0 +1,36 @@
<?php
namespace App\Http\Middleware;
use App\Http\Resources\ClientBreadcrumbPage;
use App\Http\Resources\ClientBreadcrumbSection;
use App\Http\Resources\ClientBreadcrumbSubSection;
use App\Models\Page;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class GenerateBreadcrumbs
{
public function handle(Request $request, Closure $next)
{
$path = $request->path();
$page = Page::where('path', '=', $path)
->with('section.pages.section', 'section.mainSection')
->first();
if ($page && isset($page->section)) {
$breadcrumbs = [
'mainSection' => new ClientBreadcrumbSection($page->section->mainSection),
'subSection' => new ClientBreadcrumbSubSection($page->section),
'page' => new ClientBreadcrumbPage($page),
];
} else {
$breadcrumbs = null;
}
$request->merge(['breadcrumbs' => $breadcrumbs]);
return $next($request);
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class InternalRequestOnly
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next)
{
$userAgent = $request->header('User-Agent');
// Проверяем, что User-Agent содержит ключевые слова, характерные для браузеров
if (!preg_match('/Mozilla|Chrome|Safari|Firefox|Edge/i', $userAgent)) {
return response('Access denied. This route is available only from a web browser.', 403);
}
return $next($request);
}
}
+14
View File
@@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Facades\Cache;
use Spatie\Tags\HasTags;
class Post extends Model
@@ -15,6 +16,19 @@ class Post extends Model
protected $guarded = false;
protected static function booted()
{
static::saved(function ($post) {
Cache::forget('post_' . $post->id);
Cache::forget('posts_' . $post->category_id . '_*'); // Очистка кеша для всех постов в категории
});
static::deleted(function ($post) {
Cache::forget('post_' . $post->id);
Cache::forget('posts_' . $post->category_id . '_*'); // Очистка кеша для всех постов в категории
});
}
public function category() : BelongsTo
{
return $this->belongsTo(Category::class);
+1
View File
@@ -72,6 +72,7 @@ class User extends Authenticatable implements FilamentUser
return $this->belongsToMany(Division::class, 'division_user')->withPivot(['administrativePosition']);
}
public function faculties()
{
return $this->belongsToMany(Faculty::class, 'workers_faculties')->withPivot(['position']);
+56
View File
@@ -0,0 +1,56 @@
<?php
namespace App\Observers;
use App\Models\Category;
use App\Services\App\Cache\CategoryCacheService;
class CategoryObserver
{
protected CategoryCacheService $categoryCacheService;
public function __construct()
{
$this->categoryCacheService = new CategoryCacheService();
}
/**
* Handle the Post "created" event.
*/
public function saved(Category $category): void
{
$this->categoryCacheService->clearAllCacheByModel();
}
/**
* Handle the Post "updated" event.
*/
public function updated(Category $category)
{
$this->categoryCacheService->clearAllCacheByModel();
}
/**
* Очистка кеша при удалении поста.
*/
public function deleted(Category $category)
{
$this->categoryCacheService->clearAllCacheByModel();
}
/**
* Handle the Post "restored" event.
*/
public function restored(Category $category): void
{
//
}
/**
* Handle the Post "force deleted" event.
*/
public function forceDeleted(Category $category): void
{
//
}
}
+11 -7
View File
@@ -3,16 +3,24 @@
namespace App\Observers;
use App\Models\Page;
use App\Services\App\Cache\PageCacheService;
use Illuminate\Support\Facades\Cache;
class PageObserver
{
private PageCacheService $pageCacheService;
public function __construct()
{
$this->pageCacheService = app(PageCacheService::class);
}
/**
* Handle the Page "created" event.
*/
public function created(Page $page): void
{
Cache::forget('navigation');
$this->pageCacheService->clearAllCacheByModel();
}
/**
@@ -20,9 +28,7 @@ class PageObserver
*/
public function updated(Page $page)
{
$cacheKey = 'page_' . md5($page->path);
Cache::forget($cacheKey);
Cache::forget('navigation');
$this->pageCacheService->clearCache($page);
}
/**
@@ -30,9 +36,7 @@ class PageObserver
*/
public function deleted(Page $page)
{
$cacheKey = 'page_' . md5($page->path);
Cache::forget($cacheKey);
Cache::forget('navigation');
$this->pageCacheService->clearAllCacheByModel();
}
/**
+11 -23
View File
@@ -3,18 +3,26 @@
namespace App\Observers;
use App\Models\Post;
use App\Services\App\Cache\PostCacheService;
use Filament\Notifications\Notification;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redirect;
class PostObserver
{
protected PostCacheService $postCacheService;
public function __construct()
{
$this->postCacheService = new PostCacheService();
}
/**
* Handle the Post "created" event.
*/
public function saved(Post $post): void
{
$this->postCacheService->clearAllCacheByModel();
}
/**
@@ -22,8 +30,7 @@ class PostObserver
*/
public function updated(Post $post)
{
$this->clearPostCache($post);
$this->cachePost($post); // Кешируем обновленный пост
$this->postCacheService->clearCache($post);
}
/**
@@ -31,7 +38,7 @@ class PostObserver
*/
public function deleted(Post $post)
{
$this->clearPostCache($post);
$this->postCacheService->clearAllCacheByModel();
}
/**
@@ -50,23 +57,4 @@ class PostObserver
//
}
protected function cachePost(Post $post)
{
$cacheKey = 'post_' . md5($post->slug);
$cacheData = [
'post' => $post,
'seo' => $post->seo,
];
Cache::put($cacheKey, $cacheData, now()->addHours(1)); // Кешируем на 1 час
}
/**
* Очистка кеша поста.
*/
protected function clearPostCache(Post $post)
{
$cacheKey = 'post_' . md5($post->slug);
Cache::forget($cacheKey);
}
}
+56
View File
@@ -0,0 +1,56 @@
<?php
namespace App\Observers;
use App\Models\Tag;
use App\Services\App\Cache\TagCacheService;
class TagObserver
{
protected TagCacheService $tagCacheService;
public function __construct()
{
$this->tagCacheService = new TagCacheService();
}
/**
* Handle the Post "created" event.
*/
public function saved(Tag $tag): void
{
$this->tagCacheService->clearAllCacheByModel();
}
/**
* Handle the Post "updated" event.
*/
public function updated(Tag $tag)
{
$this->tagCacheService->clearAllCacheByModel();
}
/**
* Очистка кеша при удалении поста.
*/
public function deleted(Tag $tag)
{
$this->tagCacheService->clearAllCacheByModel();
}
/**
* Handle the Post "restored" event.
*/
public function restored(Tag $tag): void
{
//
}
/**
* Handle the Post "force deleted" event.
*/
public function forceDeleted(Tag $tag): void
{
//
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Services\App\Cache;
use Illuminate\Support\Facades\Redis;
abstract class AbstractCacheService
{
public function clearCacheByPrefix(string $prefix): void
{
// Получаем префикс из .env
$redisPrefix = env('REDIS_PREFIX', 'ntspi');
// Получаем ключи, соответствующие префиксу
$keys = Redis::keys($prefix);
if (!empty($keys)) {
foreach ($keys as $key) {
// Убираем префикс и двоеточие из ключа
$cleanedKey = str_replace([$redisPrefix, ':'], '', $key);
// Удаляем ключ
Redis::del($cleanedKey);
}
}
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace App\Services\App\Cache;
interface CacheInterface
{
/**
* Очищает кеш, связанный с конкретной сущностью.
*
* @param mixed $entity
* @return void
*/
public function clearCache($entity): void;
/**
* Получает кешированные данные.
*
* @param string $key
* @return mixed
*/
public function getCachedData(string $key);
/**
* Кеширует данные.
*
* @param string $key
* @param mixed $data
* @param int $ttl Время жизни кеша в секундах
* @return void
*/
public function cacheData(string $key, $data, int $ttl = 3600): void;
}
@@ -0,0 +1,49 @@
<?php
namespace App\Services\App\Cache;
use Illuminate\Support\Facades\Cache;
class CategoryCacheService extends AbstractCacheService implements CacheInterface
{
/**
* Очищает кеш, связанный с постом.
*
* @param mixed $entity Пост или связанная сущность
* @return void
*/
public function clearCache($entity): void
{
}
public function clearAllCacheByModel(): void
{
$this->clearCacheByPrefix('categories*');
$this->clearCacheByPrefix('category_content_*');
}
/**
* Получает кешированные данные по ключу.
*
* @param string $key Ключ кеша
* @return mixed
*/
public function getCachedData(string $key)
{
return Cache::get($key);
}
/**
* Кеширует данные по ключу.
*
* @param string $key Ключ кеша
* @param mixed $data Данные для кеширования
* @param int $ttl Время жизни кеша в секундах
* @return void
*/
public function cacheData(string $key, $data, int $ttl = 3600): void
{
Cache::put($key, $data, $ttl);
}
}
@@ -0,0 +1,44 @@
<?php
namespace App\Services\App\Cache;
use Illuminate\Support\Facades\Cache;
class MainSectionCacheService extends AbstractCacheService implements CacheInterface
{
/**
* Очищает кеш, связанный с постом.
*
* @param mixed $entity Пост или связанная сущность
* @return void
*/
public function clearCache($entity): void
{
$this->clearCacheByPrefix('posts_');
}
/**
* Получает кешированные данные по ключу.
*
* @param string $key Ключ кеша
* @return mixed
*/
public function getCachedData(string $key)
{
return Cache::get($key);
}
/**
* Кеширует данные по ключу.
*
* @param string $key Ключ кеша
* @param mixed $data Данные для кеширования
* @param int $ttl Время жизни кеша в секундах
* @return void
*/
public function cacheData(string $key, $data, int $ttl = 3600): void
{
Cache::put($key, $data, $ttl);
}
}
@@ -0,0 +1,63 @@
<?php
namespace App\Services\App\Cache;
use App\Models\Page;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
class PageCacheService extends AbstractCacheService implements CacheInterface
{
/**
* Очищает кеш, связанный с постом.
*
* @param mixed $entity Пост или связанная сущность
* @return void
*/
public function clearCache($entity): void
{
$cacheKeyByPath = md5($entity->path);
$cacheKeyById = md5($entity->id);
Cache::forget('page_' . $cacheKeyByPath);
Cache::forget('page_' . $cacheKeyById);
Cache::forget('navigation');
}
public function clearAllCacheByModel(): void
{
$this->clearCacheByPrefix('page_*');
$this->clearCacheByPrefix('page_data_*');
Cache::forget('navigation');
}
/**
* Получает кешированные данные по ключу.
*
* @param string $key Ключ кеша
* @return mixed
*/
public function getCachedData(string $key)
{
return Cache::get($key);
}
/**
* Кеширует данные по ключу.
*
* @param string $key Ключ кеша
* @param mixed $data Данные для кеширования
* @param int $ttl Время жизни кеша в секундах
* @return void
*/
public function cacheData(string $key, $data, int $ttl = 3600): void
{
Cache::put($key, $data, $ttl);
}
}
@@ -0,0 +1,56 @@
<?php
namespace App\Services\App\Cache;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
class PostCacheService extends AbstractCacheService implements CacheInterface
{
/**
* Очищает кеш, связанный с постом.
*
* @param mixed $entity Пост или связанная сущность
* @return void
*/
public function clearCache($entity): void
{
$cacheKeyBySlug = md5($entity->slug);
$cacheKeyById = md5($entity->id);
Cache::forget($cacheKeyBySlug);
Cache::forget($cacheKeyById);
}
public function clearAllCacheByModel(): void
{
$this->clearCacheByPrefix('post_*');
$this->clearCacheByPrefix('posts_*');
}
/**
* Получает кешированные данные по ключу.
*
* @param string $key Ключ кеша
* @return mixed
*/
public function getCachedData(string $key)
{
return Cache::get($key);
}
/**
* Кеширует данные по ключу.
*
* @param string $key Ключ кеша
* @param mixed $data Данные для кеширования
* @param int $ttl Время жизни кеша в секундах
* @return void
*/
public function cacheData(string $key, $data, int $ttl = 3600): void
{
Cache::put($key, $data, $ttl);
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Services\App\Cache;
use Illuminate\Support\Facades\Cache;
class SubSectionCacheService extends AbstractCacheService implements CacheInterface
{
/**
* Очищает кеш, связанный с постом.
*
* @param mixed $entity Пост или связанная сущность
* @return void
*/
public function clearCache($entity): void
{
$this->clearCacheByPrefix('posts_');
}
/**
* Получает кешированные данные по ключу.
*
* @param string $key Ключ кеша
* @return mixed
*/
public function getCachedData(string $key)
{
return Cache::get($key);
}
/**
* Кеширует данные по ключу.
*
* @param string $key Ключ кеша
* @param mixed $data Данные для кеширования
* @param int $ttl Время жизни кеша в секундах
* @return void
*/
public function cacheData(string $key, $data, int $ttl = 3600): void
{
Cache::put($key, $data, $ttl);
}
}
@@ -0,0 +1,50 @@
<?php
namespace App\Services\App\Cache;
use Illuminate\Support\Facades\Cache;
class TagCacheService extends AbstractCacheService implements CacheInterface
{
/**
* Очищает кеш, связанный с постом.
*
* @param mixed $entity Пост или связанная сущность
* @return void
*/
public function clearCache($entity): void
{
}
public function clearAllCacheByModel(): void
{
$this->clearCacheByPrefix('tag_ids*');
$this->clearCacheByPrefix('tags*');
$this->clearCacheByPrefix('tag_content_*');
}
/**
* Получает кешированные данные по ключу.
*
* @param string $key Ключ кеша
* @return mixed
*/
public function getCachedData(string $key)
{
return Cache::get($key);
}
/**
* Кеширует данные по ключу.
*
* @param string $key Ключ кеша
* @param mixed $data Данные для кеширования
* @param int $ttl Время жизни кеша в секундах
* @return void
*/
public function cacheData(string $key, $data, int $ttl = 3600): void
{
Cache::put($key, $data, $ttl);
}
}
+1 -1
View File
@@ -134,7 +134,7 @@ return [
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
'database' => env('REDIS_DB', '1'),
],
'cache' => [
@@ -9,7 +9,6 @@
<div class="bg-gray-200 group-focus:scale-105 transition-transform duration-500 ease-in-out size-full absolute top-0 start-0 object-cover rounded-xl" />
</div>
<div class="ms-4 mt-2 w-full">
<p class="h-4 bg-gray-200 rounded-full" style="width: 40%;"></p>
<ul class="mt-5 space-y-3 flex flex-col">
@@ -73,11 +72,14 @@
</div>
<div class="grow">
<div>
<span class="text-sm font-light text-gray-700">Опубликовано {{ post.created_post }}</span>
</div>
<h3 class="text-xl font-semibold text-gray-800 group-hover:text-gray-600">
{{ post.title }}
</h3>
<p class="mt-3 text-gray-600">
Produce professional, reliable streams easily leveraging Preline's innovative broadcast studio
{{ textLimit(post.preview_text, 80) }}
</p>
<p class="mt-4 inline-flex items-center gap-x-1 text-sm text-primaryBlue decoration-2 group-hover:underline group-focus:underline font-medium">
Читать далее
@@ -129,7 +131,15 @@ export default {
console.error('Ошибка:', error);
this.loading = false; // Установить состояние загрузки в false даже при ошибке
});
}
},
textLimit(text, symbols) {
if (text.length > symbols) {
let LimitedText;
LimitedText = text.substring(0, symbols);
return LimitedText + "...";
}
return text;
},
},
mounted() {
this.getPosts();
+28 -21
View File
@@ -16,44 +16,51 @@ use App\Models\AdmissionCampaign;
use App\Services\Vicon\DirectionStudy\DirectionStudyService;
use App\Services\VK\VkAuthService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
Route::get('/getNavigation', [NavigateController::class, 'index'])->name('client.main.navigate');
Route::get('/getAcademicYear', function () {
$activeCampaign = AdmissionCampaign::query()->where('status', 1)->first();
return $activeCampaign->academic_year;
})->name('academic.year');
Route::get('/search', [SearchController::class, 'index'])->name('client.search.index');
Route::middleware('ensure.browser')->group(function () {
Route::get('/getNavigation', [NavigateController::class, 'index'])->name('client.main.navigate');
Route::get('/widget/get-posts', [ClientWidgetPostController::class, 'index'])->name('client.widget.post.index');
Route::get('/search', [SearchController::class, 'index'])->name('client.search.index');
Route::get('/widget/get-posts/{id}', [ClientWidgetPostController::class, 'single'])->name('client.widget.post.single');
Route::get('/widget/get-posts', [ClientWidgetPostController::class, 'index'])->name('client.widget.post.index');
Route::get('/widget/get-additional-programs', [ClientWidgetAdditionalEducationalProgramController::class, 'index'])->name('client.widget.additional.program.index');
Route::get('/widget/get-posts/{id}', [ClientWidgetPostController::class, 'single'])->name('client.widget.post.single');
Route::get('/widget/get-educational-programs', [ClientWidgetEducationalProgramController::class, 'index'])->name('client.widget.educational.program.index');
Route::get('/widget/get-additional-programs', [ClientWidgetAdditionalEducationalProgramController::class, 'index'])->name('client.widget.additional.program.index');
Route::get('/widget/get-educational-programs', [ClientWidgetEducationalProgramController::class, 'index'])->name('client.widget.educational.program.index');
Route::get('/widget/get-page-resource/{id}', [ClientWidgetPageReferenceListController::class, 'show'])->name('client.widget.page.resource.show');
Route::get('/widget/get-contact-widget/{id}', [ClientWidgetContactController::class, 'show'])->name('client.widget.contact.show');
Route::get('/widget/get-page/{path}', [ClientWidgetPageController::class, 'single'])->name('client.widget.page.single');
Route::get('/widget/get-form/{id}', [ClientWidgetFormController::class, 'single'])->middleware('rate.limited.check')->name('client.widget.form.single');
Route::post('/widget/get-form/{id}/submit', [ClientWidgetFormController::class, 'submit'])->middleware(['rate.limited.counter', 'rate.limited.check'])->name('client.widget.form.submit');
});
Route::middleware(['auth', 'superadmin'])->group(function () {
Route::get('/login/vk', [VkAuthService::class, 'redirectToProvider'])->name('vk.login');
Route::get('/login/vk/callback', [VkAuthService::class, 'handleProviderCallback'])->name('vk.callback');
Route::get('/vk-get-token', [VkAuthService::class, 'getToken'])->name('vk.getToken');
Route::get('/vk-refresh-token', [VkAuthService::class, 'refresh'])->name('vk.refreshToken');
Route::get('/vk-logout', [VkAuthService::class, 'logout'])->name('vk.logout');
});
Route::get('/widget/get-page-resource/{id}', [ClientWidgetPageReferenceListController::class, 'show'])->name('client.widget.page.resource.show');
Route::get('/widget/get-contact-widget/{id}', [ClientWidgetContactController::class, 'show'])->name('client.widget.contact.show');
Route::get('/widget/get-page/{id}', [ClientWidgetPageController::class, 'single'])->name('client.widget.page.single');
Route::get('/widget/get-form/{id}', [ClientWidgetFormController::class, 'single'])->middleware('rate.limited.check')->name('client.widget.form.single');
Route::post('/widget/get-form/{id}/submit', [ClientWidgetFormController::class, 'submit'])->middleware(['rate.limited.counter', 'rate.limited.check'])->name('client.widget.form.submit');
Route::get('/login/vk', [VkAuthService::class, 'redirectToProvider'])->name('vk.login');
Route::get('/login/vk/callback', [VkAuthService::class, 'handleProviderCallback'])->name('vk.callback');
Route::get('/vk-get-token', [VkAuthService::class, 'getToken'])->name('vk.getToken');
Route::get('/vk-refresh-token', [VkAuthService::class, 'refresh'])->name('vk.refreshToken');
Route::get('/vk-logout', [VkAuthService::class, 'logout'])->name('vk.logout');