Share
Embed
Transcript
59 slides
-
Disclaimer THE SOFTWARE SLIDES IS PROVIDED "AS IS" WITHOUT WARRANTY
OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
Create only one bundle called AppBundle uberCMS/ ├─ app/ │
├─ console │ ├─ cache/ │ ├─ config/ │ └─ logs/ │ └─ Resources/ ├─ src/ │ └─ AppBundle/ ├─ vendor/ └─ web/ ├─ app.php └─ app_dev.php -
Create only one bundle called AppBundle What about API Bundle?
What about Core Bundle? What about DDD? Do not use Sf3 dir structure... yet Imagine several kernels -
Infrastructure/App Related Configuration # app/config/config.yml imports: - resource: parameters.yml -
resource: framework.yml - resource: doctrine.yml - resource: doctrine_extension.yml - resource: html_purifier.yml - resource: facebook.yml - resource: mailer.yml - resource: monolog.yml - resource: twig.yml - resource: imagine.yml -
Use constants to define configuration options that rarely change Different
environments Different clients -
Semantic Configuration: Don't Do It services.xml/yml + *Extension.php + Configuration.php
http://symfony2-document.readthedocs.org/en/latest/cookbook/bundles/extension.html -
Config Formats Routing DBmapping Services Validation Serializer map Translations Yaml
Annotation XML Annotation, XML Yaml Yaml -
Service: No Class Parameter # app/config/services.yml parameters: slugger.class: AppBundle\Slugger services:
slugger: class: "%slugger.class%" -
Annotations for Doctrine mappings /** @MongoDB\Document */ class Topic {
/** @MongoDB\Id */ protected $id; /** @MongoDB\String */ protected $name; /** @MongoDB\Int */ protected $code; // .... } -
Data Fixtures One fixture file per entity OrderedFixtureInterface DoctrineFixturesBundle +
Alice & bundle + Faker https://github.com/doctrine/DoctrineFixturesBundle https://github.com/hautelook/AliceBundle https://github.com/fzaninotto/Faker -
Make your controller extend the FrameworkBundle Get Request Submit form
if any Call one Service method Return Response Rendering HTML far away -
Routing Configuration Annotations External format (YAML, XML) /** @Route("/") */
public function indexAction() { } _index: pattern: / defaults: { _controller: AcmeBundle:Frontend:index } -
Use ParamConverter /** @ParamConverter("post", class="BlogBundle:Post") */ public function showAction(Post $post)
{ return $this->render('show.html.twig', array( 'post' => $post, )); } -
Store all your templates in app/Resources/views/ Inconsistently with Bundle coupling
Hard to maintain Probably easier write template path Inside bundles In app/ DemoBunde:Default:index.html.twig default/index.html.twig ::layout.html.twig layout.html.twig AcmeDemoBundle::index.html.twig index.html.twig -
Use Form Types Define your forms as PHP classes class
PostType extends AbstractType { public function buildForm( FormBuilderInterface $builder, array $options ) { $builder ->add('title') ->add('summary', 'textarea') ->add('content', 'textarea') ; } -
public function setDefaultOptions( OptionsResolverInterface $resolver ) { $resolver->setDefaults(array( 'data_class' =>
'AppBundle\Entity\Post' )); } Use Form Types Always add “form model” -
class PostType extends AbstractType { public function buildForm(// ...) {
$builder // ... ->add('save', 'submit', array('label' => 'Create Post')) ; } Wrong code example “Add buttons in the templates, not in the form classes or the controllers” Form Templates -
Form Templates <form method="POST" {{ form_enctype(form) }}> {{ form_widget(form) }}
</form> “Don't use the form() or form_start()” -
Handling Forms $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em =
$this->getDoctrine()->getManager(); $em->persist($post); $em->flush(); } return $this->redirect(...); -
Handling Forms $form->handleRequest($request); if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($post);
$em->flush(); } return $this->redirect(...); -
Use the XLIFF for your translation files Too Verbose Extra
complexity Accidental complexity Inconsistently with service configs -
Translation files location “Store the translation files in the app/Resources/translations
directory” Same issues as for templates Inconsistently with Bundle coupling -
Translation Keys “Always use keys for translations instead of content
strings” At form types At templates At validation messages -
Firewalls “Be simple: use only one firewall entry with the
anonymous key enabled” Remember about API auth -
Password hashing “Use the bcrypt encoder for encoding your users
passwords” security: encoders: AppBundle\Entity\User: bcrypt For old Sf systems <2.3 https://github.com/elnur/ElnurBlowfishPasswordEncoderBundle -
Authorization Protecting broad URL patterns, use access_control access_control: - {
path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/, roles: ROLE_ADMIN } -
Authorization Whenever possible, use the @Security annotation /** * @Security("has_role('ROLE_ADMIN')")
*/ public function indexAction() { // ... } -
Custom Voter class PostVoter extends AbstractVoter { const CREATE =
'create'; const EDIT = 'edit'; protected function getSupportedAttributes() { return array(self::CREATE, self::EDIT); } protected function getSupportedClasses() { return array('AppBundle\Entity\Post'); } } For fine-grained restrictions, define a custom security voter -
For fine-grained restrictions, define a custom security voter protected function
isGranted($attribute, $post, $user = null) { if (!$user instanceof UserInterface) return false; if ($attribute == self::CREATE && in_array(ROLE_ADMIN, $user->getRoles()) ) return true; if ($attribute == self::EDIT && $user->getEmail() === $post->getAuthorEmail() ) return true; return false; } Custom Voter -
Applying voter Custom Voter # app/config/services.yml services: post_voter: class: AppBundle\Security\PostVoter
public: false tags: - { name: security.voter } /** * @Security("is_granted('edit', post)") */ public function editAction(Post $post) -
Authorization ACL For restricting access to any object by any
user via an admin interface, use the Symfony ACL