presseportale/app/Services/Web/HubPageData.php
Kevin Adametz da189c05b6 web: Stale-while-revalidate-Cache für die öffentlichen Seitendaten
Start-/Kategorieseiten bauten nach Ablauf der 5-Minuten-TTL im Besucher-
Request neu (~25-30 Archiv-Queries über ~100k PMs) — Long-Tail-Rubriken
waren dadurch praktisch bei jedem Aufruf langsam. WebPageCache nutzt jetzt
Cache::flexible([300, 3600]): Innerhalb 5 Min frisch wie bisher, danach
wird bis zu 1 h sofort der alte Stand serviert und der Neuaufbau läuft
nach der Response (deferred). HomePageData/CategoryPageData/TickerData
laufen dafür über die gemeinsame WebPageCache-Konvention (Keys unverändert),
die Hub-Kennzahlen über flexible([3600, 14400]).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 14:29:15 +00:00

55 lines
2.1 KiB
PHP

<?php
namespace App\Services\Web;
use App\Enums\Portal;
use App\Models\Category;
use App\Models\Company;
use App\Models\Plan;
use App\Models\PressRelease;
use App\Scopes\PortalScope;
use Illuminate\Support\Facades\Cache;
/**
* Datenaufbereitung der Hub-Landing (pressekonto.de): aktiver Tarif-Katalog
* plus echte Plattform-Kennzahlen statt statischer Marketing-Zahlen.
*
* Die Kennzahlen ändern sich träge, ihr Aufbau zählt aber übers Gesamtarchiv
* (inkl. whereHas über alle Firmen) → stale-while-revalidate mit langem
* Fenster, damit der Aufbau nie im Besucher-Request läuft.
*/
class HubPageData
{
private const StatsCacheKey = 'web.hub.landing-stats';
private const StatsFreshSeconds = 3600;
private const StatsStaleSeconds = 14400;
/**
* @return array<string, mixed>
*/
public function build(): array
{
return [
'plans' => Plan::query()->active()->get(),
'singlePmPriceCents' => (int) config('billing.single_pm_price_cents'),
'hubStats' => Cache::flexible(self::StatsCacheKey, [self::StatsFreshSeconds, self::StatsStaleSeconds], function (): array {
$published = PressRelease::query()
->withoutGlobalScope(PortalScope::class)
->visibleInArchive();
return [
'releases_total' => (clone $published)->count(),
'releases_presseecho' => (clone $published)->forPortalValues([Portal::Presseecho->value, Portal::Both->value])->count(),
'releases_businessportal' => (clone $published)->forPortalValues([Portal::Businessportal24->value, Portal::Both->value])->count(),
'newsrooms' => Company::query()
->withoutGlobalScope(PortalScope::class)
->whereHas('pressReleases', fn ($query) => $query->withoutGlobalScope(PortalScope::class)->visibleInArchive())
->count(),
'categories' => Category::query()->withoutGlobalScope(PortalScope::class)->count(),
];
}),
];
}
}