Introduction
The public API will give you an easy access to the eZ Publish content repository. This repository is the core component that manages content, locations (former Nodesnodes in eZ Publish 4.x), sections, content types (former Content Classes in eZ Publish 4.x), users, user groups, users and roles. It also provides a new, clear interface for plugging in custom field types (former Datatypesdatatypes in eZ Publish 4.x).
The public API is built on top of a layered architecture, including a new persistence layer for abstracting the storage functionalitypersistence API that abstracts storage. By using the public API, you are sure that your applications code will be forward compatible with future releases based on enhanced, scalable and high-performance storage engines. Applications based on the public API are also fully backwards compatible by using the included storage engine based on the current kernel and database model.
Receipt 1 - Setting up a sample commandline symfony bundle which uses the public API
This receipt shows how to setup a simple symfony bundle with a commandline script using the public API. The command is executable within the app/console and dumps a content object for a given content id.
Go to the eZ publish installation
cd <ezpublish installation root>
Generate a new Bundle
php app/console generate:bundle
Now follow the instructions. This will create a bundle eZ/Publish/Bundle/CookBookBundle in the src directory of the installation root.
Code Block | ||
---|---|---|
| ||
Welcome to the Symfony2 bundle generator
Your application code must be written in bundles. This command helps
you generate them easily.
Each bundle is hosted under a namespace (like Acme/Bundle/BlogBundle).
The namespace should begin with a "vendor" name like your company name, your
project name, or your client name, followed by one or more optional category
sub-namespaces, and it should end with the bundle name itself
(which must have Bundle as a suffix).
See http://symfony.com/doc/current/cookbook/bundles/best_practices.html#index-1 for more
details on bundle naming conventions.
Use / instead of \ for the namespace delimiter to avoid any problem.
Bundle namespace: eZ/Publish/Bundles/CookbookBundle
In your code, a bundle is often referenced by its name. It can be the
concatenation of all namespace parts but it's really up to you to come
up with a unique name (a good practice is to start with the vendor name).
Based on the namespace, we suggest eZPublishBundlesCookbookBundle.
Bundle name [eZPublishBundlesCookbookBundle]:
The bundle can be generated anywhere. The suggested default directory uses
the standard conventions.
Target directory [.../ezpublish5/src]:
Determine the format to use for the generated configuration.
Configuration format (yml, xml, php, or annotation) [annotation]: yml
To help you get started faster, the command can generate some
code snippets for you.
Do you want to generate the whole directory structure [no]? yes
Summary before generation
You are going to generate a "eZ\Publish\Bundles\CookbookBundle\eZPublishBundlesCookBookBundle" bundle
in ".../ezpublish5/src/" using the "yml" format.
Do you confirm generation [yes]? yes
Bundle generation
Generating the bundle code: OK
Checking that the bundle is autoloaded: OK
Confirm automatic update of your Kernel [yes]? yes
Enabling the bundle inside the Kernel: OK
Confirm automatic update of the Routing [yes]? yes
Importing the bundle routing resource: OK
You can now start using the generated code!
|
Add a Command directory to the bundle
cd <ezpublish installation root>/eZ/Publish/Bundle/CookbookBundle
mkdir Command
add the following class file CookbookCommand.php in the directory Command
Code Block | ||||
---|---|---|---|---|
| ||||
<?php
/**
* File containing the CookBookCommand class.
*
* @copyright Copyright (C) 2012 eZ Systems AS. All rights reserved.
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
* @version //autogentag//
*/
namespace eZ\Publish\Bundles\CookBookBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
class CookBookCommand extends ContainerAwareCommand
{
/**
* This method override configures on input argument for the content id
*/
protected function configure()
{
$this->setName( 'cookbook:run' )->setDefinition(
array(
new InputArgument( 'contentId', InputArgument::REQUIRED, 'An existing content id' )
)
);
}
/**
* execute the command
* @param InputInterface $input
* @param OutputInterface $output
*/
protected function execute( InputInterface $input, OutputInterface $output )
{
// fetch the input argument
$contentId = $input->getArgument( 'contentId' );
// get the repository from the di container
$repository = $this->getContainer()->get( 'ezpublish.api.repository' );
// get the content service from the repsitory
$contentService = $repository->getContentService();
try
{
// print out the content info for the given content id
print_r( $contentService->loadContentInfo( $contentId ) );
}
catch( \eZ\Publish\API\Repository\Exceptions\NotFoundException $e )
{
// if the id is not found
$output->writeln( "No content with id $contentId" );
}
catch( \eZ\Publish\API\Repository\Exceptions\UnauthorizedException $e )
{
// not allowed to read this content
$output->writeln( "Anonymous users are not allowed to read content with id $contentId" );
}
}
}
|
run f.e.
php app/console cookbook:run 57
Receipt 2 - Creating a content type group
This snippet creates a content type group for a given identifier.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
$contentTypeService = $repository->getContentTypeService();
try
{
// instanciate a create struct
$groupCreate = $this->contentTypeService->newContentTypeGroupCreateStruct($groupIdentifier);
// call service method
$contentTypeGroup = $this->contentTypeService->createContentTypeGroup( $groupCreate );
// print out the group
print_r($contentTypeGroup);
}
catch( \eZ\Publish\API\Repository\Exceptions\UnauthorizedException $e )
{
// react on permission denied
$output->writeln($e->getMessage());
}
catch( \eZ\Publish\API\Repository\Exceptions\ForbiddenException $e )
{
// react on identifier already exists
$output->writeln($e->getMessage());
} |
If this snipped is run with the same init code from receipt 1 we will get an UnauthorizedException.
The solution is described in the next receipt.
Receipt 3 - Setting the user for authorizing actions
By default the repository assumes the anonymous user is acting. To change this the following code can be executed
Code Block | ||||
---|---|---|---|---|
| ||||
// get the user service from the repository
$userService = $repository->getUserService();
// load user by credentials
$user = $userService->loadUserByCredentials($user,$password);
// set user in repository
$repository->setCurrentUser($user); |
If the user is identified by other mechanisms the user also can be loaded by its id via the service method
$userService->loadUser($id)
Receipt 4 - Creating a content type
With this snipped a content type with two fields of type 'ezstring' is created.
Code Block | ||||
---|---|---|---|---|
| ||||
// get content type service from repository
$contentTypeService = $repository->getContentTypeService();
// load the content type group
try
{
$contentTypeGroup = $contentTypeService->loadContentTypeGroupByIdentifier($groupIdentifier);
}
catch(\eZ\Publish\API\Repository\Exceptions\NotFoundException $e)
{
$output->writeln("content type group with identifier $groupIdentifier not found");
return;
}
// instanciate a ContentTypeCreateStruct with the given content type identifier
$contentTypeCreateStruct = $contentTypeService->newContentTypeCreateStruct($contentTypeIdentifier );
// the main language code for names and description
$contentTypeCreateStruct->mainLanguageCode = 'eng-GB';
// the name schema for generating the content name by using the title attribute
$contentTypeCreateStruct->nameSchema = '<title>';
// set names for the content type
$contentTypeCreateStruct->names = array(
'eng-GB' => $contentTypeIdentifier . 'eng-GB',
'ger-DE' => $contentTypeIdentifier . 'ger-DE',
);
// set description for the content type
$contentTypeCreateStruct->descriptions = array(
'eng-GB' => 'Description for ' . $contentTypeIdentifier . 'eng-GB',
'ger-DE' => 'Description for ' . $contentTypeIdentifier . 'ger-DE',
);
/********************** add fields ***************************************/
// add a title field
$titleFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct('title', 'ezstring');
// set names and description for display
$titleFieldCreateStruct->names = array('eng-GB' => 'Title','ger-DE' => 'Titel',);
$titleFieldCreateStruct->descriptions = array('eng-GB' => 'The Title','ger-DE' => 'Der Titel');
// set an group for the field
$titleFieldCreateStruct->fieldGroup = 'content';
// set position inside the content type
$titleFieldCreateStruct->position = 1;
// enable translation
$titleFieldCreateStruct->isTranslatable = true;
// require this field to set on content creation
$titleFieldCreateStruct->isRequired = true;
// enabled to find field via content search
$titleFieldCreateStruct->isSearchable = true;
// add field definition to content create struct
$contentTypeCreateStruct->addFieldDefinition( $titleFieldCreateStruct );
// add a body field
$bodyFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('body', 'ezstring');
// set names and description for display
$bodyFieldCreate->names = array('eng-GB' => 'Body','ger-DE' => 'Text');
$bodyFieldCreate->descriptions = array('eng-GB' => 'Description for Body','ger-DE' => 'Beschreibung Text');
$bodyFieldCreate->fieldGroup = 'content';
$bodyFieldCreate->position = 2;
$bodyFieldCreate->isTranslatable = true;
$bodyFieldCreate->isRequired = true;
$bodyFieldCreate->isSearchable = true;
// add field definition to content create struct
$contentTypeCreateStruct->addFieldDefinition( $bodyFieldCreate );
// set the content type group for the content type
$groups = array($contentTypeGroup);
// start a transaction
$repository->beginTransaction();
try
{
// create the content type - the returned content type is in status DRAFT
$contentTypeDraft = $contentTypeService->createContentType($contentTypeCreateStruct,$groups);
// publish the content type draft
$contentTypeService->publishContentTypeDraft($contentTypeDraft);
// commit the transaction
$repository->commit();
}
catch( \eZ\Publish\API\Repository\Exceptions\UnauthorizedException $e )
{
// react on permission denied
$output->writeln($e->getMessage());
$repository->rollback();
}
catch( \eZ\Publish\API\Repository\Exceptions\ForbiddenException $e )
{
// react on identifier already exists
$output->writeln($e->getMessage());
}
catch( \Exception $e )
{
$output->writeln($e->getMessage());
$repository->rollback();
}
} |
Receipt 5 - Creating content
In this receipt content is created under a given parent location. It is assumed that the loaded content type is the one created in receipt 4.
Code Block | ||||
---|---|---|---|---|
| ||||
// get the content service from the repository
$contentService = $repository->getContentService();
// get the location service from the repsitory
$locationService = $repository->getLocationService();
// get the user service from the repsitory
$contentTypeService = $repository->getContentTypeService();
try
{
// load the content type with identifier
$contentType = $contentTypeService->loadContentTypeByIdentifier($contentTypeIdentifier);
// instanciate a location create struct
$locationCreateStruct = $locationService->newLocationCreateStruct($parentLocationId);
// instanciate a content creation struct
$contentCreateStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
// set title field
$contentCreateStruct->setField('title',$title);
// set body field
$contentCreateStruct->setField('body', $body);
// create a draft using the content and location create structs
$draft = $contentService->createContent($contentCreateStruct, array($locationCreateStruct));
// publish the content draft
$content = $contentService->publishVersion($draft->versionInfo);
// print out the content
print_r($content);
}
catch(\eZ\Publish\API\Repository\Exceptions\NotFoundException $e)
{
// react on content type or location not found
$output->writeln($e->getMessage());
}
catch(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException $e)
{
// react on remote id exists already
$output->writeln($e->getMessage());
}
catch(\eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException $e)
{
// react on a field is not valid
$output->writeln($e->getMessage());
}
catch(\eZ\Publish\API\Repository\Exceptions\ContentValidationException $e)
{
// react on a required field is missing or empty
$output->writeln($e->getMessage());
}
} |
Receipt 6 - Updating Content
In this receipt the previously created content is updated with a new title and body in the same language
Code Block | ||||
---|---|---|---|---|
| ||||
try
{
// load the content info for the given id
$contentInfo = $contentService->loadContentInfo($contentId);
// create a draft from the current published version
$contentDraft = $contentService->createContentDraft($contentInfo);
// instanciate a content update struct
$contentUpdateStruct = $contentService->newContentUpdateStruct();
// set language for new version
$contentUpdateStruct->initialLanguageCode = 'eng-GB';
// set fields
$contentUpdateStruct->setField( 'title', $newtitle );
$contentUpdateStruct->setField( 'body', $newbody );
// update draft
$contentDraft = $contentService->updateContent($contentDraft->versionInfo, $contentUpdateStruct);
// publish draft
$content = $contentService->publishVersion($contentDraft->versionInfo);
print_r($content);
}
catch(\eZ\Publish\API\Repository\Exceptions\NotFoundException $e)
{
// react on content type not found
$output->writeln($e->getMessage());
}
catch(\eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException $e)
{
// react on a field is not valid
$output->writeln($e->getMessage());
}
catch(\eZ\Publish\API\Repository\Exceptions\ContentValidationException $e)
{
// react on a required field is missing or empty
$output->writeln($e->getMessage());
}
} |
Receipt 7 - Translating content
It is the same code as for updating (see Receipt 6). The initial language should be set to the translation language.
Code Block | ||||
---|---|---|---|---|
| ||||
// set language for new version
$contentUpdateStruct->initialLanguageCode = $newLanguage;
// set fields
$contentUpdateStruct->setField( 'title', $newtitle );
$contentUpdateStruct->setField( 'body', $newbody );
|
Receipt 8 - Multiple translations at once
It is possible to to make an update in content with more than one language. But there is a restriction - only one language can be assigned to the newly created version (which is displayed in the 4.x admin GUI in the translations column).
Code Block | ||||
---|---|---|---|---|
| ||||
// set one language for new version
$contentUpdateStruct->initialLanguageCode = 'fra-FR';
// set fields for german - here the language has to be passed in third argument
$contentUpdateStruct->setField( 'title', $newgermantitle, 'ger-DE' );
$contentUpdateStruct->setField( 'body', $newgermanbody, 'ger-DE' );
// set fields for french
$contentUpdateStruct->setField( 'title', $newfrenchtitle);
$contentUpdateStruct->setField( 'body', $newfrenchbody);
|
About this Cookbook
The objective of this Public API Cookbook is to progressively guide you through useful, everyday business logic, using the API in concrete recipes: obtaining a Location from a Content, fetching a set of Content, creating a User, and so on.
For each recipe, newly introduced elements will be explained in detail, including the required API components (services, value objects...).
Info |
---|
Did we forget an important recipe ? Let us know in the comments. |
Suggested tools
In addition to this cookbook, we strongly recommend that you use a full featured PHP IDE, such as Eclipse or PhpStorm. It will provide you information on every piece of code you use, including objects and classes documentation. We have paid very careful attention to PHPDoc throughout this API, and such a tool is a very valuable help when using this API.
On top of this, generated public API documentation can be found online, in various formats:
Children Display |
---|