- Created by Dominika Kurek, last modified on Jun 23, 2016
In this chapter, we will see two ways of customizing eZ Platform: command line scripts (for import scripts, for instance), and custom controllers.
Symfony bundle
In order to test and use Public API code, you will need to build a custom bundle. Bundles are Symfony's extensions, and are therefore also used to extend eZ Platform. Symfony 2 provides code generation tools that will let you create your own bundle and get started in a few minutes.
In this chapter, we will show how to create a custom bundle, and implement both a command line script and a custom route with its own controller action and view. All shell commands assume that you use some Linux shell, but those commands would of course also work on Windows systems.
Generating a new bundle
First, change the directory to your eZ Platform root.
Then use the app/console application with the generate:bundle
command to start the bundle generation wizard.
Let's follow the instructions provided by the wizard. Our objective is to create a bundle named
EzSystems/Bundles/CookBookBundle
, located in the src
directory.
The wizard will first ask about our bundle's namespace. Each bundle's namespace should feature a vendor name (in our own case: EzSystems
), optionally followed by a sub-namespace (we could have chosen to use Bundle
), and end with the actual bundle's name, suffixed with Bundle: CookbookBundle
.
You will then be asked about the Bundle's name, used to reference your bundle in your code. We can go with the default, EzSystemsCookbookBundle
. Just hit Enter to accept the default.
The next question is your bundle's location. By default, the script offers to place it in the src
folder. This is perfectly acceptable unless you have a good reason to place it somewhere else. Just hit Enter to accept the default.
Next, you need to choose the generated configuration's format, out of YAML, XML, PHP or annotations. We mostly use yaml in eZ Platform, and we will use it in this cookbook. Enter 'yml', and hit Enter.
The last choice is to generate code snippets demonstrating the Symfony directory structure. If you're learning Symfony, it is a good idea to accept, as it will create a controller, yaml files, etc.
The generator will then summarize the previous choices, and ask for confirmation. Hit Enter to confirm.
The wizard will generate the bundle, check autoloading, and ask about the activation of your bundle. Hit Enter in the answer to both questions to have your bundle automatically added to your Kernel (app/AppKernel.php
) and routes from your bundle added to the existing routes (app/config/routing.yml
).
Your bundle should be generated and activated. Let's now see how you can interact with the Public API by creating a command line script, and a custom controller route and action.
Creating a command line script in your bundle
Writing a command line script with Symfony 2 is very easy. The framework and its bundles ship with a few scripts. They are all started using php app/console <command>
. You can get the complete list of existing command line scripts by executing php app/console list
from the eZ Platform root.
In this chapter, we will create a new command, identified as ezpublish:cookbook:hello
, that takes an optional name argument, and greets that name. To do so, we need one thing: a class with a name ending with "Command" that extends Symfony\Component\Console\Command\Command
. Note that in our case, we use ContainerAwareCommand
instead of Command
, since we need the dependency injection container to interact with the Public API. In your bundle's directory (src/EzSystems/CookbookBundle
), create a new directory named Command
, and in this directory, a new file named HelloCommand.php
.
Add this code to the file:
This is the skeleton for a command line script.
One class with a name ending with "Command" (HelloCommand
), extends Symfony\Bundle\FrameworkBundle\Command\Command
, and is part of our bundle's Command namespace. It has two methods: configure()
, and execute()
. We also import several classes & interfaces with the use keyword. The first two, InputInterface
and OutputInterface
are used to 'typehint' the objects that will allow us to provide input & output management in our script.
Configure
will be used to set your command's name, as well as its options and arguments. Execute
will contain the actual implementation of your command. Let's start by creating the configure()
method.
First, we use setName()
to set our command's name to "ezpublish:cookbook:hello
". We then use setDefinition()
to add an argument, named name
, to our command.
You can read more about argument definitions and further options in the Symfony 2 Console documentation. Once this is done, if you run php app/console list
, you should see ezpublish:cookbook:hello
listed in the available commands. If you run it, it will however still do nothing.
Let's just add something very simple to our execute()
method so that our command actually does something.
You can now run the command from the eZ Platform root.
Creating a custom route with a controller action
In this short chapter, we will see how to create a new route that will catch a custom URL and execute a controller action. We want to create a new route, /cookbook/test
, that displays a simple 'Hello world' message. This tutorial is a simplified version of the official one that can be found on http://symfony.com/doc/current/book/controller.html.
During our bundle's generation, we have chosen to generate the bundle with default code snippets. Fortunately, almost everything we need is part of those snippets. We just need to do some editing, in particular in two locations: src/EzSystems/Resources/CookbookBundle/config/routing.yml
and src/EzSystems/CookbookBundle/Controllers/DefaultController.php
. The first one will be used to configure our route (/cookbook/test
) as well as the controller action the route should execute, while the latter will contain the actual action's code.
routing.yml
This is the file where we define our action's URL matching. The generated file contains this YAML block:
We can safely remove this default code, and replace it with this:
We define a route that matches the URI /cookbook/* and executes the action hello
in the Default controller of our bundle. The next step is to create this method in the controller.
DefaultController.php
This controller was generated by the bundle generator. It contains one method, helloAction()
, that matched the YAML configuration we have changed in the previous part. Let's just rename the indexAction()
method so that we end up with this code.
We won't go into details about controllers in this cookbook, but let's walk through the code a bit. This method receives the parameter defined in routing.yml
. It is called "name" in the route definition, and must be called $name in the matching action. Since the action is named "hello" in routing.yml
, the expected method name is helloAction
.
Controller actions must return a Response object that will contain the response's content, the headers, and various optional properties that affect the action's behavior. In our case, we simply set the content, using setContent()
, to "Hello $name". Go to http://ezplatform/cookbook/hello/YourName, and you should get "Hello YourName".
The custom EzPublishCoreBundle Controller
For convenience, a custom controller is available at eZ\Bundle\EzPublishCoreBundle\Controller. It gives you with a few commodity methods:
getRepository()
Returns the Public API repository that gives you access to the various services throughgetContentService()
,getLocationService()
and so on;getLegacyKernel()
Returns an instance of the eZ\Publish\Core\MVC\Legacy\Kernel that you can use to interact with the Legacy eZ Platform kernelgetConfigResolver()
Returns the ConfigResolver that gives you access to configuration data.
You are encouraged to use it for your custom controllers that interact with eZ Platform.
With both command line scripts and HTTP routes, you have the basics you need to start writing Public API code.