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

Chuck Norris Jokes Laravel Package

mpociot/chuck-norris-jokes

A lightweight Laravel package for adding Chuck Norris humor to your app. Fetch random jokes through a simple interface and easily expose them in views, routes, or APIs with minimal setup and configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install

composer require mpociot/chuck-norris-jokes

On Laravel 5.5+ the service provider and ChuckNorris facade are auto-discovered; on older versions add them to config/app.php. If the package ships a config file, publish it first:

php artisan vendor:publish --provider="Mpociot\ChuckNorrisJokes\ChuckNorrisJokesServiceProvider"

2. Where to look first

  • vendor/mpociot/chuck-norris-jokes/src/ — the whole package is a single client class plus a facade. Read the client first; it is the only thing that matters day-to-day.
  • composer.json inside the vendor folder — check the illuminate/* and guzzlehttp/guzzle constraints before you build anything against it. This is the single most likely reason the install will or won't work on your Laravel major.
  • config/chuck-norris-jokes.php (if published) — the base URL and any HTTP options. This is your escape hatch to point at a mock or proxy.

3. First use case — smoke test in Tinker

Before wiring it into a page, confirm the call works and see the actual return shape:

php artisan tinker
>>> \Mpociot\ChuckNorrisJokes\Facades\ChuckNorris::random();

You should get back a joke string (or a value object/array depending on how the package wraps the chucknorris.io payload — verify in the client source). The upstream returns { id, value, icon_url, url, categories }; the package typically unwraps .value for you. This is the moment to note whether it returns a plain string, an object, or throws on failure — that determines every pattern below.

4. Minimum viable integration

The canonical first use case is an easter-egg line on a non-critical page — a 404, an empty state, or a dev-only dashboard widget:

// app/Http/Controllers/NotFoundController.php
use Mpociot\ChuckNorrisJokes\Facades\ChuckNorris;

public function show()
{
    try {
        $joke = ChuckNorris::random();
    } catch (\Throwable $e) {
        $joke = null; // never let a joke 500 the page
    }

    return view('errors.404', compact('joke'));
}

That try/catch is not optional — see Gotchas.

Implementation Patterns

Controller usage (the common case)

Inject the underlying client rather than reaching for the facade when you intend to unit-test the calling class:

use Mpociot\ChuckNorrisJokes\ChuckNorrisJokes; // verify exact class name in src/

public function __construct(private ChuckNorrisJokes $jokes) {}

public function index()
{
    return view('dashboard', [
        'joke' => $this->jokes->random('dev'),
    ]);
}

This is the pattern to prefer for anything beyond a throwaway — the facade is convenient but hard to swap in tests.

Blade view usage

For pure-cosmetic surfaces, calling directly in Blade is fine and idiomatic for this kind of package:

@if ($joke = rescue(fn () => \Mpociot\ChuckNorrisJokes\Facades\ChuckNorris::random(), null, false))
    <p class="text-muted">{{ $joke }}</p>
@endif

rescue() keeps you from importing exception-handling into the template. Use it sparingly — if this is doing real work, move it to the controller.

Category filtering

If the package exposes categories (the description says it does), the underlying API supports random?category=dev. Categories include dev, movie, food, science, sport, etc. Treat the category string as a user-supplied value: validate against a known allowlist rather than passing raw input through, or you invite 400s and unexpected content:

$allowed = ['dev', 'movie', 'science'];
$category = in_array($request->input('category'), $allowed, true)
    ? $request->input('category')
    : 'dev';

$joke = ChuckNorris::random($category);

Artisan command / scheduled output

A natural fit for the package:

public function handle()
{
    $this->line(ChuckNorris::random('dev'));
    return self::SUCCESS;
}

Use it for Slack/Discord slash commands, morning standup bots, or php artisan joke in dev tooling. Keep it out of scheduled jobs that feed customer surfaces.

Caching wrapper (do this if you call it more than occasionally)

The package itself does not cache — every call is a network round-trip. Wrap it:

use Illuminate\Support\Facades\Cache;

function random_joke(?string $category = null): string
{
    return Cache::remember(
        'chuck:' . ($category ?? 'any'),
        now()->addHours(6),
        fn () => rescue(fn () => ChuckNorris::random($category), 'Chuck Norris can divide by zero.', false)
    );
}

This kills three problems at once: upstream latency, rate-limit risk, and the failure mode where the API is down and your page breaks. Cache the fallback too, so one outage doesn't hammer the dead endpoint.

Adapter / interface pattern (recommended)

Since the package is unmaintained, do not let its namespace leak into your domain code. Wrap it behind your own tiny interface:

interface JokeSource
{
    public function random(?string $category = null): string;
}

Bind ChuckNorrisJokesSource implements JokeSource in a provider. When the package inevitably breaks against a future Laravel major, you replace one binding and nothing else. This also makes mocking in tests trivial and lets you ship a StaticJokeSource for local/test environments.

Testing

Because the package uses Guzzle directly (not Laravel's Http facade), Http::fake() will not intercept its calls. Options, in order of preference:

  1. Bind a fake JokeSource implementation in tests (the adapter pattern above).
  2. Mock the underlying client class via Mockery::mock(ChuckNorrisJokes::class) if injecting into a service.
  3. Use Guzzle's MockHandler against the client if you must exercise the real wrapper.

Never let a test suite make live calls to chucknorris.io — it will flake and, in CI, throttle.

Gotchas and Tips

The package is frozen. Last release was February 2019 (1.0.0), single maintainer, zero dependents. There is no roadmap, no changelog, and no maintenance. Treat the source as read-only and vendor it if you use it at all. Do not expect fixes.

Dependency resolution is the real gate. A 2019 package will typically constrain Guzzle ^6.0 and older illuminate/* ranges. On a current Laravel tree:

  • If it resolves cleanly, you got lucky — move on.
  • If it requires --ignore-platform-reqs, do not do that in production. That flag turns "won't install" into "will break at runtime," which is worse.
  • If it pins Guzzle v6 and you're on v7, you have a hard conflict. Do not downgrade Guzzle for a joke.

Verify with composer why-not mpociot/chuck-norris-jokes before you invest any integration time.

No caching, no timeout, no retry — you supply all three. Every call is a bare network round-trip to a third-party API with no SLA. Under any real traffic that means latency on the request path and 429s from the upstream. Cache aggressively (see pattern above). If the client accepts an options array, pass a short timeout (2–3 s) so a slow upstream can't stall a page render.

Failure behaviour is unknown and unsafe by default. You have no guarantee whether a timeout, non-200, or malformed JSON raises an exception, returns null, or hangs. For a decorative feature this must never be able to break the host page. Always wrap in try/catch or rescue(), and always have a hardcoded fallback joke. Test this explicitly by blocking the upstream host (e.g. in your hosts file) and loading the page.

Content is uncontrolled. The upstream is an external, unmoderated joke feed. For internal tools (dashboards, dev CLIs), that's acceptable. For any customer-visible surface it is a policy decision you are making by default — Chuck Norris jokes have historically included edgy content, and you cannot moderate, localize, or filter them through this package. If the surface is customer-facing, curate an allowlist / mirror of jokes instead of calling upstream live.

Base URL configurability is your escape hatch. If the config exposes a base URL, use it: point at a local mock in test environments, and at a small caching proxy in production if you want to survive upstream outages. If the base URL is hardcoded in the client, that is a signal to reimplement rather than adopt.

Facade in tests will make real calls. The facade resolves the client out of the container — there's no built-in fake. Any test that touches a code path calling the facade will hit the network unless you swap the container binding. Bind your own JokeSource fake in setUp() or via $this->app->instance(...).

Cost/benefit sanity check. The whole package is a thin wrapper over GET https://api.chucknorris.io/jokes/random that unwraps .value. Behind your own interface, with caching and a fallback, it is roughly 15–20 lines against Laravel's own Http client:

$joke = Http::timeout(3)
    ->get('https://api.chucknorris.io/jokes/random', ['category' => $category])
    ->throw()
    ->json('value');

That version is testable with Http::fake(), respects Laravel's configured timeouts and retries, emits events for logging, and carries zero external dependency risk. For most teams this is the right extension point — the package's real value day-to-day is as a reference for the facade-plus-config design, not as a dependency to carry into a framework upgrade next year.

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.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk