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

Omdbapi Laravel Package

aharen/omdbapi

A Laravel package for the OMDb API that lets you look up movies and series by title or IMDb ID, run searches, and retrieve posters, plot summaries, and IMDb, Rotten Tomatoes, and Metacritic ratings through a simple, expressive interface.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install and confirm compatibility first. The last release was December 2023 and the repo link is unknown, so before committing, check the require block in vendor/aharen/omdbapi/composer.json against your Laravel/PHP version. Install with:

composer require aharen/omdbapi

2. Get an OMDb key. Register at omdbapi.com/apikey.aspx — the free tier is ~1,000 requests/day and is activated by clicking a link in a confirmation email. A key that returns "Error":"Invalid API key!" is usually just unactivated.

3. Publish config and set the key. Look for a service provider and config tag:

php artisan vendor:publish --tag=config

Then add the key to .env (the exact variable name varies — check config/omdbapi.php or config/omdb.php after publishing). Typical names are OMDB_API_KEY or OMDBAPI_KEY. Never hardcode it; the config file should read from env().

4. Where to look first. The package is intentionally thin, so read these three files and you know the whole surface:

  • src/*ServiceProvider.php — what config key, facade alias, and container bindings exist
  • src/*.php (the client class) — the actual public methods, usually something like search($term, $page) and find($id) / findByTitle($title)
  • README.md — confirms the facade name (Omdb vs OMDb) and method signatures

Ignore the vendor tests/ folder for guidance — at 10 stars it's likely near-empty.

5. First use case: a title search. In a controller, do the smallest possible thing to validate the wiring:

use Aharen\Omdbapi\Facades\Omdb; // confirm actual namespace/alias

public function index(Request $request)
{
    $results = Omdb::search($request->string('q'));
    return view('movies.index', ['results' => $results]);
}

dd() the raw response before writing any view code — see the Gotchas section on why the shape matters.

Implementation Patterns

Wrap it in your own service. The biggest day-to-day risk with a 10-star, single-maintainer wrapper is that it disappears. Put one class between your app and the package:

final class MovieCatalog
{
    public function search(string $term): array { /* Omdb::search(...) */ }
    public function byImdbId(string $id): ?array { /* Omdb::find($id) */ }
}

Then controllers, jobs, and Blade views depend on MovieCatalog, not on the package facade. Swapping to a raw Http::get('https://www.omdbapi.com', [...]) later becomes a one-file change. This is the single highest-value pattern for this package.

Two-step lookup — search, then hydrate. OMDb’s search endpoint returns only Title, Year, imdbID, Type, and Poster. Anything richer (plot, runtime, ratings, genre) requires a second call keyed by imdbID. So a results grid should stay cheap: render from the search payload, and only fetch full details on the detail page or an explicit "expand" action. Avoid hydrating all 10 results on the index page — that turns one request into eleven against a 1,000/day quota.

Cache aggressively — it’s the only real quota strategy. Movie metadata is effectively immutable, so cache by a deterministic key:

$movie = Cache::remember("omdb:id:{$imdbId}", now()->addDays(30), fn () => Omdb::find($imdbId));
$search = Cache::remember("omdb:s:{$term}:{$page}", now()->addHours(12), fn () => Omdb::search($term, $page));

Use long TTLs for ID lookups, short ones for searches (results shift as new titles are added). This also absorbs repeated page loads and bot traffic.

Pagination is offset-by-page only. OMDb paginates search results with a page parameter and returns 10 per page, plus a totalResults count. Drive your own paginator from that number rather than exposing infinite "next" links, and remember totalResults arrives as a string — cast it before use in LengthAwarePaginator.

Queue bulk work. For seeding a catalog from an IMDb ID list, put each lookup in a queued job with RateLimited / retryUntil, and Http::fake() or a stubbed client in tests. Free-tier throttling is per-day, not per-second, so a burst of a few hundred jobs is fine; thousands is not.

Type-filter for clean UX. Search accepts a type of movie, series, or episode. If you surface a filter chip in the UI, pass it through — otherwise a search for a common word mixes series and films together and looks broken.

Episode data needs extra parameters. Title/ID lookups won't give you per-season breakdowns. Episode retrieval requires Season and Episode alongside the series ID, so check whether the package exposes those before promising episode-level features.

Validate and encode input. Run search terms through $request->validate(['q' => 'required|string|min:2|max:100']) and let the HTTP client handle encoding. Titles with &, :, +, or apostrophes are common and will 400 or silently mismatched if you concatenate URLs yourself.

Gotchas and Tips

OMDb returns HTTP 200 on failure. A bad key, a missing title, or too many requests all come back as a successful response with "Response": "False" and an Error string. If you only check status codes, your "not found" handling will never fire and you’ll render empty movie cards. Always branch on Response === 'False' and surface Error as a 404 or a user-facing message. This is the number-one source of confusion with this API.

N/A is a string, not null. Fields like Poster, Runtime, Metascore, Genre, and imdbRating are frequently the literal string "N/A". Guard in your accessor or model cast, otherwise (int) "N/A" becomes 0 and "N/A" renders as a broken image URL in Blade. A small nullIfNa() helper used across your MovieCatalog pays for itself quickly.

Poster URLs are hotlinks to IMDb’s CDN. They work, but they can change and you have no SLA. For anything user-facing at scale, copy posters to your own storage during ingestion.

Config caching will bite you. After adding the key to .env, run php artisan config:cache (or config:clear if the key isn’t picking up). In a Docker/deploy pipeline, .env edits with a stale config cache are a classic "works locally, fails on the server" bug with this kind of package.

Check for facade alias collisions. If the service provider registers a global alias like Omdb, it lives in config/app.php under aliases. If you already have a class or package using that name, you’ll get confusing resolution errors — alias it explicitly instead, and prefer constructor injection of the underlying client over the facade for anything beyond trivial controller code.

Don’t assume exception behaviour. A thin wrapper may return arrays, may return an object, may throw on transport errors and return errors-as-data on API errors. Read the client class once and standardise in your wrapper: pick "throw or array" and enforce it in MovieCatalog so callers never have to branch on both.

Missing key fails late. Several wrappers only fail when the first request is made, not at boot. Add a php artisan tinker smoke test (Omdb::search('matrix')) in your deploy checklist, or better, add a failing-fast check in a service provider when the app is non-local.

Extension points are limited — plan the exit. With 10 stars, no visible repository, and a 2023 release, treat the package as unmaintained. Concrete mitigations: pin the exact version in composer.json, keep the MovieCatalog seam described above, and note that replacing it is roughly:

Http::get('https://www.omdbapi.com', [
    'apikey' => config('services.omdb.key'),
    't' => $title,
])->json();

That is the whole library. If you hit a wall — a need for season/episode traversal, response DTOs, or retry logic — write those 20 lines yourself rather than waiting for a commit.

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.
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics
robbiep/afterthedeadline
frankkessler/incontact-laravel-oauth2-rest
jlxh/laravel-userlog
davidmgilo/timetables
qylinfly/role-permission
reflect-digital/conduit
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr