An example of developing a blog on Zend Framework 2. Part 2. Module MyBlog
This is the second of a three part article on developing a simple application using Zend Framework 2. first part I have reviewed the structure of the ZendSkeletonApplication, and in this part I will give an example of developing a simple module. the Third part will be dedicated to working with users and Twig templating engine.
the
The first thing I want to note that installing a third-party module in Zend Framework usually consists of about four steps:
Also, I want to emphasize that for all of the modules listed below I ask the minimum necessary for their work settings, learn more about the settings and capabilities of each of the modules can be found on their documentation pages.
Let's start with the installation of simple but useful module for Zend Developer Tools.
the
Zend Developer Tools — is a convenient toolbar which is useful for developer information about the generated page: the list of queries to the database, a list of roles the current user, used by the Entity that uploaded the site configuration, etc. of Course, the toolbar can be extended with any other supporting information. You can find it here: github.com/zendframework/ZendDeveloperTools.
To install the toolbar first, add the line:
the
in the file composer.json in the project root and then run the command php composer.phar update in the root of the project.
Then, in the file config/application.config.php in the array of modules you want to add the element ZendDeveloperTools:
the
Now we have to copy the file vendor/zendframework/zend-developer-tools/config/zenddevelopertools.local.php.dist to folder config/autoload of our project and rename it, for example, in zenddevelopertools.local.php (part of the name before local.php by and large, does not matter).
All now, by default, at the bottom of all pages displaying information on took to generate the page resources, project configuration, etc.
I want to draw attention to the fact that by default the toolbar will be available to all site visitors and therefore in production environment, it should not be used.
The current version of the application is available on the Github repository of the project tagged zenddevelopertools: github.com/romka/zend-blog-example/tree/zenddevelopertools
the
For integration with Doctrine need modules, DoctrineModule and DoctrineORMModule (https://github.com/doctrine/DoctrineModule and github.com/doctrine/DoctrineORMModule).
Add to require section of composer file.json the lines:
the
and execute the console command php composer.phar update.
The module can DoctrineModule is not explicitly specified in our composer.json, since this dependency is spelled out at the level of the DoctrineORMModule module.
Now you need in the directory config/autoload place the file doctrine.local.php with parameters of access to the database that will be used Doctrine, its contents should be something like this:
the
Now if we reload the page on our website at the bottom of the page in the Zend developer the toolbar will see the new unit showing the number of requests and a list of mappings to the database. Both values are zero, since mapping we have not done and, as a consequence, queries to the database.
In this tutorial I want to develop a simple blog and now it is time to write the first lines of code of the new module.
the
In the directory modules will create the following directories and files:
the
The contents of the file Module.php should be:
the
The file is similar to what is used in the Application, we say the core of the framework where to look for the configuration file of the module and the source files.
The configuration file should return an empty array, configure a new module we will ask later.
The file src/MyBlog/Entity/BlogPost.php is the relationship (mapping) between the Doctrine and the database and it needs to talk more.
the
Each blogpost in my example will contain the following fields:
the
For simplicity, I'm not going in this tutorial to bother with the tags, comments and other typical blogging features.
This file declares the class BlogPost which contains descriptions of the fields blogpost and access methods to them. The full version of the file you can view on Github (https://github.com/romka/zend-blog-example/blob/master/module/MyBlog/src/MyBlog/Entity/BlogPost.php), here is part of it:
the
Each variable in this class will be a field in the database, the field options are set in the annotations that will be read by Doctrine (like this: php.net/manual/en/reflectionclass.getdoccomment.phpclass Doctrine\Common\Annotations\AnnotationReader method getClassAnnotations()).
Now in the config file of the module config/module.config.php you can add information about our new Entity, which will be used by the Doctrine:
the
And add the MyBlog module to the list of active modules in the application.config.php.
We have finished the configuration entity BlogPost and now we need to create the corresponding table in the database, we will use a command-line utility that comes with the Doctrine. In the project root directory run the command:
the
And the result should be a message:
the
After we were convinced that the Doctrine sees our BlogPost object then use the command:
the
The result should return an error like:
the
This is logical, as our database is still empty and now we will create the desired table with the command:
the
Results in the following output:
the
And now the command:
the
Then, if the form was validated (a validation now it will be in any case, as the validators have not yet), we create an instance of the class \MyBlog\Entity\BlogPost(), which is the relationship between our application and the database, fill the created object with data and save them in the database:
the
The current version of the template that displays the form, you can see the link github.com/romka/zend-blog-example/blob/blogpost_form_1/module/MyBlog/view/my-blog/blog/add.phtml.
If you now try to save a blank form, the Doctrine will return the error message:
the
That's right, because we have only one field marked as nullable="true" is the state field, and all the rest needs to be filled. Let's add to the form input filters and validators to intercept such errors before even attempting to save the data (in our application, not the database) that the user was able to correct the error.
the
In a previously generated file BlogPostInputFilter.php place this code (full version on Github: github.com/romka/zend-blog-example/blob/master/module/MyBlog/src/MyBlog/Form/BlogPostInputFilter.php):
the
Guess the meaning of these lines should be intuitively clear: for the fields title and text, we add input filters that remove from the text all html tags (fltr StripTags) and cut off the gaps at the edges of strings (StringTrim), and add validators that determine the minimum and maximum field length (StringLength).
Left to attach the new filter to the form by adding the form class line:
the
Now the form does not pass validation, if it is entered incorrect data.
the
After the blogpost was successfully stored (or not stored) we redirect the user to a page /blog where in the future we will have a full list of blogposts. I would just like to do a redirect, but also display a message about the successfully performed action.
To add these messages using the methods:
the
Retrieve messages added in this way, it is possible the controller or in phtml-templates, thus:
the
The problem is that inconvenient (and in Twig-templates that we will use later, not impossible) to cause the PHP code to display messages. Therefore, we will write a small View plugin that will be able one line to display all messages.
To do this, in the directory src\MyBlog module will create these directories and files:
the
The contents of the ShowMessages.php can be found here: github.com/romka/zend-blog-example/blob/master/module/MyBlog/src/MyBlog/View/Helper/ShowMessages.phpit's not very interesting, I'm just here to get a list of messages, format and return html code to display them.
Left to do are three steps:
To register the plugin add the plugin settings in seckau view_helper => invokables line:
the
In the templates add a message:
the
To display messages on the screen add to the controller the following lines:
the
Now we have the opportunity to display to the user a system message.
This version of the application you can find in the git repository with the tag blogpost_form_1: github.com/romka/zend-blog-example/tree/blogpost_form_1.
At this stage we have:
Now let's add the page to one blogpost, list of blogposts and forms edit/delete post.
the
Add to the controller BlogpostController new action view:
the
This action is available at blog/view/ID. In it we first, we check that URL specified e blogpost id if not, return error and redirected the user to a page with a list of blogposts. If the id is specified we will remove the post from the database and pass it to the template.
As the template name defaults to the controller name, so now in the module directory view/my-blog/blog you want to create the view file.phtml with something like this content:
the
the
Update the code to our indexAction like this:
the
Here we select all published blogpost (state == 1), sort them by date of publication and pass in a template index.phtml github.com/romka/zend-blog-example/blob/blogpost_form_2/module/MyBlog/view/my-blog/blog/index.phtml. The template displays the titles of blogposts and links to edit and delete.
the
Above, when creating the form I forgot to add a field userId, which is stored aydishnik author blogpost. So as of now the registration/authorization in this blog post no, the default field is filled with zero, but in the future it will be useful, so now I've added to a form hidden field userId.
In addition, I added to the form Csrf token (field security), which should protect the form from a fake. By default, this token is generated based on a user session, and salt and lives 300 seconds (Zend\Form\Element\Csrf.php), but can be (and for good should) be overridden and it should at least be added the dependence on ip of the visitor.
the
To edit a post we will use an existing form. In the controller you can create an action editAction () that will create a form, populate it with existing data and give the user. This action is a mixture of addAction(), in terms of working with the form, and the viewAction () in the data selection github.com/romka/zend-blog-example/blob/blogpost_form_2/module/MyBlog/src/MyBlog/Controller/BlogController.php#L95.
Here's the most interesting part of this controller:
the
Here we load from DB blogpost, based on the id that came in the form of the updated data:
the
and put the updated blogpost to the database:
the
the
Remove blogpost trivial, is enough to bring the user to the form with the question of the form ”do you Really want to remove the post?” and if the user clicks “Yes”, perform the corresponding action.
Code of the corresponding controller and template can be viewed at Github: github.com/romka/zend-blog-example/blob/blogpost_form_2/module/MyBlog/src/MyBlog/Controller/BlogController.php#L161.
The source code with the tag blogpost_form_2 (https://github.com/romka/zend-blog-example/tree/blogpost_form_2) contain forms for editing and deleting blogpost, a list of posts and the corresponding templates.
I would like to complete the second part of the article. the third part we'll do the work with users and attach the project the templating engine Twig.
Article based on information from habrahabr.ru
the
Installing and configuring additional modules
The first thing I want to note that installing a third-party module in Zend Framework usually consists of about four steps:
-
the
- add the appropriate line in the composer.json to inform the Composer about the new module, the
- run the command php composer.phar update that the Composer uploaded a new module and, if necessary, have paragenezisov autoload files the
- added a new module to the modules list in the file config/application.config.php, the
- if necessary, placed the configuration file of the module (typically an example of such a file is in the config folder of the module) to config/autoload and make the necessary changes.
Also, I want to emphasize that for all of the modules listed below I ask the minimum necessary for their work settings, learn more about the settings and capabilities of each of the modules can be found on their documentation pages.
Let's start with the installation of simple but useful module for Zend Developer Tools.
the
Zend Developer Tools
Zend Developer Tools — is a convenient toolbar which is useful for developer information about the generated page: the list of queries to the database, a list of roles the current user, used by the Entity that uploaded the site configuration, etc. of Course, the toolbar can be extended with any other supporting information. You can find it here: github.com/zendframework/ZendDeveloperTools.
To install the toolbar first, add the line:
the
"zendframework/zend-developer-tools": "dev-master",
in the file composer.json in the project root and then run the command php composer.phar update in the root of the project.
Then, in the file config/application.config.php in the array of modules you want to add the element ZendDeveloperTools:
the
'modules' => array(
'Application',
'ZendDeveloperTools',
),
Now we have to copy the file vendor/zendframework/zend-developer-tools/config/zenddevelopertools.local.php.dist to folder config/autoload of our project and rename it, for example, in zenddevelopertools.local.php (part of the name before local.php by and large, does not matter).
All now, by default, at the bottom of all pages displaying information on took to generate the page resources, project configuration, etc.
I want to draw attention to the fact that by default the toolbar will be available to all site visitors and therefore in production environment, it should not be used.
The current version of the application is available on the Github repository of the project tagged zenddevelopertools: github.com/romka/zend-blog-example/tree/zenddevelopertools
the
Doctrine ORM
For integration with Doctrine need modules, DoctrineModule and DoctrineORMModule (https://github.com/doctrine/DoctrineModule and github.com/doctrine/DoctrineORMModule).
Add to require section of composer file.json the lines:
the
"doctrine/common": "> =2.1",
"doctrine/doctrine-orm-module": "0.7.*"
and execute the console command php composer.phar update.
The module can DoctrineModule is not explicitly specified in our composer.json, since this dependency is spelled out at the level of the DoctrineORMModule module.
Now you need in the directory config/autoload place the file doctrine.local.php with parameters of access to the database that will be used Doctrine, its contents should be something like this:
the
<?php
return array(
'doctrine' => array(
'connection' => array(
'orm_default' => array(
'driverClass' = > 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => array(
'host' => 'localhost',
'port' = > '3306',
'user' => 'username',
'password' => 'pass',
'dbname' => 'dbname',
)
)
),
),
);
Now if we reload the page on our website at the bottom of the page in the Zend developer the toolbar will see the new unit showing the number of requests and a list of mappings to the database. Both values are zero, since mapping we have not done and, as a consequence, queries to the database.
In this tutorial I want to develop a simple blog and now it is time to write the first lines of code of the new module.
the
Module MyBlog
In the directory modules will create the following directories and files:
the
MyBlog/
config/
module.config.php
src/
MyBlog/
Entity/
BlogPost.php
Module.php
The contents of the file Module.php should be:
the
<?php
namespace MyBlog;
class Module
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ = > __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
}
The file is similar to what is used in the Application, we say the core of the framework where to look for the configuration file of the module and the source files.
The configuration file should return an empty array, configure a new module we will ask later.
The file src/MyBlog/Entity/BlogPost.php is the relationship (mapping) between the Doctrine and the database and it needs to talk more.
the
BlogPost.php
Each blogpost in my example will contain the following fields:
the
-
the
- the header the
- body blogpost, the
- author's id (0 for anonymous), the
- status (published/unpublished) the
- publication date.
For simplicity, I'm not going in this tutorial to bother with the tags, comments and other typical blogging features.
This file declares the class BlogPost which contains descriptions of the fields blogpost and access methods to them. The full version of the file you can view on Github (https://github.com/romka/zend-blog-example/blob/master/module/MyBlog/src/MyBlog/Entity/BlogPost.php), here is part of it:
the
<?php
namespace MyBlog\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
class BlogPost
{
/**
* @var int
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
* @ORM\Column(type="string", length=255, nullable=false)
*/
protected $title;
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set id.
*
* @param int $id
*
* @return void
*/
public function setId($id)
{
$this->id = (int) $id;
}
/**
* Get title.
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set title.
*
* @param string $title
*
* @return void
*/
public function setTitle($title)
{
$this->title = $title;
}
}
Each variable in this class will be a field in the database, the field options are set in the annotations that will be read by Doctrine (like this: php.net/manual/en/reflectionclass.getdoccomment.phpclass Doctrine\Common\Annotations\AnnotationReader method getClassAnnotations()).
Now in the config file of the module config/module.config.php you can add information about our new Entity, which will be used by the Doctrine:
the
return array(
'doctrine' => array(
'driver' => array(
'myblog_entity' => array(
'class' = > 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'paths' => array(__DIR__ . '/../src/MyBlog/Entity')
),
'orm_default' => array(
'drivers' => array(
'MyBlog\Entity' => 'myblog_entity',
)
)
)
),
);
And add the MyBlog module to the list of active modules in the application.config.php.
We have finished the configuration entity BlogPost and now we need to create the corresponding table in the database, we will use a command-line utility that comes with the Doctrine. In the project root directory run the command:
the
./vendor/bin/doctrine-module orm:info
And the result should be a message:
the
Found 1 mapped entities:
[OK] MyBlog\Entity\BlogPost
After we were convinced that the Doctrine sees our BlogPost object then use the command:
the
./vendor/bin/doctrine-module orm:validate-schema
The result should return an error like:
the
[Mapping] OK - The mapping files are correct.
[Database] FAIL - The database schema is not in sync with the current mapping file.
This is logical, as our database is still empty and now we will create the desired table with the command:
the
./vendor/bin/doctrine-module orm:schema-tool:update --force
Results in the following output:
the
Updating database schema...
Database schema updated successfully! "1" queries were executed
And now the command:
the
./vendor/bin/doctrine-module orm:validate-schema
returns the result:
the [Mapping] OK - The mapping files are correct.
[Database] OK - The database schema is in sync with the mapping files.
If you now refresh the page of our website, then in the toolbar at the bottom of the page we see that the Doctrine sees one mapping Myblog\Entity\BlogPost.
Source code the current version of the project can be found in the repository project on Github with the tag blogpost_entity: github.com/romka/zend-blog-example/tree/blogpost_entity.
Now that we have the substance to work with blogposts you can move on to writing my first controller that implements the form to add blogpost.
the Adding blogpost
In the src/directory MyBlog module will create two new files directory:
the Controller/
BlogController.php
Form/
BlogPostForm.php
BlogPostInputFilter.php
Later in the configuration file of the module you want to add items declaring a list of the module's controllers, routes, and path to directory with templates:
the 'controllers' => array(
'invokables' => array(
'MyBlog\Controller\BlogPost' => 'MyBlog\Controller\BlogController',
),
),
'router' => array(
'routes' => array(
'blog' => array(
'type' => 'segment',
'options' => array(
'route' = > '/blog[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'MyBlog\Controller\BlogPost',
'action' => 'index'
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
Depending on the above settings, all the pages of our blog will have URLs of the form blog/[action]/[id] (the path elements in square brackets are optional).
The file BlogPostForm.php will contain the form that will be used to add/edit blogpost, let's create this form.
the BlogPostForm.php
In the simplest case, the form code will look like this (this is not full source code form, as a whole it can be seen here: github.com/romka/zend-blog-example/blob/master/module/MyBlog/src/MyBlog/Form/BlogPostForm.php):
the class extends Form BlogPostForm
{
public function __construct($name = null)
{
parent::__construct('blogpost');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'id',
'type' => 'Hidden',
));
$this->add(array(
'name' => 'title',
'type' => 'Text',
'options' => array(
'label' => 'Title',
),
'options' => array(
'min' => 3,
'max' => 25
),
));
$this->add(array(
'name' => 'text',
'type' => 'Textarea',
'options' => array(
'label' => 'Text',
),
));
$this->add(array(
'name' = > 'state',
'type' => 'Checkbox',
));
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Save',
'id' => 'submitbutton',
),
));
}
}
Obviously, this code declares we need the form fields, but while they do not set any filters (allows you to transform incoming data), or by the validator (which will not allow to enter in the form data in the wrong format). We'll ask them later, but for now let's write the controller code which will display the form for adding blogpost and to save the entered data.
the BlogController.php
Full controller code you can see in the repository (https://github.com/romka/zend-blog-example/blob/master/module/MyBlog/src/MyBlog/Controller/BlogController.php)below him is the key part:
the class BlogController extends AbstractActionController
{
public function indexAction()
{
return new ViewModel();
}
public function addAction()
{
$form = new \MyBlog\Form\BlogPostForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$blogpost = new \MyBlog\Entity\BlogPost();
$blogpost- > exchangeArray($form->getData());
$blogpost- > setCreated(time());
$blogpost- > setUserId(0);
$objectManager- > persist($blogpost);
$objectManager- > flush();
// Redirect to list of blogposts
return $this->redirect()->toRoute('blog');
}
}
return array('form' => $form);
}
}
Important for us is the code of action addAction (names of all action games should be created on the mask nameAction()). In it, we first create a form object and replace the button text submit on it (we have one and the same form will be used to create and edit blogposts, therefore this button is convenient to have different):
$form->get('submit')->setValue('Add');
Then, if the form was validated (a validation now it will be in any case, as the validators have not yet), we create an instance of the class \MyBlog\Entity\BlogPost(), which is the relationship between our application and the database, fill the created object with data and save them in the database:
the
$blogpost- > exchangeArray($form->getData());
$blogpost- > setCreated(time());
$blogpost- > setUserId(0);
$objectManager- > persist($blogpost);
$objectManager- > flush();
The current version of the template that displays the form, you can see the link github.com/romka/zend-blog-example/blob/blogpost_form_1/module/MyBlog/view/my-blog/blog/add.phtml.
If you now try to save a blank form, the Doctrine will return the error message:
the
An exception occurred while executing 'INSERT INTO blogposts (title, text, userId, created, state) VALUES (?, ?, ?, ?, ?)' with params [null, null, 0, 1377086855, null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'title' cannot be null
That's right, because we have only one field marked as nullable="true" is the state field, and all the rest needs to be filled. Let's add to the form input filters and validators to intercept such errors before even attempting to save the data (in our application, not the database) that the user was able to correct the error.
the
form Validation
In a previously generated file BlogPostInputFilter.php place this code (full version on Github: github.com/romka/zend-blog-example/blob/master/module/MyBlog/src/MyBlog/Form/BlogPostInputFilter.php):
the
class InputFilter extends BlogPostInputFilter
{
public function __construct()
{
$this->add(array(
'name' => 'title',
'required' => true,
'validators' => array(
array(
'name' = > 'StringLength',
'options' => array(
'min' => 3,
'max' = > 100,
),
),
),
'filters' => array(
array('name' = > 'StripTags'),
array('name' = > 'StringTrim'),
),
));
$this->add(array(
'name' => 'text',
'required' => true,
'validators' => array(
array(
'name' = > 'StringLength',
'options' => array(
'min' => 50,
),
),
),
'filters' => array(
array('name' = > 'StripTags'),
array('name' = > 'StringTrim'),
),
));
$this->add(array(
'name' = > 'state',
'required' => false,
));
}
}
Guess the meaning of these lines should be intuitively clear: for the fields title and text, we add input filters that remove from the text all html tags (fltr StripTags) and cut off the gaps at the edges of strings (StringTrim), and add validators that determine the minimum and maximum field length (StringLength).
Left to attach the new filter to the form by adding the form class line:
the
$this->setInputFilter(new \MyBlog\Form\BlogPostInputFilter());
Now the form does not pass validation, if it is entered incorrect data.
the
View plugins
After the blogpost was successfully stored (or not stored) we redirect the user to a page /blog where in the future we will have a full list of blogposts. I would just like to do a redirect, but also display a message about the successfully performed action.
To add these messages using the methods:
the
$this- > flashMessenger()->addMessage($message);
$this- > flashMessenger ()- > addErrorMessage($message);
Retrieve messages added in this way, it is possible the controller or in phtml-templates, thus:
the
$this- > flashMessenger()->getMessages();
$this- > flashMessenger ()- > getErrorMessages();
The problem is that inconvenient (and in Twig-templates that we will use later, not impossible) to cause the PHP code to display messages. Therefore, we will write a small View plugin that will be able one line to display all messages.
To do this, in the directory src\MyBlog module will create these directories and files:
the
View\
Helper\
ShowMessages.php
The contents of the ShowMessages.php can be found here: github.com/romka/zend-blog-example/blob/master/module/MyBlog/src/MyBlog/View/Helper/ShowMessages.phpit's not very interesting, I'm just here to get a list of messages, format and return html code to display them.
Left to do are three steps:
-
the
- to register a View the plugin the
- to add it using the template the
- and display message on successful/failed save the form.
To register the plugin add the plugin settings in seckau view_helper => invokables line:
the
'view_helpers' => array(
'invokables' => array(
'showMessages' => 'MyBlog\View\Helper\ShowMessages',
),
),
In the templates add a message:
the
print $this- > showMessages();
To display messages on the screen add to the controller the following lines:
the
$message = 'Blogpost succesfully saved!';
$this- > flashMessenger()->addMessage($message);
Now we have the opportunity to display to the user a system message.
This version of the application you can find in the git repository with the tag blogpost_form_1: github.com/romka/zend-blog-example/tree/blogpost_form_1.
At this stage we have:
-
the
- entity to link applications and databases, created using Doctrine the
- service controller page adding blogpost, the
- form for adding blogpost with input filters and validation, the
- your custom View plugin to display messages on the screen.
Now let's add the page to one blogpost, list of blogposts and forms edit/delete post.
the
Page blogpost
Add to the controller BlogpostController new action view:
the
public function viewAction()
{
$id = (int) $this->params ()- > fromRoute('id', 0);
if (!$id) {
$this- > flashMessenger()->addErrorMessage('Blogpost id doesn\'t set');
return $this->redirect()->toRoute('blog');
}
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$post = $objectManager
->getRepository('\MyBlog\Entity\BlogPost')
->findOneBy(array('id' => $id));
if (!$post) {
$this- > flashMessenger ()- > addErrorMessage(sprintf('Blogpost with id %s doesn\'t exists', $id));
return $this->redirect()->toRoute('blog');
}
$view = new ViewModel(array(
'post' => $post->getArrayCopy(),
));
return $view;
}
This action is available at blog/view/ID. In it we first, we check that URL specified e blogpost id if not, return error and redirected the user to a page with a list of blogposts. If the id is specified we will remove the post from the database and pass it to the template.
As the template name defaults to the controller name, so now in the module directory view/my-blog/blog you want to create the view file.phtml with something like this content:
the
<?php
print $this- > showMessages();
print '<h1>' . $post['title'] . '</h1>';
print '<div>' . $post['text'] . '</div>';
the
List of blogposts
Update the code to our indexAction like this:
the
public function indexAction()
{
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$posts = $objectManager
->getRepository('\MyBlog\Entity\BlogPost')
->findBy(array('state' => 1), array('created' => 'DESC'));
$view = new ViewModel(array(
'posts' => $posts,
));
return $view;
}
Here we select all published blogpost (state == 1), sort them by date of publication and pass in a template index.phtml github.com/romka/zend-blog-example/blob/blogpost_form_2/module/MyBlog/view/my-blog/blog/index.phtml. The template displays the titles of blogposts and links to edit and delete.
the
digress
Above, when creating the form I forgot to add a field userId, which is stored aydishnik author blogpost. So as of now the registration/authorization in this blog post no, the default field is filled with zero, but in the future it will be useful, so now I've added to a form hidden field userId.
In addition, I added to the form Csrf token (field security), which should protect the form from a fake. By default, this token is generated based on a user session, and salt and lives 300 seconds (Zend\Form\Element\Csrf.php), but can be (and for good should) be overridden and it should at least be added the dependence on ip of the visitor.
the
Edit blogpost
To edit a post we will use an existing form. In the controller you can create an action editAction () that will create a form, populate it with existing data and give the user. This action is a mixture of addAction(), in terms of working with the form, and the viewAction () in the data selection github.com/romka/zend-blog-example/blob/blogpost_form_2/module/MyBlog/src/MyBlog/Controller/BlogController.php#L95.
Here's the most interesting part of this controller:
the
if ($form->isValid()) {
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$data = $form->getData();
$id = $data['id'];
try {
$blogpost = $objectManager- > find('\MyBlog\Entity\BlogPost', $id);
}
catch (\Exception $ex) {
return $this->redirect()->toRoute('blog', array(
'action' => 'index'
));
}
$blogpost- > exchangeArray($form->getData());
$objectManager- > persist($blogpost);
$objectManager- > flush();
$message = 'Blogpost succesfully saved!';
$this- > flashMessenger()->addMessage($message);
// Redirect to list of blogposts
return $this->redirect()->toRoute('blog');
}
Here we load from DB blogpost, based on the id that came in the form of the updated data:
the
$blogpost- > exchangeArray($form->getData());
and put the updated blogpost to the database:
the
$objectManager- > persist($blogpost);
$objectManager- > flush();
the
Remove blogposts
Remove blogpost trivial, is enough to bring the user to the form with the question of the form ”do you Really want to remove the post?” and if the user clicks “Yes”, perform the corresponding action.
Code of the corresponding controller and template can be viewed at Github: github.com/romka/zend-blog-example/blob/blogpost_form_2/module/MyBlog/src/MyBlog/Controller/BlogController.php#L161.
The source code with the tag blogpost_form_2 (https://github.com/romka/zend-blog-example/tree/blogpost_form_2) contain forms for editing and deleting blogpost, a list of posts and the corresponding templates.
I would like to complete the second part of the article. the third part we'll do the work with users and attach the project the templating engine Twig.
Comments
Post a Comment