Laravel

Obrazki OG w
Laravel

Trait na modelu, zadanie w kolejce, adres w bazie.

Gdzie to wpiąć

W Laravelu naturalnym miejscem jest kolejka. Pakiet dodaje trait: zapis wpisu wrzuca zadanie, zadanie renderuje przez API i zapisuje adres, a nieudany render sam się ponowi. Zanim skończy, `<x-og-image :model="$post" />` wypisuje podpisany adres tego samego obrazka, więc żadna strona nie wychodzi bez niego.

app/Models/Post.php

// composer require shareglint/laravel
// .env: SHAREGLINT_KEY, SHAREGLINT_ACCOUNT_ID, SHAREGLINT_SIGNING_SECRET

use Shareglint\Laravel\Concerns\HasOgImage;
use Shareglint\Laravel\Contracts\OgImageable;

final class Post extends Model implements OgImageable
{
    use HasOgImage;

    // On create and on every change, a queued job (after commit) renders
    // the image and stores its URL in the og_image column.
    public function ogImageFields(): array
    {
        return [
            'title' => $this->title,
            'author' => $this->author->name,
            'date' => $this->published_at,
            'reading_time' => $this->reading_minutes,
            'site' => config('app.domain'),
            'locale' => 'en',
        ];
    }

    // Re-render only when these change (default: any attribute).
    public function ogImageWatched(): ?array
    {
        return ['title', 'author_id', 'published_at'];
    }
}

// resources/views/posts/show.blade.php, in <head> - the stored URL,
// or a signed URL of the same image until the job has run:
// <x-og-image :model="$post" />

Bez pakietu

To samo jednym zwykłym wywołaniem HTTP — bez instalowania zależności.

app/Jobs/GenerateOgImage.php

final class GenerateOgImage implements ShouldQueue
{
    use Queueable;

    public int $tries = 3;

    public function __construct(private readonly int $postId) {}

    public function handle(): void
    {
        $post = Post::findOrFail($this->postId);

        $response = Http::withToken(config('services.shareglint.key'))
            ->timeout(20)
            ->post('https://shareglint.com/v1/images?wait=true', [
                'template' => 'blog-og',
                'locale' => 'en',
                'modifications' => [
                    'title' => $post->title,
                    'author' => $post->author->name,
                    'date' => $post->published_at->toDateString(),
                    'reading_time' => $post->reading_minutes,
                    'site' => config('app.domain'),
                ],
            ])
            ->throw();

        $post->update(['og_image' => $response->json('url')]);
    }
}

// Dispatch it on publish:
// GenerateOgImage::dispatch($post->id)->afterCommit();
Pułapka

Kolejkuj po zatwierdzeniu transakcji. Pakiet wysyła zadanie z `afterCommit()`; jeśli piszesz zadanie sam i to pominiesz, worker może wystartować, zanim transakcja zapisująca wpis się zatwierdzi — i `findOrFail` wywali się na nieistniejącym rekordzie.

Co dostajesz w odpowiedzi

Z ?wait=true czekasz na gotowy obrazek w tym samym połączeniu — zwykle około sekundy.

{
    "id": "img_01m08s3ez1zcv28h335g9923bw",
    "status": "completed",
    "url": "https://cdn.shareglint.com/renders/img_01m08s3ez1zcv28h335g9923bw.png",
    "duration_ms": 912
}

Ile to kosztuje

Sto obrazków miesięcznie za darmo, potem $9 za dwa tysiące. Ten sam wpis wyrenderowany drugi raz zwraca istniejący adres i nie zużywa limitu — więc przebudowanie strony nic nie kosztuje.

Inne frameworki