Contributing Code
A PHP library designed to simplify interaction with the dotCMS Page API. This SDK provides a clean, object-oriented interface for retrieving and working with dotCMS pages and their components.
Requirements#
- PHP 8.2 or higher
- Composer
Installation#
Install the SDK using Composer:
composer require dotcms/php-sdk
Configuration#
The SDK requires configuration to connect to your dotCMS instance:
use Dotcms\PhpSdk\Config\Config; // Create a configuration for the client $config = new Config( host: 'https://your-dotcms-instance.com', apiKey: 'YOUR_API_KEY', clientOptions: [ 'timeout' => 30 ] );
Configuration Options#
Required Parameters#
host
: Your dotCMS instance URLapiKey
: Your dotCMS API key
Optional Parameters#
-
clientOptions
: Guzzle HTTP client optionsheaders
: Custom HTTP headersverify
: SSL verification (boolean)timeout
: Request timeout in secondsconnect_timeout
: Connection timeout in secondshttp_errors
: Whether to throw exceptions for HTTP errorsallow_redirects
: Whether to follow redirects
-
logConfig
: Logging configurationlevel
: Log level (DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY)console
: Whether to output logs to consolehandlers
: Array of custom Monolog handlers
Basic Usage#
Creating a Client#
use Dotcms\PhpSdk\DotCMSClient; // Create the dotCMS client $client = new DotCMSClient($config);
Fetching a Page#
try { // Create a page request for a specific page $pageRequest = $client->createPageRequest('/', 'json'); // Get the page $pageAsset = $client->getPage($pageRequest); // Access page information echo "Page title: " . $pageAsset->page->title . "\n"; echo "Page URL: " . $pageAsset->page->pageUrl . "\n"; echo "Template name: " . $pageAsset->template->title . "\n"; // Check if page has vanity URL if ($pageAsset->vanityUrl !== null) { echo "Vanity URL: " . $pageAsset->vanityUrl->url . "\n"; echo "Forward to: " . $pageAsset->vanityUrl->forwardTo . "\n"; } } catch (\Exception $e) { echo "Error: " . $e->getMessage() . "\n"; }
Fetching Navigation#
try { // Create a navigation request $navRequest = $client->createNavigationRequest('/about-us', 2); // Get the navigation $nav = $client->getNavigation($navRequest); // Access navigation information echo "Navigation title: " . $nav->title . "\n"; echo "Navigation URL: " . $nav->href . "\n"; // Access children if available if ($nav->hasChildren()) { foreach ($nav->getChildren() as $child) { echo "- " . $child->title . " (" . $child->href . ")\n"; } } } catch (\Exception $e) { echo "Error: " . $e->getMessage() . "\n"; }
Asynchronous Requests#
// Create a page request $asyncPageRequest = $client->createPageRequest('/', 'json'); // Get the page asynchronously $promise = $client->getPageAsync($asyncPageRequest); // Add callbacks for success and failure $promise->then( function ($asyncPage) { echo "Async page title: " . $asyncPage->page->title . "\n"; if ($asyncPage->vanityUrl !== null) { echo "Vanity URL: " . $asyncPage->vanityUrl->url . "\n"; } }, function (\Exception $e) { echo "Error: " . $e->getMessage() . "\n"; } ); // Wait for the promise to complete $promise->wait();
Asynchronous Navigation Requests#
// Create a navigation request $asyncNavRequest = $client->createNavigationRequest('/', 2); // Get the navigation asynchronously $promise = $client->getNavigationAsync($asyncNavRequest); // Add callbacks for success and failure $promise->then( function ($nav) { echo "Navigation title: " . $nav['title'] . "\n"; if ($nav->hasChildren()) { foreach ($nav->getChildren() as $child) { echo "- " . $child['title'] . "\n"; } } }, function (\Exception $e) { echo "Error: " . $e->getMessage() . "\n"; } ); // Wait for the promise to complete $promise->wait();
Advanced Usage#
Customizing Page Requests#
The PageRequest
class provides several methods to customize your page requests:
$pageRequest = $client->createPageRequest('/about-us', 'json'); // Set the language ID for the request $pageRequest = $pageRequest->withLanguageId(1); // Set the mode (LIVE, WORKING, EDIT_MODE) $pageRequest = $pageRequest->withMode('WORKING'); // Set the depth of the content to retrieve (0-3) $pageRequest = $pageRequest->withDepth(2); // Set personalization options $pageRequest = $pageRequest->withPersonaId('persona_id'); // Set whether to fire rules $pageRequest = $pageRequest->withFireRules(true); // Set the host ID (Site ID) $pageRequest = $pageRequest->withHostId('48190c8c-42c4-46af-8d1a-0cd5db894797');
Note that each method returns a new instance with the updated value, so you need to reassign the result.
Customizing Navigation Requests#
The NavigationRequest
class allows you to customize your navigation requests:
// Create a navigation request with custom parameters $navRequest = $client->createNavigationRequest( path: '/about-us', // The root path to begin traversing depth: 2, // The depth of the folder tree to return (1-3) languageId: 2 // The language ID for content (e.g., 2 for Spanish) ); // Get the navigation with the custom parameters $nav = $client->getNavigation($navRequest);
Working with Page Components#
Once you have a page, you can access its components:
// Access site information echo "Site hostname: " . $page->site->hostname . "\n"; // Access template information echo "Template title: " . $page->template->title . "\n"; // Access layout information echo "Layout header: " . $page->layout->header . "\n"; // Access vanity URL if present if ($page->vanityUrl !== null) { echo "Vanity URL pattern: " . $page->vanityUrl->pattern . "\n"; echo "Forward to: " . $page->vanityUrl->forwardTo . "\n"; echo "Response code: " . $page->vanityUrl->response . "\n"; echo "Is temporary redirect: " . ($page->vanityUrl->temporaryRedirect ? 'Yes' : 'No') . "\n"; } // Access containers and contentlets foreach ($page->containers as $containerId => $container) { echo "Container ID: " . $containerId . "\n"; echo "Max Contentlets: " . $container->maxContentlets . "\n"; if (!empty($container->contentlets)) { foreach ($container->contentlets as $uuid => $contentlets) { foreach ($contentlets as $contentlet) { echo "Contentlet type: " . $contentlet->contentType . "\n"; echo "Contentlet title: " . ($contentlet->title ?? 'N/A') . "\n"; // Access additional fields using object properties foreach ($contentlet->getAdditionalProperties() as $fieldName => $fieldValue) { if (is_scalar($fieldValue)) { echo "$fieldName: $fieldValue\n"; } } } } } }
Working with Navigation Items#
The NavigationItem
class provides array access to its properties:
// Check if the navigation item is a folder if ($nav->isFolder()) { echo "This is a folder\n"; } // Check if the navigation item is a page if ($nav->isPage()) { echo "This is a page\n"; } // Access navigation properties echo "Title: " . $nav->title . "\n"; echo "URL: " . $nav->href . "\n"; echo "Type: " . $nav->type . "\n"; echo "Target: " . $nav->target . "\n"; // e.g., "_self", "_blank" echo "Order: " . $nav->order . "\n"; // Recursively process navigation tree function processNavigation($navItem, $level = 0) { $indent = str_repeat(" ", $level); echo $indent . "- " . $navItem->title . " (" . $navItem->href . ")\n"; if ($navItem->hasChildren()) { foreach ($navItem->getChildren() as $child) { processNavigation($child, $level + 1); } } } processNavigation($nav);
Using SDK Utilities#
The SDK includes a DotCmsHelper
class with common functions for rendering and working with DotCMS content:
use Dotcms\PhpSdk\Utils\DotCmsHelper; use Dotcms\PhpSdk\Model\Content\Contentlet; // Generate HTML attributes from an associative array $attrs = [ 'class' => 'my-class', 'data-id' => '123', 'disabled' => true ]; $htmlAttrs = DotCmsHelper::htmlAttributes($attrs); // Generate simple HTML for a contentlet $contentlet = new Contentlet( identifier: 'abc123', inode: 'inode123', title: 'My Content', contentType: 'Banner' ); $html = DotCmsHelper::simpleContentHtml($contentlet->jsonSerialize()); // Extract accept types from container structures $acceptTypes = DotCmsHelper::extractAcceptTypes($containerStructures); // Extract contentlets from container page $contentlets = DotCmsHelper::extractContentlets($containerPage, $uuid);
These utilities help with common tasks like:
- Generating HTML attributes safely
- Rendering contentlets with basic HTML
- Working with container structures and contentlets
- Extracting data from container pages
Data Access Patterns#
The SDK provides two ways to access data: object notation and array access. Here's when to use each:
Object Notation (->)#
Use object notation for accessing standard properties of these classes:
// Page and Site properties $page->title $page->pageUrl $site->hostname // Container properties $container->identifier $container->title $container->maxContentlets // Contentlet properties $contentlet->identifier $contentlet->title $contentlet->contentType // Navigation properties $nav->title $nav->href $nav->type
Array Access ([])#
Use array access for:
- Additional properties not explicitly defined in the class
- Accessing container contentlets by UUID
- Accessing rendered content by UUID
// Additional properties $contentlet['customField'] $page['metadata'] // Container contentlets $container->contentlets['uuid-123'] // Rendered content $container->rendered['uuid-123']
Classes That Support Both#
These classes support both object and array access:
Page
Site
Contentlet
Container
- Any class extending
AbstractModel
Classes That Only Support Object Access#
These classes only support object notation:
PageAsset
ContainerPage
NavigationItem
Layout
Template
VanityUrl
API Reference#
DotCMSClient#
The main client for interacting with the dotCMS API.
Method | Description | Parameters |
---|---|---|
__construct | Create a new client instance | Config $config |
getPage | Fetch a page synchronously | PageRequest $request |
getPageAsync | Fetch a page asynchronously | PageRequest $request |
createPageRequest | Create a new page request | string $pagePath, string $format = 'json' |
getNavigation | Fetch navigation items synchronously | NavigationRequest $request |
getNavigationAsync | Fetch navigation items asynchronously | NavigationRequest $request |
createNavigationRequest | Create a new navigation request | string $path = '/', int $depth = 1, int $languageId = 1 |
PageRequest#
Represents a request to the dotCMS Page API.
Method | Description | Parameters |
---|---|---|
__construct | Create a new page request | string $pagePath, string $format = 'json' |
withLanguageId | Set the language ID for the request | int $languageId |
withMode | Set the mode (LIVE, WORKING, EDIT_MODE) | string $mode |
withDepth | Set the depth of the content to retrieve (0-3) | int $depth |
withPersonaId | Set the persona ID for personalization | string $personaId |
withHostId | Set the host ID (Site ID) | string $hostId |
withFireRules | Set whether to fire rules | bool $fireRules |
buildPath | (Internal) Build the API path for the request | None |
buildQueryParams | (Internal) Build the query parameters for the request | None |
NavigationRequest#
Represents a request to the dotCMS Navigation API.
Method | Description | Parameters |
---|---|---|
__construct | Create a new navigation request | string $path = '/', int $depth = 1, int $languageId = 1 |
getPath | Get the path | None |
getDepth | Get the depth | None |
getLanguageId | Get the language ID | None |
buildPath | (Internal) Build the API path for the request | None |
buildQueryParams | (Internal) Build the query parameters for the request | None |
PageAsset#
Represents a complete page asset from dotCMS.
Property | Type | Description |
---|---|---|
page | Page | The Page object |
site | Site | The Site object |
template | Template | The Template object |
layout | Layout | The Layout object |
containers | array | Array of ContainerPage objects |
urlContentMap | Contentlet|null | Content map for generated pages |
viewAs | ViewAs | Visitor context information |
vanityUrl | VanityUrl|null | Optional vanity URL configuration |
ContainerPage#
Represents a container page from dotCMS.
Property | Type | Description |
---|---|---|
container | Container | The Container object |
containerStructures | array | Array of ContainerStructure objects |
rendered | array<string, string> | Rendered content keyed by UUID |
contentlets | array<string, array | Contentlets keyed by UUID |
Contentlet#
Represents a content item from dotCMS.
Property | Type | Description |
---|---|---|
identifier | string | The content identifier |
inode | string | The content inode |
title | string | The content title |
contentType | string | The content type |
additionalProperties | array<string, mixed> | Additional content properties |
Method | Description | Return Type |
---|---|---|
getAdditionalProperties | Get additional properties | array<string, mixed> |
jsonSerialize | Convert to array for JSON serialization | array<string, mixed> |
DotCmsHelper#
Utility class for common DotCMS operations.
Method | Description | Parameters | Return Type |
---|---|---|---|
htmlAttributes | Generate HTML attributes | array<string, mixed> | string |
simpleContentHtml | Generate simple HTML for content | array<string, mixed> | string |
extractAcceptTypes | Extract accept types from structures | array<ContainerStructure> | string |
extractContentlets | Extract contentlets from container | ContainerPage, string | array<Contentlet> |
Error Handling#
The SDK provides several exception classes for error handling:
Exception | Description |
---|---|
DotCMSException | Base exception class for all SDK exceptions |
ConfigException | Thrown when there's an issue with the configuration |
HttpException | Thrown when there's an HTTP error |
ResponseException | Thrown when there's an issue with the response |
Example error handling:
try { $pageAsset = $client->getPage($pageRequest); } catch (ConfigException $e) { echo "Configuration error: " . $e->getMessage() . "\n"; } catch (HttpException $e) { echo "HTTP error: " . $e->getMessage() . "\n"; echo "Status code: " . $e->getStatusCode() . "\n"; } catch (ResponseException $e) { echo "Response error: " . $e->getMessage() . "\n"; } catch (DotCMSException $e) { echo "dotCMS error: " . $e->getMessage() . "\n"; } catch (\Exception $e) { echo "General error: " . $e->getMessage() . "\n"; }
Examples#
Basic Page Example#
<?php require_once __DIR__ . '/vendor/autoload.php'; use Dotcms\PhpSdk\Config\Config; use Dotcms\PhpSdk\DotCMSClient; use Dotcms\PhpSdk\Model\Page\PageAsset; use Dotcms\PhpSdk\Model\Page\VanityUrl; // Create configuration $config = new Config( host: 'https://demo.dotcms.com', apiKey: 'YOUR_API_KEY' ); // Create client $client = new DotCMSClient($config); // Create page request $pageRequest = $client->createPageRequest('/', 'json'); // Get page $pageAsset = $client->getPage($pageRequest); // Display page information echo "Page title: " . $pageAsset->page->title . "\n"; echo "Page URL: " . $pageAsset->page->pageUrl . "\n"; // Check for vanity URL if ($pageAsset->vanityUrl !== null) { echo "Vanity URL: " . $pageAsset->vanityUrl->url . "\n"; echo "Forward to: " . $pageAsset->vanityUrl->forwardTo . "\n"; }
Basic Navigation Example#
<?php require_once __DIR__ . '/vendor/autoload.php'; use Dotcms\PhpSdk\Config\Config; use Dotcms\PhpSdk\DotCMSClient; use Dotcms\PhpSdk\Model\Navigation\NavigationItem; // Create configuration $config = new Config( host: 'https://demo.dotcms.com', apiKey: 'YOUR_API_KEY' ); // Create client $client = new DotCMSClient($config); // Create navigation request for the About Us section with depth=2 $navRequest = $client->createNavigationRequest('/about-us', 2); // Get navigation $nav = $client->getNavigation($navRequest); // Display navigation information echo "Navigation title: " . $nav->title . "\n"; // Display children if available if ($nav->hasChildren()) { echo "Children:\n"; foreach ($nav->getChildren() as $child) { echo "- " . $child->title . " (" . $child->href . ")\n"; } }
Integration with Symfony#
The SDK can be easily integrated with Symfony. See the examples/dotcms-symfony
directory for a complete example.
We Need Your Feedback!#
The SDK is in active development, and your feedback is crucial to its success. We're particularly interested in:
- Use cases and real-world scenarios
- Feature requests and improvements
- Performance feedback
- Integration challenges
- Documentation suggestions
Feel free to:
- Open issues for bugs or feature requests
- Join our community discussions
- Share your implementation experiences
- Suggest improvements to the API design
Contributing#
We welcome contributions of all kinds! Whether you're fixing bugs, adding features, or improving documentation, your help makes the SDK better for everyone.
How to Contribute#
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Make your changes
- Run the test suite (
composer check
) - Commit your changes (
git commit -m 'feat: add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Pull Requests#
We actively review and merge pull requests. To ensure a smooth process:
- Follow our coding standards
- Add tests for new features
- Update documentation
- Use conventional commit messages
- Keep PRs focused and manageable
Development Setup#
- Clone the repository
- Install dependencies:
composer install
- Run tests:
composer test
Coding Standards#
The project uses PHP-CS-Fixer for code style. Run the following commands:
- Check code style:
composer cs-check
- Fix code style:
composer cs-fix
Static Analysis#
The project uses PHPStan for static analysis:
composer phpstan
Running All Checks#
composer check
What's Next#
The SDK is actively being developed with several exciting features planned:
Template Rendering System#
We're working on a comprehensive template rendering system that will make it easier to integrate DotCMS with popular PHP frameworks:
Twig Templates#
- Pre-built templates for DotCMS layouts, containers, and content types
- Twig extensions for common DotCMS operations
Blade Templates#
- Ready-to-use Blade components for DotCMS content
- Blade directives for DotCMS-specific functionality
- Standard layouts for common page structures
- SEO-friendly markup and metadata handling
Content API Support#
- Full Content API integration for content management
- ElasticSearch Support
- Advanced search capabilities
Logging System#
- Configurable log levels (DEBUG, INFO, WARNING, ERROR, etc.)
- Multiple logging handlers (file, console, syslog)
- Context-aware logging with request/response details
Data Validation Layer#
- Schema-based validation for content types
- Custom validation rules
- Validation error handling
- Type conversion and normalization
- Cross-field validation
- Validation caching
Additional Features#
- Enhanced caching mechanisms
- Additional framework integrations
- Performance optimizations
- Extended documentation and examples
Stay tuned for updates and feel free to contribute to these upcoming features!
License#
This project is licensed under the MIT License - see the LICENSE file for details.
main
Found an issue with this documentation? Report it on GitHub