Global navigation

   Documentation Center
   eZ Studio & eZ Platform
     User Manual
     Technical Manual
     Glossary
   eZ Publish 4.x / legacy

 
eZ Publish (5.x)

eZ Publish 5.x | For eZ Platform & eZ Studio topics see Technical manual and User manual, for eZ Publish 4.x and Legacy topics see eZ Publish legacy

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Excerpt IncludeeZ Publish DocumentationeZ Publish DocumentationWe will start by going through the various ways to find and retrieve content from eZ Publish using the API. While this will be covered in further dedicated documentation, it is necessary to explain a few basic concepts of the Public API. In the following recipes, you will learn about the general principles of the API as they are introduced in individual recipes.

Table of Contents

Displaying values from a Content item

In this recipe, we will see how to fetch a Content instance from the repository, and obtain its Field's content. 

...

Code Block
languagephp
titleViewing content
linenumberstrue
$repository = $this->getContainer()->get( 'ezpublish.api.repository' );
$contentService = $repository->getContentService();
$contentTypeService = $repository->getContentTypeService();
$fieldTypeService = $repository->getFieldTypeService();

try
{
    $content = $contentService->loadContent( 66 );
    $contentType = $contentTypeService->loadContentType( $content->contentInfo->contentTypeId );
    // iterate over the field definitions of the content type and print out each field's identifier and value
    foreach( $content$contentType->contentType->fieldDefinitions as $fieldDefinition )
    {
        $output->write( $fieldDefinition->identifier . ": " );
        $fieldType = $fieldTypeService->getFieldType( $fieldDefinition->fieldTypeIdentifier );
        $field = $content->getFieldValue>getField( $fieldDefinition->identifier );

		// We use the Field's toHash() method to get readable content out of the Field
        $valueHash = $fieldType->toHash( $field->value );
        $output->writeln( $valueHash );
    }
}
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" );
}

...

Code Block
languagephp
linenumberstrue
$repository = $this->getContainer()->get( 'ezpublish.api.repository' );
$contentService = $repository->getContentService();
$contentTypeService = $repository->getContentTypeService();
$fieldTypeService = $repository->getFieldTypeService();

...

The first thing we do is use the Content Service to load a Content item using its ID, 66: $contentService->loadContent( 66 ). As you can see on the API doc page, this method expects a Content ID, and returns a Content Value Object.

Code Block
languagephp
linenumberstrue
foreach( $content$contentType->contentType->fieldDefinitions as $fieldDefinition )
{
    // ignore ezpage
    if( $fieldDefinition->fieldTypeIdentifier == 'ezpage' )
        continue;
    $output->write( $fieldDefinition->identifier . ": " );
    $fieldType = $fieldTypeService->getFieldType( $fieldDefinition->fieldTypeIdentifier );
    $fieldValue = $content->getFieldValue( $fieldDefinition->identifier );
    $valueHash = $fieldType->toHash( $fieldValue );
    $output->writeln( $valueHash );
}

...

It iterates over the Content's (Content Object) fields using the ContentType's (Content Class) FieldDefinitions (Content Class Attribute) ($content$contentType->contentType->fieldDefinitions).

For each Field Definition (Content Class Attribute), we start by displaying its identifier ($fieldDefinition->identifier). We then get the FieldType (Datatype) instance using the FieldType Service ($fieldTypeService->getFieldType( $fieldDefinition->fieldTypeIdentifier )). This method expects the requested FieldType's identifier, as a string (ezstring, ezxmltext...), and returns an eZ\Publish\API\Repository\FieldType object.

...

Info
titleLoading Content in different languages

Since we didn't specify any language code, our Field objects object is returned in the default language, depending on your language settings in ezpublish.yml. If you want to use a non-default given Content item's main language. If you'd prefer it to fall back to the SiteAccess language(s), then take advantage of TranslationHelpers. Or if you want to use an altogether different language, you can specify a language code in the getField() call:

Code Block
languagephp
$content->getFieldValue( $fieldDefinition->identifier, 'fre-FR' )

...

In this code, we introduce the LocationService. This service is used to interact with locations (eZ Publish 4 nodes). We use two methods from this service: loadLocation(), and loadLocationChildren().

Code Block
languagephp
titleLoading a location
try
{
    // load the starting location and browse
    $location = $this->locationService->loadLocation( $locationId );
    $this->browseLocation( $location, $output );
}
catch ( \eZ\Publish\API\Repository\Exceptions\NotFoundException $e )
{
    $output->writeln( "<error>No location found with id $locationId</error>" );
}
catch( \eZ\Publish\API\Repository\Exceptions\UnauthorizedException $e )
{
    $output->writeln( "<error>Current users are not allowed to read location with id $locationId</error>" );
}

As for the ContentService, loadLocation() returns a  Value Object, here a Location. Errors are handled with exceptions: NotFoundException if the Location ID couldn't be found, and UnauthorizedException if the current repository user isn't allowed to view this location.

...

Info
titleFull code

Should you need more advanced children fetching methods, the SearchService is what you are looking for.

...

Content is a central piece in the Public API. You will often need to start from a Content item, and dig in from its metadata. Basic content metadata is made available through ContentInfo objects. This Value Object mostly provides primitive fields: contentTypeId, publishedDate or mainLocationId. But it is also used to request further Content related Value Objects from various services.

...

We introduce here several new services: URLAliasService, UserService and SectionService. The concept should be familiar to you now.

...

Tip

In a command line script, the repository runs as if executed by the anonymous user. In order to identify it as a different user, you need to use the UserService as follows:

Code Block
languagephp
$administratorUser = $userService->loadUser( 14 );
$repository->setCurrentUser( $administratorUser );

This may be crucial when writing maintenance or synchronization scripts.

This is of course not required in template functions or controller code, as the HTTP layer will take care of identifying the user, and automatically set it in the repository.

...

Code Block
languagephp
titleGetting Content Locations
// show all locations of the content
$locations = $locationService->loadLocations( $contentInfo );
$output->writeln( "<info>LOCATIONS</info>" );
foreach ( $locations as $location )
{
    $urlAlias = $urlAliasService->reverseLookup( $location );
    $output->writeln( "  $location->pathString  ($urlAlias->path)" );
}

We first use LocationService::loadLocations() to get the Locations for our ContentInfo. This method returns an array of Location Value Objects. In this example, we print out the Location's path string (/path/to/content). We also use URLAliasService::reverseLookup() to get the location's main URLAlias.

Note
titleLimitations with multi-location

(version <= 5.2)

When Content has multiple Locations, note that sorting on Location properties cannot  work correctly. It's a limitation by design : SortClause\LocationPriority will not be limited to the locations under Criterion\ParentLocationId.

Info
titleLocation Search in 5.3

This limitation does not exist in Location Search. Migrating to version 5.3 adds the Location Search feature, and removes this limitation.
With Location Search, usage of Location Criterions and Sort Clauses with Content Search is deprecated. If search by Location properties is needed Location Search should be used.

 

Relations

We now want to list relations from and to our Content. Since relations are versioned, we need to feed the ContentService::loadRelations() with a VersionInfo object. We can get the current version's VersionInfo using ContentService::loadVersionInfo(). If we had been looking for an archived version, we could have specified the version number as the second argument to this method.

Code Block
languagephp
titleBrowsing a Content's relations
// show all relations of the current version
$versionInfo = $contentService->loadVersionInfo( $contentInfo );
$relations = $contentService->loadRelations( $versionInfo );
if ( count( $relations ) )
{
    $output->writeln( "<info>RELATIONS</info>" );
    foreach ( $relations as $relation )
    {
        $name = $relation->destinationContentInfo->name;
        $output->write( "  Relation of type " . $this->outputRelationType( $relation->type ) . " to content $name" );
    }
}

We can iterate over the Relation objects array we got from loadRelations(), and use these Value Objects to get data about our relations. It has two main properties: destinationContentInfo, and sourceContentInfo. They also hold the relation type (embed, common...), and the optional Field this relations is made with.

...

Code Block
languagephp
titlePrimitive object metadata
// show meta data
$output->writeln( "\n<info>METADATA</info>" );
$output->writeln( "  <info>Name:</info> " . $contentInfo->name" );
$output->writeln( "  <info>Type:</info> " .$contentInfo $contentType->contentType->identifier );
$output->writeln( "  <info>Last modified:</info> " . $contentInfo->modificationDate->format( 'Y-m-d' ) );
$output->writeln( "  <info>Published:</info> ". $contentInfo->publishedDate->format( 'Y-m-d' ) );
$output->writeln( "  <info>RemoteId:</info> $contentInfo->remoteId" );
$output->writeln( "  <info>Main Language:</info> $contentInfo->mainLanguageCode" );
$output->writeln( "  <info>Always available:</info> " . ( $contentInfo->alwaysAvailable ? 'Yes' : 'No' ) );

Owning user

We can use UserService::loadUser() with content ownerId property of our ContentInfo to load the Content's owner as a User Value Object.

Code Block
languagephp
$owner = $userService->loadUser( $contentInfo->ownerId );
$output->writeln( "  <info>Owner:</info> " . $owner->contentInfo->name );

...

To conclude we can also iterate over the Content's version, as VersionInfo Value Objects.

Code Block
languagephp
$versionInfoArray = $contentService->loadVersions( $contentInfo );
if ( count( $versionInfoArray ) )
{
    $output->writeln( "\n<info>VERSIONS</info>" );
    foreach ( $versionInfoArray as $versionInfo )
    {
        $creator = $userService->loadUser( $versionInfo->creatorId );
        $output->write( "  Version $versionInfo->versionNo " );
        $output->write( " by " . $creator->contentInfo->name );
        $output->writeln( " " . $this->outputStatus( $versionInfo->status ) . " " . $versionInfo->initialLanguageCode );
    }
}

We use the ContentService::loadVersions() method, and get an array of VersionInfo objects.

...

In this section we will cover how the SearchService can be used to search for ContententContent, by using a Query and a combinations of Criteria you will get a SearchResult object back containing list of Content and count of total hits. In the future this object will also include facets, spell checking and "more like this" when running on a backend that supports it (for instance Solr).

...

We introduce here a new object: Query. It is used to build up a Content query based on a set of Criterion objects.

Code Block
languagephp
titleversion <= Ez Publish 5.2
$query = new \eZ\Publish\API\Repository\Values\Content\Query();
$query->criterion = new Query\Criterion\FullText( $text );
Code Block
languagephp
titleversion >= Ez Publish 5.3
$query = new \eZ\Publish\API\Repository\Values\Content\Query();
$query->filter = new Query\Criterion\FullText( $text );

 

Multiple criteria can be grouped together using "logical criteria", such as LogicalAnd or LogicalOr. Since in this case we only want to run a text search, we simply use a FullText criterion object.

Info

The full list of criteria available can be seen at: https://github.com/found on your installation in the following directory vendor/ezsystems/ezpublish-kernel/tree/master/eZ/Publish/API/Repository/Values/Content/Query/Criterion

 

. Additionally you may look at integration tests like vendor/ezsystems/ezpublish-kernel/eZ/Publish/API/Repository/Tests/SearchServiceTest.php for more details on how these are used.

NB: Be aware that the links point to code in the upcoming version (master) and might not represent the criteria in your eZ Publish version.

Note
titleCriterion independence before 5.3

Note the criterion independance : Criterion are not related to each other by design and this can lead to a limitation in Content Search. See an example in the Criterion Independance example page.

Running the search query and using the results

The Query object is given as an argument to SearchService::findContent(). This method returns a SearchResult object. This object provides you with various information about the search operation (number of results, time taken, spelling suggestions, or facets, as well as of course, the results themselves.

...

The searchHits properties of the SearchResult object is an array of ContentInfo objects SearchHit objects. In valueObject property of SearchHit, you will find the Content object that match the given Query.

Tip: If you you are searching using a unique identifier, for instance using the content id or content remote id criterion, then you can use SearchService::findSingle(), this takes a Criterion and returns a single Content item, or throws NotFound exception if none is found.

...

Code Block
languagephp
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
use eZ\Publish\API\Repository\Values\Content;
 
// [...]
 
$query = new Query();
$criterion1 = new Criterion\Subtree( '/location/path_string' )$locationService->loadLocation( 2 )->pathString );
$criterion2 = new Criterion\ContentTypeIdContentTypeIdentifier( 1'folder' );
$query->criterion = new Criterion\LogicalAnd(
    array( $criterion1, $criterion2 )
);
 
$result = $searchService->findContent( $query );

A Subtree criterion limits the search to the subtree with path_string /location/path_stringpathString, which looks like: /1/2/. A ContentTypeId Criterion to limit the search to Content of ContentType 1. Those two criteria are grouped with a LogicalAnd operator. The query is executed as before, with SearchService::findContent().

...

Code Block
languagephp
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
use eZ\Publish\API\Repository\Values\Content;
 
// [...]
 
$query = new Query();
$query->criterion = new Criterion\LogicalAnd(
    array(
        new Criterion\ParentLocationId( 2 ),
        new Criterion\LogicalOr(
            array(
                new Criterion\ContentTypeIdContentTypeIdentifier( 1'folder' ),
                new Criterion\ContentTypeId( 2 )
            )
        )
    )
);
 
$result = $searchService->findContent( $query );

ParentLocationId criterion limits the search to the children of location 2. An array of "ContentTypeId" Criteria to limit the search to Content of ContentType's with id 1 or 2 grouped in a LogicalOr operator. Those two criteria are grouped with a LogicalAnd operator. As always the query is executed as before, with SearchService::findContent().

...

The above example is fine, but it can be optimized a bit by taking advantage of the fact that all filter criteria support being given an array of values (IN operator) instead of as single value (EQ operator).

Code Block
languagephp
titleeZ Publish 5.0
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
use eZ\Publish\API\Repository\Values\Content;
 
// [...]
 
$query = new Query();
$query->criterion = new Criterion\LogicalAnd(
    array(
        new Criterion\ParentLocationId( 2 ),
        new Criterion\ContentTypeId( array( 1, 2 ) )
    )
);
 
$result = $searchService->findContent( $query );

Or if If your on eZ Publish 5.1+ you can use the new ContentTypeIdentifier Criterion:

Code Block
languagephp
titleeZ Publish 5.1+ (2013.01+)
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
use eZ\Publish\API\Repository\Values\Content;
 
// [...]
 
$query = new Query();
$query->criterion = new Criterion\LogicalAnd(
    array(
        new Criterion\ParentLocationId( 2 ),
        new Criterion\ContentTypeIdentifier( array( 'article', 'folder' ) )
    )
);
 
$result = $searchService->findContent( $query );

...

In many cases you might need the number of contents Content items matching a search, but with no need to do anything else with the results.
Thanks to the fact that the "searchHits" property of the SearchResult object always refers to the total amount, it is enough to run a standard search and set $limit to 0. This way no results will be retrieved, and the search will not be slowed down, even when the number of matching results is huge.

...

Code Block
languagephp
use eZ\Publish\API\Repository\Values\Content\Query;
 
// [...]
 
$query = new Query();
$query->limit = 0;
 
// [...] ( Add criteria as shown above )
 
$resultCount = $searchService->findContent( $query )->searchHits>totalCount;