You can find out how to install the part of the manual you need in the description of the repository by the link . (For example, if you want to start with this lesson without going through the previous one)
src/Blogger/BlogBundle/Resources/config/routing.yml
# src/Blogger/BlogBundle/Resources/config/routing.yml BloggerBlogBundle_contact: path: /contact defaults: { _controller: "BloggerBlogBundle:Page:contact" } requirements: methods: GET
src/Blogger/BlogBundle/Controller/PageController.php
src/Blogger/BlogBundle/Controller/PageController.php
class PageController extends Controller { //.. public function contactAction() { return $this->render('BloggerBlogBundle:Page:contact.html.twig'); } }
src/Blogger/BlogBundle/Resources/views/Page/contact.html.twig
{# src/Blogger/BlogBundle/Resources/views/Page/contact.html.twig #} {% extends 'BloggerBlogBundle::layout.html.twig' %} {% block title %}Contact{% endblock%} {% block body %} <header> <h1>Contact symblog</h1> </header> <p>Want to contact symblog?</p> {% endblock %}
app/Resources/views/base.html.twig
#app/Resources/views/base.html.twig {% block navigation %} <nav> <ul class="navigation"> <li><a href="{{ path('BloggerBlogBundle_homepage') }}">Home</a></li> <li><a href="{{ path('BloggerBlogBundle_about') }}">About</a></li> <li><a href="{{ path('BloggerBlogBundle_contact') }}">Contact</a></li> </ul> </nav> {% endblock %}
src/Blogger/BlogBundle/Entity/Enquiry.php
and paste in the following content: <?php // src/Blogger/BlogBundle/Entity/Enquiry.php namespace Blogger\BlogBundle\Entity; class Enquiry { protected $name; protected $email; protected $subject; protected $body; /** * @return mixed */ public function getName() { return $this->name; } /** * @param mixed $name */ public function setName($name) { $this->name = $name; } /** * @return mixed */ public function getEmail() { return $this->email; } /** * @param mixed $email */ public function setEmail($email) { $this->email = $email; } /** * @return mixed */ public function getSubject() { return $this->subject; } /** * @param mixed $subject */ public function setSubject($subject) { $this->subject = $subject; } /** * @return mixed */ public function getBody() { return $this->body; } /** * @param mixed $body */ public function setBody($body) { $this->body = $body; } }
The note
Let's talk about how namespaces are used in symfony2. The entity class we created sets theBlogger\BlogBundle\Entity
namespace. Since Symfony2 supports the PSR-0 autoload standard, the namespace points directly to the bundle file structure. The Inquiry entity class is located insrc/Blogger/BlogBundle/Entity/Enquiry.php
, which ensures Symfony2 has the correct class autoload.
How does the symfony2 autoloader understand that the blogger namespace is in the src directory? This is achieved through the autoloader configurationapp/autoload.php
/** * @var ClassLoader $loader */ $loader = require __DIR__.'/../vendor/autoload.php'; AnnotationRegistry::registerLoader(array($loader, 'loadClass')); return $loader;
It registers all namespaces that have not been registered. Since the Blogger namespace is not registered, the Symfony2 autoloader will look for the necessary files in the src directory.
Autoloader and namespace is a very powerful concept in symfony2. If you get errors where PHP cannot find classes, you probably have an error in your namespace or folder structure. You should not be tempted to fix this with PHP's require or include inclusion.
src/Blogger/BlogBundle/Form/EnquiryType.php
and add the following content: <?php namespace Blogger\BlogBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class EnquiryType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('name', TextType::class); $builder->add('email', EmailType::class); $builder->add('subject', TextType::class); $builder->add('body', TextareaType::class); } public function configureOptions(OptionsResolver $resolver) { } public function getBlockPrefix() { return 'contact'; } }
The note
Here it is necessary to mention that the getBlockPrefix method should return a unique identifier.
src/Blogger/BlogBundle/Controller/PageController.php
following: // src/Blogger/BlogBundle/Controller/PageController.php public function contactAction(Request $request) { $enquiry = new Enquiry(); $form = $this->createForm(EnquiryType::class, $enquiry); if ($request->isMethod($request::METHOD_POST)) { $form->handleRequest($request); if ($form->isValid()) { // Perform some action, such as sending an email // Redirect - This is important to prevent users re-posting // the form if they refresh the page return $this->redirect($this->generateUrl('BloggerBlogBundle_contact')); } } return $this->render('BloggerBlogBundle:Page:contact.html.twig', array( 'form' => $form->createView() )); }
submit($request)
will turn the submitted data back into the elements of our $ inquiry object. At the moment, the object $ $ inquiry contains an idea of ​​what the user sent. Next we will make a check to make sure the form is filled out correctly. Since we have not specified a single validator for this moment, the form will always be valid. Finally, we will specify the template to render.src/Blogger/BlogBundle/Controller/PageController.php
<?php // src/Blogger/BlogBundle/Controller/PageController.php namespace Blogger\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; // Import new namespaces use Symfony\Component\HttpFoundation\Request; use Blogger\BlogBundle\Entity\Enquiry; use Blogger\BlogBundle\Form\EnquiryType; class PageController extends Controller { //..
<form action="{{ path('BloggerBlogBundle_contact') }}" method="post" > {{ form_start(form) }} {{ form_widget(form) }} {{ form_end(form) }} <input type="submit" /> </form>
src/Blogger/BlogBundle/Resources/views/Page/contact.html.twig
{# src/Blogger/BlogBundle/Resources/views/Page/contact.html.twig #} {% extends 'BloggerBlogBundle::layout.html.twig' %} {% block title %}Contact{% endblock%} {% block body %} <header> <h1>Contact symblog</h1> </header> <p>Want to contact symblog?</p> {{ form_start(form, { 'action': path('BloggerBlogBundle_contact'), 'method': 'POST', 'attr': {'class': 'blogger'} }) }} {{ form_errors(form) }} {{ form_row(form.name) }} {{ form_row(form.email) }} {{ form_row(form.subject) }} {{ form_row(form.body) }} {{ form_rest(form) }} <input type="submit" value="Submit" /> {% endblock %}
The note
Cross-site request forgery (CSRF) is explained in detail in the Shapes chapter of the Symfony2 book .
src/Blogger/BlogBundle/Resources/public/css/blog.css
and insert styles. .blogger-notice { text-align: center; padding: 10px; background: #DFF2BF; border: 1px solid; color: #4F8A10; margin-bottom: 10px; } form.blogger { font-size: 16px; } form.blogger div { clear: left; margin-bottom: 10px; } form.blogger label { float: left; margin-right: 10px; text-align: right; width: 100px; font-weight: bold; vertical-align: top; padding-top: 10px; } form.blogger input[type="text"], form.blogger input[type="email"] { width: 500px; line-height: 26px; font-size: 20px; min-height: 26px; } form.blogger textarea { width: 500px; height: 150px; line-height: 26px; font-size: 20px; } form.blogger input[type="submit"] { margin-left: 110px; width: 508px; line-height: 26px; font-size: 20px; min-height: 26px; } form.blogger ul li { color: #ff0000; margin-bottom: 5px; }
src/Blogger/BlogBundle/Resources/views/layout.html.twig
and replace the content with the following: {# src/Blogger/BlogBundle/Resources/views/layout.html.twig #} {% extends '::base.html.twig' %} {% block stylesheets %} {{ parent() }} <link href="{{ asset('bundles/bloggerblog/css/blog.css') }}" type="text/css" rel="stylesheet" /> {% endblock %} {% block sidebar %} Sidebar content {% endblock %}
app/Resources/base.html.twig
, and allow you to add our new style file. We do not want to override already existing style sheets.php app/console assets:install web --symlink
src/Blogger/BlogBundle/Resources/config/routing.yml
to handle POST requests. # src/Blogger/BlogBundle/Resources/config/routing.yml BloggerBlogBundle_contact: path: /contact defaults: { _controller: "BloggerBlogBundle:Page:contact" } requirements: methods: GET|POST
The note
Now that you submit the form, it should function as expected, however the page will simply redirect you back to the contact form.
src/Blogger/BlogBundle/Entity/Enquiry.php
we src/Blogger/BlogBundle/Entity/Enquiry.php
point out a few validators. Make sure you add 4 new applications at the top of the file. <?php // src/Blogger/BlogBundle/Entity/Enquiry.php namespace Blogger\BlogBundle\Entity; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Constraints\Length; class Enquiry { public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('name', new NotBlank()); $metadata->addPropertyConstraint('email', new Email()); $metadata->addPropertyConstraint('subject', new Length(array( 'max' => 50 ))); $metadata->addPropertyConstraint('body', new Length(array( 'min' => 50 ))); } //..
$metadata->addPropertyConstraint('email', new Email(array( 'message' => 'symblog does not like invalid emails. Give me a real one!' )));
The note
If you use a browser that supports HTML5, you will see HTML5 messages of certain restrictions. This is a client-side check and Symfony2 will set suitable HTML5 restrictions based on Entity metadata. You can see this on the email element. HTML display
<input type="email" id="contact_email" name="contact[email]" required="required">
He used one of the new types of HTML5 fields, email and set the required attribute. Verification on the client side is a big plus because it does not require requests to the server to verify the form. However, client side validation should not be used alone. You should always check the data presented on the server side, since it is quite easy to bypass the client side check.
app/config/parameters.yml
and find the settings with the mailer_ prefix.mailer_transport: smtp
mailer_host: 127.0.0.1
mailer_user: null
mailer_password: null
mailer_transport: gmail
mailer_encryption: ssl
mailer_auth_mode: login
mailer_host: smtp.gmail.com
mailer_user: _
mailer_password: _
Important !
Be careful if you use a version control system (VCS) as Git for your project, especially if your repository is publicly available. You need to make sure that the application fileapp/config/parameters.yml
added to ignore your vcs.
src/Blogger/BlogBundle/Controller/PageController.php
copying the following code into it: if ($form->isValid()) { $message = \Swift_Message::newInstance() ->setSubject('Contact enquiry from symblog') ->setFrom('enquiries@symblog.co.uk') ->setTo('email@email.com') ->setBody($this->renderView('BloggerBlogBundle:Page:contactEmail.txt.twig', array('enquiry' => $enquiry))); $this->get('mailer')->send($message); $this->get('session')->getFlashBag()->add('blogger-notice', 'Your contact enquiry was successfully sent. Thank you!'); // Redirect - This is important to prevent users re-posting // the form if they refresh the page return $this->redirect($this->generateUrl('BloggerBlogBundle_contact')); }
The note
Since the Swift Mailer library does not use namespaces, we must prefix the Swift Mailer \ class. This tells PHP to go back to the global space. You will need to add the prefix to all classes and functions that do not have a namespace with \. If you do not place this prefix before the Swift_Message class, PHP will be visible to the class in the current namespace, which in this example is Blogger \ BlogBundle \ Controller, which will result in an error.
src/Blogger/BlogBundle/Resources/views/Page/contact.html.twig
: //.. <header> <h1>Contact symblog</h1> </header> {% for flashMessage in app.session.flashbag.get('blogger-notice') %} <div class="blogger-notice"> {{ flashMessage }} </div> {% endfor %} <p>Want to contact symblog?</p> //..
src/Blogger/BlogBundle/Resources/config/config.yml
: parameters: # Blogger contact email address blogger_blog.emails.contact_email: contact@email.com
app/config/config.yml
, : # app/config/config.yml imports: # .. existing import here - { resource: "@BloggerBlogBundle/Resources/config/config.yml"}
// src/Blogger/BlogBundle/Controller/PageController.php public function contactAction(Request $request) { $enquiry = new Enquiry(); $form = $this->createForm(EnquiryType::class, $enquiry); if ($request->isMethod($request::METHOD_POST)) { $form->handleRequest($request); if ($form->isValid()) { $message = \Swift_Message::newInstance() ->setSubject('Contact enquiry from symblog') ->setFrom('enquiries@symblog.co.uk') ->setTo($this->container->getParameter('blogger_blog.emails.contact_email')) ->setBody($this->renderView('BloggerBlogBundle:Page:contactEmail.txt.twig', array('enquiry' => $enquiry))); $this->get('mailer')->send($message); $this->get('session')->getFlashBag()->add('blogger-notice', 'Your contact enquiry was successfully sent. Thank you!'); // Redirect - This is important to prevent users re-posting // the form if they refresh the page return $this->redirect($this->generateUrl('BloggerBlogBundle_contact')); } } return $this->render('BloggerBlogBundle:Page:contact.html.twig', array( 'form' => $form->createView() )); }
The board
. ,app/config/config.yml
.
# app/config/config.yml parameters: # Blogger contact email address blogger_blog.emails.contact_email: assistant@email.com
src/Blogger/BlogBundle/Resources/views/Page/contactEmail.txt.twig
{# src/Blogger/BlogBundle/Resources/views/Page/contactEmail.txt.twig #} A contact enquiry was made by {{ enquiry.name }} at {{ "now" | date("Ymd H:i") }}. Reply-To: {{ enquiry.email }} Subject: {{ enquiry.subject }} Body: {{ enquiry.body }}
The board
Symfony2 SwiftMailer Symfony2. . , Symfony 2 SwiftMailer , .app/config/config_test.yml
swiftmailer: disable_delivery: true
, Dev . , , . , Dev ,app/config/config_dev.yml
app/config/config_dev.yml
true , .app/config/config_dev.yml
swiftmailer: delivery_address: development@symblog.dev
, , , .
Part 1 - Configuring Symfony2 and Templates
Part 3 - Doctrine 2 and Data Fixtures
Part 4 - Comment Model, Repository and Migrations of Doctrine 2
Part 5 - Twig Extensions, Sidebar (sidebar) and Assetic
Part 6 - Modular and Functional Testing
Source: https://habr.com/ru/post/302032/
All Articles