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

Newsapi Laravel Package

jcobhams/newsapi

jcobhams/newsapi is a PHP client for NewsAPI.org that lets you fetch top headlines, search articles, and list sources using simple, fluent methods. It handles API requests, query parameters, and responses, making it easy to add news feeds to Laravel or plain PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer and grab an API key from newsapi.org:

composer require jcobhams/newsapi
NEWSAPI_KEY=your-key-here

Wire it into the container (there is no service provider shipped, so do it yourself in AppServiceProvider::register()):

use jcobhams\NewsApi\NewsApi;

$this->app->singleton(NewsApi::class, fn () => new NewsApi(config('services.newsapi.key')));

Add the config entry so config:cache works:

// config/services.php
'newsapi' => ['key' => env('NEWSAPI_KEY')],

First use case — a trivial smoke test to confirm the key works and to see the response shape:

$news = app(NewsApi::class);
$response = $news->getTopHeadlines(country: 'us', category: 'technology', pageSize: 10);

foreach ($response->articles as $article) {
    echo $article->title;
}

Where to look first: the package's src/NewsApi.php — it's a single thin wrapper class with three public methods (getTopHeadlines, getEverything, getSources). Read those signatures before anything else; there is no hidden magic, no facade, no config file. The README's examples folder is the fastest path to seeing valid parameter combinations.

Implementation Patterns

Service wrapper for testability. Don't inject jcobhams\NewsApi\NewsApi directly into controllers. Wrap it in your own NewsService with typed methods returning your own DTOs — the package returns plain stdClass trees, and you do not want NewsAPI's field names leaking into Blade templates or Livewire components.

class NewsService
{
    public function __construct(private NewsApi $client) {}

    public function techHeadlines(int $limit = 20): Collection
    {
        return Cache::remember("news.tech.{$limit}", now()->addMinutes(15), function () use ($limit) {
            $res = $this->client->getTopHeadlines(country: 'us', category: 'technology', pageSize: $limit);
            return collect($res->articles ?? [])->map(fn ($a) => ArticleData::fromApi($a));
        });
    }
}

Cache aggressively — it is not optional. The free tier is 100 requests/day. Any page that fetches on every load will exhaust the quota in an afternoon. Cache at the query level (15–60 min for headlines, 24 h for /sources), and consider warming the cache in a scheduled command so user requests never block on the upstream API.

Scheduled ingestion over on-demand fetching. For dashboards, feeds, or content pipelines, a php artisan news:sync command running every 15–30 minutes into a database table gives you pagination, search, and full-text filtering for free — and decouples your uptime from NewsAPI's.

Queue the expensive queries. getEverything() with a broad q, a long date range, and many pages is slow and quota-hungry. Dispatch a job, page through results, persist, then notify. Never loop pages synchronously in a web request.

Multi-call composition. getSources() is cheap and stable; cache it and use it to populate a country/language selector, then feed those choices into getTopHeadlines(). Similarly, getEverything(domains: 'techcrunch.com,verge.com', sortBy: 'publishedAt') is the right pattern for a curated feed rather than a full-text search.

HTTP-layer escape hatch. If you hit a parameter the wrapper doesn't expose, drop down to the Http facade against https://newsapi.org/v2/* — you're not gaining much from the wrapper at that point, and it avoids forking.

Gotchas and Tips

This is not a Laravel package. No service provider, no facade, no config publishing, no Http client injection, no retry logic. Everything above is scaffolding you write. Budget for that — it is roughly 60 lines of glue.

The free tier blocks production. NewsAPI's developer plan permits localhost development only; requests from a deployed server are rejected or throttled. It also delays articles by 24 hours on the free plan and caps totalResults at 100. If someone says "just use the free key in prod," that is the failure you will hit within days.

A 200 response can still be an error. NewsAPI frequently returns HTTP 200 with {"status":"error","code":"apiKeyInvalid","message":"..."} in the body. Always check $response->status === 'ok' before touching ->articles, or you will get "Undefined property" errors that mask the real cause. Log the code and message fields when it isn't ok.

Parameter mixing rules are enforced upstream. You cannot combine sources with country or category on /top-headlines, and q cannot be combined with sources. sortBy only exists on /everything and accepts relevancy, popularity, publishedAt. Breaking these yields a 400 with a vague message.

Pass null, not '', for unused filters. The wrapper forwards arguments as query params; empty strings serialize into the URL and produce validation errors. Build an explicit array of non-null params before the call.

pageSize caps at 100 and page is 1-indexed. Off-by-one pagination bugs are common here. Also, at pageSize=100 the free tier's 100-result ceiling means page 2 returns nothing.

Timestamps must be ISO 8601. $from/$to on getEverything() want 2024-01-01T00:00:00 or 2024-01-01. Passing a Unix timestamp or a Carbon __toString format silently returns wrong or empty results.

Article fields are nullable. author, urlToImage, and content are frequently null or truncated with a [+1234 chars] suffix. Guard your blade templates and store content as TEXT, not VARCHAR.

Country and category codes are strict. Lowercase ISO 3166-1 alpha-2 for countries (us, gb, de); categories are limited to business, entertainment, general, health, science, sports, technology. There is no validation in the package — a typo becomes a 400 at runtime.

Last release was February 2023. No maintenance activity, and no compatibility testing against Laravel 11/12 or PHP 8.3+. It uses ext-curl/file_get_contents-style calls without a PSR-18 abstraction. Pin the version in composer.json and be prepared to replace it with a 100-line Guzzle client if NewsAPI changes its response envelope.

Extension points are minimal. Subclassing NewsApi to override the base URL is the only realistic hook (useful for pointing at a caching proxy or a recorded-response fixture server in tests). For tests, bind a fake into the container behind your own NewsService interface rather than mocking the package class — it makes the swap to a different client painless later.

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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator