Message-ID: <529099335.3084.1485851948020.JavaMail.confluence@ip-10-127-227-164> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_3083_1251912984.1485851948020" ------=_Part_3083_1251912984.1485851948020 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html
With the introduction of Symfony 2 as the framework powering eZ = Publish 5, the whole eZ Publish 4.x extensions system is changing. Pretty m= uch everything needs to be done with entirely new concepts. In this chapter= , we will see two ways of customizing eZ Publish 5: command line scripts (f= or import scripts, for instance), and custom controllers, the eZ Publish 5 = equivalent of eZ Publish 4.x custom modules.
In order to test and use Public API code, you will need to build a custo= m bundle. Bundles are Symfony's extensions, and are therefore also used to = extend eZ Publish. Symfony 2 provides code generation tools that will let y= ou create your own bundle and get started in a few minutes.
In this chapter, we will show how to create a custom bundle, and impleme= nt both: a command line script and a custom route with its own controller a= ction and view. All shell commands assume that you use some Linux shell, bu= t those commands would of course also work on Windows systems.
First, change the directory to your eZ Publish root.
$ cd /path/to/ezpublish5=20
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 t=
o create a bundle named EzSystems/Bundles/CookBookBundle
, l=
ocated in the src
directory.
$ php ezpublish/console generate:bundle=20
The wizard will first ask about our bundle's namespace. Each bundle's na=
mespace should feature a vendor name (in our own case: EzSystems=
), optionally followed by a sub-namespace (we could have chosen to u=
se Bundle
), and end with the actual bundle's name, suffix=
ed with Bundle: CookbookBundle
.
Your application code must be written in bundles. This command hel= ps 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, you= r project name, or your client name, followed by one or more optional categ= ory sub-namespaces, and it should end with the bundle name itself (which mu= st have Bundle as a suffix). See http://symfony.com/doc/current/cookbook/bundles/best_practices.html#ind= ex-1 for more details on bundle naming conventions.=20 Use / instead of \ for the namespace delimiter to avoid any problem. Bundle namespace: EzSystems/CookbookBundle=20
You will then be asked about the Bund=
le's name, used to reference your bundle in your code. We can go with the d=
efault, EzSystemsCookbookBundle
. Just hit enter to accept=
the default.
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 EzSystemsCookbookBundle. Bundle name [EzSystemsCookbookBundle]:=20
The next question is your bundle's lo=
cation. 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.
=
p>
The bundle can be generated anywhere. The suggested default direc= tory uses the standard conventions. Target directory [/path/to/ezpublish5/src]:=20
Next, you need to choose the generate= d configuration's format, out of YAML, XML, PHP or annotations. We mostly u= se yaml in eZ Publish 5, and we will use it in this cookbook. Enter 'yml', = and hit enter.
Determine the format to use for the generated configuration. = = =20 Configuration format (yml, xml, php, or annotation) [annotation]: yml= =20
The last choice is to generate code s=
nippets demonstrating the Symfony directory structure. If you're learning S=
ymfony, it is a good idea to accept, as it will pre-create a controller, ya=
ml files, etc.
To help you get started faster, the command can generate some cod= e snippets for you. Do you want to generate the whole directory structure [no]? yes=20
The generator will then summarize the= previous choices, and ask for confirmation. Hit enter to confirm.= p>
You are going to generate a "EzSystems\Bundle\CookbookBundle\EzSy= stemsCookbookBundle" bundle in "/path/to/ezpublish5/src/" using the "yml" f= ormat. Do you confirm generation [yes]? yes=20
The wizard will generate the bundle, check autoloading, and ask about th=
e activation of your bundle. Hit enter to both questions to have your bundl=
e automatically added to your Kernel (ezpublish/EzPublishKernel.php=
code>) and routes from your bundle added to the existing routes (
ezpu=
blish/config/routing.yml
).
Bundle generation Generating the bundle code: OK Checking that the bundle is autoloaded: OK Confirm automatic update of your Kernel [yes]? Enabling the bundle inside the Kernel: OK Confirm automatic update of the Routing [yes]? Importing the bundle routing resource: OK You can now start using the generated code!=20
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 cust= om controller route and action.
Writing a command line script with Symfony 2 is very =
easy. The framework and its bundles ship with a few scripts. They are all s=
tarted using php ezpublish/console <command>
(=
app/console
in a default symfony 2 application). You can =
get the complete list of existing command line scripts by executing
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 w=
ith "Command" that extends Symfony\Component\Console\Command\Com=
mand
. Note that in our case, we use ContainerAwareCommand=
instead of Command
, since we need the depend=
ency injection container to interact with the Public API). In your bun=
dle's directory (src/EzSystems/CookbookBundle
), create a new d=
irectory named Command
, and in this directory, a new file=
named HelloCommand.php
.
Add this code to the file:
<?php namespace EzSystems\CookBookBundle\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; class HelloCommand extends \Symfony\Bundle\FrameworkBundle\Command\Containe= rAwareCommand { /** * Configures the command */ protected function configure() { } /** * Executes the command * @param InputInterface $input * @param OutputInterface $output */ protected function execute( InputInterface $input, OutputInterface $out= put ) { } }=20
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: execute()
. We also import seve=
ral classes & interfaces with the use keyword. The first two, OutputInterface
are=
used to 'typehint' the objects that will allow us to provide input & o=
utput management in our script.
Configure will be used to set your command's name, as well as its option=
s and arguments. Execute will contain the actual implementation of your com=
mand. Let's start by creating the configure()
method=
.
protected function configure() { $this->setName( 'ezpublish:cookbook:hello' ); $this->setDefinition( array( new InputArgument( 'name', InputArgument::OPTIONAL, 'An argumen= t' ) ) ); }=20
First, we use setName() to set our command's name to "ezpublish:co=
okbook:hello
". We then use setDefinition()
&n=
bsp;to add an argument, named name
, to our command.
You can read more about arguments definitions and further options in the=
Symfony 2 Console documenta=
tion. Once this is done, if you run php ezpublish/conso=
le list
, you should see ezpublish:cookbook:hello
&n=
bsp;listed in the available commands. If you run it, it should just do noth=
ing.
Let's just add something very simple to our execute() method so that our= command actually does something.
protected function execute( InputInterface $input, OutputInterface = $output ) { // fetch the input argument if ( !$name =3D $input->getArgument( 'name' ) ) { $name =3D "World"; } $output->writeln( "Hello $name" ); }=20
You can now run the command from the eZ Publish 5 root.
$ php ezpublish/console ezpublish:cookbook:hello world Hello world=20
In this short chapter, we will see how to create a new route that will c=
atch a custom URL and execute a controller action. We want to create a new =
route, /cookbook/test
, that displays a simple 'Hello world' me=
ssage. This tutorial is a simplified version of the official one that can b=
e found on http://symfony.com/doc/curren=
t/book/controller.html.
eZ Publish 4 equivalent
This eZ Publish 5 extension would have been a custom module, with its ow=
n module.php
file, in eZ Publish 4.
During our bundle's generation, we have chosen to generate the bundle wi=
th default code snippets. Fortunately, almost everything we need is part of=
those default snippets. We just need to do some editing, in particular in =
two locations: src/EzSystems/CookbookBundle/Resources/config/rou=
ting.yml
and src/EzSystems/CookbookBundle/Controller=
s/DefaultController.php
. The first one will be used to configure our=
route (/cookbook/test
) as well as the controller action the r=
oute should execute, while the latter will contain the actual action's code=
.
This is the file where we define our action's URL matching. The generate= d file contains this YAML block
ez_systems_cookbook_homepage: pattern: /hello/{name} defaults: { _controller: EzSystemsCookbookBundle:Default:index }= =20
We can safely remove this default code, and replace it with this
ezsystems_cookbook_hello: pattern: /cookbook/hello/{name} defaults: { _controller: EzSystemsCookbookBundle:Default:hello }= =20
We define a route that matches the URI /cookbook/* and executes the acti= on hello in the Default controller of our bundle. The next step is to creat= e this method in the controller.
This controller was generated by the bundle generator. It contains one m=
ethod, helloAction()
, that matched the YAML configuration=
we have changed in the previous part. Let's just rename the ind=
exAction()
method so that we end up with this code.
public function helloAction( $name ) { $response =3D new \Symfony\Component\HttpFoundation\Response; $response->setContent( "Hello $name" ); return $response; }=20
We won't go into details about controllers in this cookbook, but let's w=
alk through the code a bit. This method receives the parameter defined=
in routing.yml
. It is named "name" in the route definiti=
on, and must be named $name in the matching action. Since the action is nam=
ed "hello" in routing.yml
, the expected method name is&nb=
sp;helloAction
.
Controller actions must return a Response obj=
ect that will contain the response's content, the headers, and various opti=
onal properties that affect the action's behavior. In our case, we simply s=
et the content, using setContent()
, to "Hello $name". Sim=
ple. Go to http://ezpublish5/co=
okbook/hello/YourName, and you should get "Hello YourName".
The custom EzPublishCoreBundle Controller
For convenience, a custom controller is available at eZ\Bundle\EzPublishCoreBundle\C= ontroller. It gives you with a few commodity methods:
You are encouraged to use it for your custom controllers that interact w= ith eZ Publish.
With both command line scripts and HTTP routes, you have the basics you = need to start writing Public API code.