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

Mediawikiapi Laravel Package

starcitizenwiki/mediawikiapi

A PHP package for working with the MediaWiki API, built for the Star Citizen Wiki. It offers convenient methods for querying wiki pages, search, and related data in Laravel or standalone PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package via Composer:

    composer require starcitizenwiki/mediawikiapi
    

    The package auto-discovers its service provider. If not, register StarCitizenWiki\MediaWikiApi\Providers\MediaWikiApiServiceProvider (or similar — check composer.json for the actual class name) manually in config/app.php.

  2. Publish the config and inspect it before anything else:

    php artisan vendor:publish --tag=mediawikiapi-config
    

    This gives you the file to add your wiki base URL, OAuth consumer key/secret, and access token values to config/mediawikiapi.php (or equivalent).

  3. Generate OAuth credentials on the target wiki. This is the step people skip. MediaWiki's OAuth is not a simple bearer token — you register a consumer at Special:OAuthConsumerRegistration on the wiki itself, get a consumer key/secret, then do the OAuth handshake to obtain an access token stored per-user. The package wraps that handshake, but the wiki-side registration is manual.

  4. Store credentials in .env, never in the config file directly. Wire the config keys to env vars like MEDIAWIKI_BASE_URL, MEDIAWIKI_CONSUMER_KEY, MEDIAWIKI_CONSUMER_SECRET, MEDIAWIKI_ACCESS_TOKEN.

  5. First use case — read a page to confirm the connection works before trying to write:

    use StarCitizenWiki\MediaWikiApi\Facades\MediaWikiApi;
    
    $page = MediaWikiApi::getPage('Main Page');
    

    If the response is empty or throws, the URL or OAuth credentials are wrong — not an API bug. Verify the base URL points at the wiki root (e.g. https://wiki.example.com), not /api.php.

  6. First write — authenticate, then edit a sandbox page:

    MediaWikiApi::edit('Sandbox/Test', 'Hello from Laravel', 'Testing');
    

    MediaWiki will reject edits from a consumer that lacks the edit grant on its OAuth registration, so double-check grants on Special:OAuthConsumerRegistration.

  7. Then reach for the fluent query builder for anything beyond the convenience methods. As of v1.0.2 you can set MediaWiki API parameters by calling them as methods, e.g. $query->rvprop('content'). This maps one-to-one onto the action=query parameter names, so you can read the MediaWiki API docs and use the parameter names verbatim.

Implementation Patterns

Wrap the client behind your own interface. This is a small, single-maintainer package. Don't leak MediaWikiApi calls directly into controllers. Create a WikiClient interface, implement it with the package, and swap it out later if the package stalls:

interface WikiClient {
    public function page(string $title): string;
    public function save(string $title, string $content, string $summary): void;
}

final class MediaWikiClient implements WikiClient { /* delegates to the facade */ }

Use constructor injection, not the facade, in services. The facade is convenient in Tinker and one-off commands but ties your code to the container. In application services:

public function __construct(private MediawikiApi $wiki) {}

Use the fluent property setters for anything the convenience methods don't cover. Since v1.0.2, properties are set by calling them as methods. This is the idiomatic way to pass through MediaWiki's module-specific parameters (rvprop, rvslots, rvlimit, srwhat, list, prop, …):

$query = MediaWikiApi::query()
    ->prop('revisions')
    ->rvprop('content|ids|timestamp')
    ->rvslots('main')
    ->titles($title);

$response = $query->get();

Because the method name is the API parameter name, prefer mirroring the MediaWiki docs exactly rather than inventing wrappers — it keeps the translation obvious to the next developer and to future-you reading api.php documentation. Build your own typed DTOs at the boundary so callers never touch raw parameter strings.

Model edits as idempotent operations. MediaWiki's edit endpoint supports baseRevId / baserevid to detect edit conflicts. If the package exposes it (or you can set it via a property method), pass the last known revision. If it doesn't, capture revision IDs from getPage and treat every write as "read → compare → write" rather than blind overwrite:

$current = $this->wiki->getPage($title);
if ($current->content_revision !== $expectedRevision) {
    throw new EditConflict($title);
}
$this->wiki->edit($title, $newContent, $summary);

Run batch work in queued jobs with rate limiting. MediaWiki will throttle OAuth consumers. Use Laravel's RateLimited job middleware:

public function middleware(): array {
    return [new RateLimited('mediawiki')];
}

Define the limiter in a service provider (e.g. 12/min for edits, more for reads).

Categorize errors. The package's exceptions likely collapse HTTP errors into a generic exception. Catch them at the boundary and translate into domain exceptions (PageNotFound, PermissionDenied, EditConflict, TokenError) so callers can react. MediaWiki returns a JSON error.code field (badtoken, protectedpage, editconflict, readapidenied) — map those.

For OAuth handshake flows (user authorises your app on the wiki): the package supports the redirect/verification dance. Store the request token in the session or a short-lived cache row, then exchange for the access token on the callback route. Treat the access token as a per-user secret — don't share it across the app.

Uploads need multipart form data and a CSRF token from action=query&meta=tokens&type=csrf. If the package handles it, use upload(); if not, you'll need to drop down to Http::withToken(...)->asMultipart() against /api.php directly.

Testing. Point the config at a fixture mode or a local MediaWiki docker container (mediawiki official image). Stub the service in unit tests and reserve integration tests for a live or dockerised wiki. The fluent setters make it worth asserting on the outgoing parameter set, not just the parsed response — that's where typos hide.

Gotchas and Tips

  • Recent releases are small and incremental. v1.0.2 adds fluent property setters; it isn't a rewrite. The package is still single-maintainer and lightly used, so treat each release as "check the changelog, check the diff" rather than assuming a maintenance cadence. Pin the version in composer.json and review upgrade diffs — the surface area is small enough to read in full.

  • Fluent property setters are magic __call. $query->rvprop('content') almost certainly resolves through __call into an internal parameter bag. Consequences: no IDE autocompletion, no static analysis, and a typo ($query->rvprops(...)) doesn't fail loudly — it silently becomes an unknown parameter that MediaWiki either ignores or errors on with a confusing unknown_parameter / unrecognized parameter message. Keep the parameter names next to the MediaWiki docs version you target, and validate the outgoing parameter bag in tests.

  • The fluent API sets parameters; it doesn't validate them. rvprop('content|ids') pipe-separated vs array, and rvlimit as an int vs string, are your responsibility. MediaWiki is strict about types and formats in places — mismatches come back as badvalue, not a PHP type error.

  • OAuth 1.0a, not 2.0. MediaWiki still uses OAuth 1.0a for its consumer protocol. That means HMAC-SHA1 signatures, nonces, and timestamps. Clock skew between your server and the wiki will break signatures with opaque "signature mismatch" errors — run ntpd on servers.

  • Bot passwords vs OAuth. For simple automation on a wiki you control, action=login with a bot password is far simpler than OAuth. OAuth is only worth it when (a) you represent users, or (b) the wiki forbids bot passwords. Don't reach for OAuth by default.

  • Special:OAuthConsumerRegistration grants matter. A consumer with only read cannot edit; a consumer with only basic cannot identify the user. If edits silently 403 or return permissiondenied, re-check grants before debugging code.

  • CSRF tokens expire and must be refetched per-session, not per-app. If you cache a token across users, edits will fail with badtoken. Fetch a fresh token immediately before each write, or cache per-session with a short TTL.

  • The base URL is the wiki root, not /api.php. A wrong URL typically produces an HTML page (the wiki's homepage) that fails JSON decoding, which surfaces as a confusing parse error. Log the raw response body when debugging.

  • No pagination helper guarantee. MediaWiki's action=query returns continue tokens for large result sets. If the package's list methods don't loop on continue, you'll silently get only the first batch (usually 50 or 500). Verify with a category containing more than 50 members. If you're building the query fluently, you own the continue loop yourself — check for continue in the response and merge batches.

  • Rate limits and maxlag. Send maxlag=5 on writes so MediaWiki rejects the request cleanly (HTTP 503) rather than queueing it on a replica lag. Also log X-RateLimit-* headers if the wiki sets them. With the fluent setters, maxlag is just another property to set on the query.

  • Content models. Editing wikitext is fine; editing json, css, javascript, or Scribunto pages requires the right contentmodel and contentformat in the payload. The package may default to wikitext — you'll need to pass the model explicitly.

  • text vs appendtext vs prependtext. A common bug: appending sections by re-sending the whole page. Use the append variant to avoid edit conflicts and to keep diffs small.

  • Extension points are thin. Expect config + service override only. If you need custom behaviour (retry policy, circuit breaker, metrics), decorate your own service around the package rather than extending it. That's also your escape hatch if the package is abandoned — the wrapper survives, the implementation swaps.

  • Log the raw API payload at debug level during onboarding. The package's exception messages are unlikely to include the error.info MediaWiki returns; you'll want it when diagnosing protectedpage, spamdetected, abusefilter-disallowed, readonly, or a parameter typo introduced via a fluent setter.

  • No dependents means no community. There's no StackOverflow tail, no other projects to crib patterns from. Budget time to read the package source (it's small — likely under 2k lines) and vendor it with --prefer-source so it's browsable in vendor/. The fluent setter change in v1.0.2 is a good excuse to read exactly how __call resolves parameters.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console