Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Placid Php Laravel Package

placidapp/placid-php

Official PHP SDK for the Placid creative automation API. Generate images, videos, and PDFs from templates by merging dynamic data, then retrieve rendered assets through a simple client for Laravel or any PHP app.

Deep Wiki
Context7

Getting Started

  1. Install the client alongside the HTTP stack it depends on:
    composer require placidapp/placid-php guzzlehttp/guzzle
    
  2. Grab credentials in Placid, not in code: create an API token under Settings → API in the Placid dashboard, then add it to .env as PLACID_API_TOKEN and reference it from config/services.php ('placid' => ['token' => env('PLACID_API_TOKEN')]). Never hard-code the token in a service provider.
  3. Build the template in Placid first. The SDK is only a transport layer — every render is driven by a template UUID and the layer names you defined in the Placid editor. Open the template in the dashboard, note the UUID and every layer key (e.g. title, subtitle, hero_image); those strings are your real API contract.
  4. Bind the client once. Add a tiny service provider so the SDK is constructed with the token and resolved as a singleton:
    $this->app->singleton(\Placid\Placid::class, fn () =>
        new \Placid\Placid(config('services.placid.token'))
    );
    
    Check vendor/placidapp/placid-php/src/ for the exact class name and constructor signature — the package is thin and the README is the authoritative example.
  5. First use case: OG / social card images for blog posts. A Post model with title, author, and cover_image_url maps almost 1:1 to a template with three layers. Render one card, hit the returned URL in a browser, and you've validated token, template UUID, and layer schema in a single loop.

Implementation Patterns

Wrap it in a domain service, not controllers. Create App\Services\PlacidImageService that exposes intent-level methods (renderPostCard(Post $post): string) and hides the layer-payload shape. Controllers and jobs should never assemble layers arrays directly — that payload is template-specific and will drift.

Treat rendering as async by default. Placid's image/video jobs are queued server-side; the create call returns a job/ID, and the final asset URL arrives via response polling or a webhook. Two viable Laravel patterns:

  • Webhook-driven (preferred for volume): dispatch a GenerateSocialCard job that calls the SDK with webhook_success_url pointing at a signed route. A PlacidWebhookController receives the payload, matches it to the record via a placid_job_id column, and stores the final URL.
  • Poll-driven (simpler for low volume): in the job, create then poll the SDK's job-status endpoint with retry()/backoff. Fine for a few dozen images a day; painful at scale.

Always re-host the output. Don't store Placid's URL as the canonical asset — download it once and push to your own disk:

Storage::disk('s3')->put($path, Http::get($url)->body());
$post->update(['og_image_path' => $path]);

This decouples your app from Placid's CDN and keeps URLs stable if you ever switch providers.

Cache aggressively and key on inputs. A rendered card is deterministic given template UUID + layer payload. Hash that payload (sha1(json_encode($layers))) and store it alongside the asset path; re-render only when the hash changes. This alone cuts most Placid spend.

Fake it in tests. The SDK is Guzzle-based, so Http::fake() won't intercept it — either inject a mock of your PlacidImageService into feature tests, or bind a fake client implementation of an interface you define around the SDK. Do not let real HTTP calls leak into the suite.

Queue + rate-limit. Rendering 500 cards on save will burn your Placid quota and time out. Use a dedicated queue with RateLimited middleware and a per-minute cap that matches your plan.

Gotchas and Tips

  • The package is stale (last release mid-2022) and thinly starred. Placid's REST API has evolved; verify the SDK's request shape against current Placid docs before assuming it works. If it lags, the fallback is trivial — the calls are plain JSON POSTs, so a 40-line Http::withToken() wrapper gives you the same result with none of the dependency risk.
  • Layer names are case-sensitive and template-bound. A typo (Title vs title) doesn't error loudly — it silently renders the template's default. Validate your payload keys against a stored copy of the template schema, or add an integration test that asserts the rendered image differs when a layer changes.
  • Image layers must be publicly fetchable. Placid downloads source images server-side, so private S3 objects or signed URLs that expire in minutes will render broken. Generate a long-lived presigned URL (or a public CDN copy) at dispatch time, not at call time.
  • Don't assume the create response contains the image URL. It usually contains an ID/status; the URL comes later. Code that does $response['image_url'] on the create call is the #1 source of "works in curl, fails in prod" bugs.
  • Webhooks need auth + idempotency. Sign the callback URL with URL::temporarySignedRoute(), and make the handler idempotent (upsert on placid_job_id) — retries are expected.
  • Error surface is Guzzle-native. Expect GuzzleHttp\Exception\ClientException (4xx — bad token, unknown UUID, invalid layer) and ServerException/ConnectException (5xx/timeouts). Catch at the service boundary and translate into a domain exception; don't let Guzzle exceptions bubble into your queue's failure logs unlabelled.
  • No config publishing or facade ships with the package. If you want Placid::-style ergonomics in Laravel, write the facade and service provider yourself — it's five lines and keeps the dependency confined to one binding.
  • Log the request payload, not just the response. When a render comes back blank, the payload is what you need; redact the token but keep template UUID, layer keys, and job ID.
  • Extension point is the HTTP client. If you need timeouts, retries, or a proxy, the cleanest path is bypassing the SDK and injecting a configured Illuminate\Http\Client\PendingRequest. Given the package's age, budgeting for that swap is a realistic long-term plan, not a pessimism.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core