Official PHP SDK for the Wue CMS.
Sibling to @wuemv/content-sdk (JS/TS).
Same API surface, idiomatic PHP — typed value objects, Stripe-style resource
methods, PSR-18 transport.
composer require wuemv/content-sdk-phpRequires PHP 8.4+.
Using Laravel? Install
wuemv/content-sdk-laravelinstead for a service provider,Wuefacade, andconfig/wue.php.
use Wuemv\ContentSdk\Client;
$wue = new Client(
apiKey: 'wue_...', // bearer token from CMS settings
siteId: 'portfolio', // optional, for clarity in your code
baseUrl: 'https://your-wue-instance.com/api', // API root — INCLUDE /api suffix
);
// Health check / setup confirmation
$health = $wue->ping->check();
// → ['ok' => true, 'api_version' => 'v1', 'site' => [...], 'server_time' => '...']
// Schema discovery
$types = $wue->contentTypes->list();
foreach ($types as $ct) {
echo $ct->slug; // 'blog', 'product', ...
echo $ct->name;
foreach ($ct->fields as $field) {
echo " - {$field->key} ({$field->type})";
}
}
// Single content type
$blog = $wue->contentTypes->retrieve('blog');
// List entries
$posts = $wue->entries->list('blog');
foreach ($posts as $post) {
echo $post->slug; // typed static property
echo $post->fields->string('title'); // typed dynamic accessor
echo $post->fields->date('published_at'); // ?DateTimeImmutable
echo $post->fields['body']; // array access also works
}
// Single entry
$post = $wue->entries->retrieve('blog', 'hello-world');Running against a local Herd / self-signed CMS instance? Pass a Guzzle client with SSL verification off:
use GuzzleHttp\Client as GuzzleClient;
$wue = new Client(
apiKey: '...',
baseUrl: 'https://cms.yoursite.test/api',
httpClient: new GuzzleClient(['verify' => false]),
);Don't disable verification in production — your trusted CA chain handles real certs.
For full IDE + PHPStan typing over your site's actual content types, generate typed Entry classes from the live schema:
vendor/bin/wue-types \
--api-key=$WUE_API_KEY \
--base-url=$WUE_BASE_URL \
--output=src/Wue \
--namespace='App\Wue'This produces three kinds of output:
src/Wue/
├── ContentType.php ← enum { Blog = 'blog', Product = 'product', ... }
├── BlogEntry.php ← typed: title(), excerpt(), publishedAt(), ...
└── ProductEntry.php
Then in your code:
use App\Wue\BlogEntry;
use App\Wue\ContentType;
// Pass the enum — the SDK hydrates into BlogEntry, not generic Entry
$posts = $wue->entries->list(ContentType::Blog);
foreach ($posts as $post) {
/** @var BlogEntry $post */
echo $post->title(); // string, type-safe
echo $post->publishedAt()?->format('Y-m-d');
echo $post->slug; // inherited from Entry
}The CLI is env-driven too — WUE_API_KEY, WUE_BASE_URL,
WUE_OUTPUT_DIR, WUE_NAMESPACE, WUE_VERIFY_SSL=0 are all honoured.
Recommended: run in CI to keep your committed types in sync with production schema.
The SDK's FieldBag and the codegen tool both understand these field
types:
| Wue field type | FieldBag accessor | PHP type |
|---|---|---|
text, longtext, richtext, string, media, url, email, select |
string() |
?string |
number |
float() |
?float |
integer, int |
int() |
?int |
boolean, bool |
bool() |
bool |
date, datetime |
date() |
?DateTimeImmutable |
json |
get() |
mixed |
| unknown | string() (fallback) |
?string |
The SDK throws a typed exception hierarchy:
Wuemv\ContentSdk\Exception\ContentSdkException
├── ConfigurationException ← bad SDK setup (missing api key, etc.)
├── ConnectionException ← network failure
└── ApiException ← any 4xx/5xx response
├── AuthenticationException ← 401
├── PermissionException ← 403
├── NotFoundException ← 404
├── ValidationException ← 422 (with field errors)
└── RateLimitException ← 429
try {
$wue->ping->check();
} catch (\Wuemv\ContentSdk\Exception\AuthenticationException $e) {
// Invalid API key
} catch (\Wuemv\ContentSdk\Exception\ContentSdkException $e) {
// Anything else from the SDK
}The SDK accepts any PSR-18 HTTP client via the httpClient: constructor
arg. Use Guzzle's MockHandler for unit tests, or your own fake:
$mock = new GuzzleHttp\Handler\MockHandler([
new GuzzleHttp\Psr7\Response(200, [], '{"ok": true}'),
]);
$client = new Wuemv\ContentSdk\Client(
apiKey: 'wue_test',
baseUrl: 'https://api.example.com',
httpClient: new GuzzleHttp\Client([
'handler' => GuzzleHttp\HandlerStack::create($mock),
]),
);- ✅ Client, Transport, exception hierarchy
- ✅ Ping (health check)
- ✅ ContentTypes (
list,retrieve) - ✅ Entries (
list,retrieve) — read-only - ✅ Codegen tool (
vendor/bin/wue-types) — generatesContentTypeenum + typed Entry subclasses - ⏳ Entries mutations (create / update / delete / publish)
- ⏳ Media (upload / list / delete)
- ⏳ Submissions (form inbox)
- ⏳ Webhook signature verifier + typed event objects
composer install
composer test # pest
composer format # pint
composer analyse # phpstanMIT