Working With The Symfony Admin Generator

John Cleveley
John CleveleyWeb Applications Developer
Working with the admin
      generator
My background
John Cleveley
Trained as a Systems Engineer with BAE Systems
Started my own business in 2006
Created symfony apps for NHS, V&A Museum and
Hornby.
Currently work at the BBC using their Forge
platform (ZF)
Working With The Symfony Admin Generator
Objectives

Provide information beyond the docs
Update on what’s new
Suggest a few best practices
Real world examples of customising
How to get the best from the form framework
Utilise the various ways of extending
It’s super awesome.
Saves huge amount of development time and costs
Provides most common admin requirements out of
the box
Can be extended to provide bespoke needs
Fully tested and documented
It’s free!
What’s new since 1.0?
Completely re-written for the form framework
Relationships including m2m work without
configuration
Generator.yml is validated
Batch actions (delete)
Less reliance on generator.yml (DRY)
More templates and actions to override
Different configuration for the edit and new form
Adds a REST route for your module
New PHP configuration file
Configure generator via PHP to be more dynamic:
lib/newsGeneratorConfiguration.class.php

The generated class in the cache lists functions
cache/backend/dev/modules/autoNews/lib/BaseNe
wsGeneratorConfiguration.class.php

You can also mix configuration between the two
New helper file
      Provides html snippets for action links
      lib/[module]GeneratorHelper.class.php
getUrlForAction ()
linkToDelete ()
linkToEdit ()
linkToList ()
linkToNew ()
linkToSave ()
linkToSaveAndAdd ()



    Create custom links with extra javascript etc
Your thoughts?




PHP!               YAML!
Is it the right tool?



               …maybe.
Think requirements!




Don’t jump to use the admin generator
Analyse what’s needed first
A bespoke solution may be more appropriate
Misusing the admin generator could cause big
problems in the future
How do we decide?
Admin                           Bespoke
  Normal CRUD operations          Public interface to data
  Non – technical users           Sophisticated sorting
  need to add data                and searching of data
  Trusted site administrators
  Ownership of all records


        The admin site can take you a long way….
        …. But be careful it doesn’t become a mess.
admin
The 10 Commandments
10 Commandments (1-5)
1. Understand the client’s workflow and customise
   admin to suit
2. Think about security from the start
3. Look through and understand the cached php
   files
4. Change table_method to reduce db calls
5. Use bespoke Form class for admin if different
10 Commandments (6-10)
6. Keep all form form configuration in the Form Class
7. If you need to make changes to multiple admin
   modules – create a theme.
8. Think about small screens and target browser
9. Create functional tests – guard against regression
10. Maintain good MVC and decoupling practices
What’s the object-oriented way
    to become wealthy?
           Inheritance!
John’s Top tips!
1. The URL
  Clients don’t like using:
application.com/admin.php

         Option 1:
  application.com/admin

        Option 2:
  admin.application.com
1. The URL: /admin
Modify web/.htaccess
 RewriteCond %{REQUEST_URI} ^/admin/?
 RewriteRule ^(.*)$ admin.php [QSA,L]

 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteRule ^(.*)$ index.php [QSA,L]

Change all your standard routes – routing.yml
  homepage:
      url:   /admin
      param: { module: default, action: index }
  test:
      url: /admin/test
      ...
1. The URL: /admin
Change your route collections – routing.yml

  prefix_path:   /admin/module_name



Remove script name in urls – settings.yml

  prod:
     .settings:
        no_script_name:   true
1. The URL: admin.app
Create a new virtual host in httpd.conf
   <VirtualHost *:80>
     ServerName admin.application.com
     DirectoryIndex admin.php
     DocumentRoot "/path/to/web/folder"
     <Directory "/path/to/web/folder">
       AllowOverride All
       Allow from All
     </Directory>
   </VirtualHost>

Tell symfony not to output admin.php in urls
   Prod
     .settings:
        no_script_name:   true
2. Dynamic MaxPerPage
    Add a select box within the _list_header.php
                                            js onchange
                                            submits to action


    Add an action to set a user attribute
public function executeChangeMaxPage(sfWebRequest $request){

    $this->getUser()->setAttribute('maxPage',
       $request->getParameter('maxPage'));

    $this->redirect($request->getReferer());
}
2. Dynamic MaxPerPage

    Override getPagerMaxPerPage()

class employeeGeneratorConfiguration extends BaseEmployee
{
  public function getPagerMaxPerPage()
  {
    $maxPage = sfContext::getInstance()->getUser()
            ->getAttribute('maxPage', 10);
    return $maxPage;
  }
}
3. Adding relations
Fewest clicks for common tasks
Relevant data placed together
Currently unsupported by the generator
Symfony provides functions to help
  sfForm : : mergeForm()
  sfForm : : embedForm()
  sfFormDoctrine : : embedRelation()
Employee has many phones
Employee:                    Phone:
  columns:                     columns:
    id:                          id:
      type: integer(4)              type: integer(4)
      primary: true                 primary: true
      autoincrement: true           autoincrement: true
    name:                        number:
      type: string(255)             type: string(255)
      notnull: true                 notnull: true
  relations:                     employee_id:
    Phones:                         type: integer(4)
      type: many                    notnull: true
      class: Phone               type:
      local: id                     type: enum
      foreign: employee_id          values: [mobile, home, work]
      onDelete: CASCADE
3. Adding relations
Add ability to edit existing phone numbers from
within employee form

Embed the ‘Phones’ relation in EmployeeForm::configure

   class EmployeeForm extends BaseEmployeeForm
   {
     public function configure()
     {
       $this->embedRelation('Phones');
     }
   }
Hide employee_id in PhoneForm::configure()
class PhoneForm extends BasePhoneForm
{
  public function configure()
  {
    $this->widgetSchema['employee_id'] =
      new sfWidgetFormInputHidden();
  ...




                                      No Delete?
                                      No Add?
There’s a symfony plugin for that!
 Thanks to ahDoctrineEasyEmbeddedRelationsPlugin by
 Daniel Lohse
4. Translate admin interface
  Add chosen culture to settings.yml
.all:
  .settings:
    i18n: on
    default_culture: fr




  ./symfony cc and delete browser cookies
4. Translate admin interface
Create a new startrek catalogue

Add vulcan XLIFF files to:
   apps/admin/il8n/
    • startrek.vu.xml
    • startrek_forms.vu.xml
4. Translate admin interface
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN"
"http://www.oasis-
open.org/committees/xliff/documents/xliff.dtd" >
<xliff version="1.0">
  <file original="global" source-language="en" target-
language="vu_VU" datatype="plaintext">
    <header />
    <body>
      <!-- Actions -->
      <trans-unit>
        <source>New</source>
                               startrek.vu.xml
        <target>Uzh</target>
      </trans-unit>
      <trans-unit>
        <source>Edit</source>
        <target>Ver-tor</target>
      </trans-unit>
...
4. Translate admin interface
  Tell admin generator to use alternative catalogue
           generator:
             class: sfDoctrineGenerator
             param:
               i18n_catalogue: startrek

  Tell the forms as well – sfFormDoctrine::setup()
abstract class BaseFormDoctrine extends sfFormDoctrine
{
  public function setup()
  {
    $this->widgetSchema->getFormFormatter()
       ->setTranslationCatalogue('startrek_forms');
  }
}
5. Tidy up filters
Filters work great – but the default style is a bit off




A few CSS tweaks
#sf_admin_container #sf_admin_bar   {
   float:none;
   margin-left: 0px;
}
#sf_admin_container #sf_admin_bar   .sf_admin_filter table tr {
   clear: none;
   border: 1px solid #DDD;
   padding: 0px;
}
#sf_admin_container #sf_admin_bar   .sf_admin_filter table tr td {
   height: 50px;
   vertical-align: middle;
   border: none;
}
#sf_admin_container #sf_admin_bar   .sf_admin_filter table tbody {
   clear: none;
   float: left;
}
#sf_admin_container #sf_admin_bar   .sf_admin_filter table tbody tr {
   float: left;
   border-right: none;
}
#sf_admin_container #sf_admin_bar   .sf_admin_filter table tfoot {
   clear: none;
   float: right;
}
#sf_admin_container #sf_admin_bar   .sf_admin_filter table tfoot tr {
   float: right;
}
                                              Thanks to Sebastien
What is the definition of
     programmer?

Programmers are machines that turn
        coffee into code.
6. Timestampable fields
   Generally don’t need to edit these



   Simply unset them in form class
class NewsForm extends BaseNewsForm
{
  public function configure()
  {
    unset($this['created_at'], $this['updated_at']);
  }
}
6. Timestampable fields
What if you still need to see the value?
6. Timestampable fields
         Use sfWidgetFormPlain widget
    http://trac.symfony-project.org/attachment/ticket/7963/sfWidgetPlain.diff


public function configure()
{
 $this->setWidget('created_at',
   new sfWidgetFormPlain(array('value'=>$this->getObject()->created_at)));

unset($this->validatorSchema['created_at']);

$this->setWidget('updated_at',
  new sfWidgetFormPlain(array('value'=>$this->getObject()->updated_at)));

 unset($this->validatorSchema['updated_at']);
...



                                                            Thanks to Stephen.Ostrow
7. Pre-filter list
7. Pre-filter list
        Add an object action to generator.yml
list:
  object_actions:
    _edit:        ~
    viewPhones:   { label: Phone numbers, action: viewPhones }


        Set filter atribute in user session
class employeeActions extends autoEmployeeActions
{
   public function executeViewPhones($request){

         $this->getUser()->setAttribute(
            'phone.filters',
            array('employee_id' => $request->getParameter('id')),
            'admin_module'
            );
         $this->redirect($this->generateUrl('phone'));
    }
}
8. Row level ownership
Only allow owners of objects access
Example presumes:
  sfGuard plugin is installed
  Objects have a user_id field fk
8. Row level ownership
Secure the list page - moduleActions::buildquery()

protected function buildQuery(){

    $query = parent::buildQuery();

    $query->andWhere(
     'user_id = ?', $this->getUser()->getId()
    );

    return $query;
}                            This belongs in the model!!
8. Row level ownership
        Secure all other actions - moduleActions::preExecute()
public function preExecute(){

    if($this->getActionName()!= 'new' &&
                       $this->getActionName()!= 'index'){

        $this->forward404Unless(

          $this->getUser()->isOwner($this->getRoute()->getObject())

        );
    }

    parent::preExecute();
}
8. Row level ownership
    Add a new method to user class - myUser::isOwner()

class myUser extends sfGuardSecurityUser
{
  public function isOwner($obj){

        if(is_object($obj)){

          if($this->getId() == $obj->getUserId()) return true;

        }
        return false;
    }
}
8. Row level ownership
What about the user_id field in the form?
  Don’t want users to change owner
  Also be careful with injected data
8. Row level ownership
   We need to remove the widget - Form::configure()
           public function configure()
             {
               unset($this['user_id']);
             ...

   Set the user_id manually – Form::doUpdateObject()
public function doUpdateObject($values){

        $userId = sfContext::getInstance()->getUser()->getId();
        $this->getObject()->setUserId($userId);

        return parent::doUpdateObject($values);
    }
                               eatmymonkeydust.com
9. Custom filters
Find out who has a birthday today
Add the new filter name to generator.yml
filter:
  display: [ name, birthday_today ]
  fields:
    birthday_today:
      help: Employees who have a birthday today!




                           Based on info from Tomasz Ducin and dlepage
9. Custom filters
Create a new widget in - xxFormFilter::configure()
public function configure()
{
  $this->widgetSchema['birthday_today'] =
    new sfWidgetFormInputCheckbox();

    $this->validatorSchema['birthday_today'] =
      new sfValidatorPass();
}

Filter form is now displayed
9. Custom filters
      Add a add*ColumnQuery to FormFilter class

public function addBirthdayTodayColumnQuery($query,$field,$value)
{
  if($value){
    $query->andWhere("SUBSTRING(`birthday`, 6, 5)
                    = SUBSTRING(NOW(), 6, 5)");
  }

return $query;
}


      Now buy the presents!
Plugins
sfAdminDashPlugin
     Kevin Bond
            Joomla style admin
            Adds a dashboard
            Configurable admin
            navigation

            Replaces the admin css
            Manually add header
            component and footer
            partial to layout
sfAdminThemejRollerPlugin
       Gerald Estadieu
                 Looks stunning
                 jQuery
                 Theme roller system
                 Popup filters
                 Tabs in edit view

                 Completely new admin
                 theme
Optimist : The glass is half full.
Pessimist : The glass is half empty..
  Coder: The glass is twice as big as it needs
                     to be
Extending Methods

What degree of customisation do you need?
Will you need to re-use the functionality?
Extending - CSS
Define an alternative CSS
     generator:
          class: sfDoctrineGenerator
          param:
            model_class:           News
            theme:                 admin
            non_verbose_templates: true
            with_show:             false
            singular:              ~
            plural:                ~
            route_prefix:          news
            with_doctrine_route:   1
            css:                   funkystyle
Extending - Override code
Override individual templates and actions
Quick and easy
Can’t be re-used between modules
Can become untidy
Extending – Create a theme
More work upfront
Can be used for multiple modules / projects
Much more scope for customising
Steep learning curve – PHP in PHP!
Extending – Create a theme
     Create container folder for new theme
    mkdir -p data/generator/sfDoctrineModule/newtheme




    Copy the generator files from sfDoctrine plugin
cp -r lib/vendor/symfony/lib/plugins/

→ sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/*

→   data/generator/sfDoctrineModule/newtheme/
Extending – Create a theme
      Name of theme

             Parts – Snippets of code
             included into cache

             Skeleton – copied to admin
             module

                Templates – generated into
                cache
Extending – Create a theme
Change theme name in generator.yml
    generator:
      class: sfDoctrineGenerator
      param:
        model_class:           News
        theme:                 newtheme
    ...


Clear cache

You’ve made your own theme!
Extending – Admin events
admin.pre_execute: Notified before any action is
executed.
admin.build_criteria: Filters the Criteria used for the
list view.
admin.save_object: Notified just after an object is
saved.
admin.delete_object: Notified just before an object
will be deleted.
So, what does…


                 …do?
Dashboard




Show
related
models
Object history



Delete related
objects
warning
Future….
What do you want the admin generator to do?
What should the scope of the generator be?

Better support for embedded forms?
More customisable list view (sfGrid)?
Fulltext search in the fields?
Saving goes back to list view?
Dashboard?
Nested sets? Ordering?
Inherit from multiple themes?
Thanks for listening!
   Twitter: @jcleveley
1 of 66

Recommended

Curso Symfony - Clase 4 by
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4Javier Eguiluz
2.1K views89 slides
Curso Symfony - Clase 2 by
Curso Symfony - Clase 2Curso Symfony - Clase 2
Curso Symfony - Clase 2Javier Eguiluz
1.8K views135 slides
Django Forms: Best Practices, Tips, Tricks by
Django Forms: Best Practices, Tips, TricksDjango Forms: Best Practices, Tips, Tricks
Django Forms: Best Practices, Tips, TricksShawn Rider
23.4K views18 slides
Kyiv.py #17 Flask talk by
Kyiv.py #17 Flask talkKyiv.py #17 Flask talk
Kyiv.py #17 Flask talkAlexey Popravka
500 views23 slides
HTML::FormFu talk for Sydney PM by
HTML::FormFu talk for Sydney PMHTML::FormFu talk for Sydney PM
HTML::FormFu talk for Sydney PMDean Hamstead
1.2K views38 slides
Apostrophe (improved Paris edition) by
Apostrophe (improved Paris edition)Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)tompunk
3.3K views41 slides

More Related Content

What's hot

Forms, Getting Your Money's Worth by
Forms, Getting Your Money's WorthForms, Getting Your Money's Worth
Forms, Getting Your Money's WorthAlex Gaynor
6.9K views26 slides
Synapseindia reviews sharing intro cakephp by
Synapseindia reviews sharing intro cakephpSynapseindia reviews sharing intro cakephp
Synapseindia reviews sharing intro cakephpSynapseindiaComplaints
517 views65 slides
Flask patterns by
Flask patternsFlask patterns
Flask patternsit-people
7.3K views43 slides
Curso Symfony - Clase 3 by
Curso Symfony - Clase 3Curso Symfony - Clase 3
Curso Symfony - Clase 3Javier Eguiluz
1.3K views83 slides
CRUD with Dojo by
CRUD with DojoCRUD with Dojo
CRUD with DojoEugene Lazutkin
4.9K views57 slides
WordPress REST API hacking by
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hackingJeroen van Dijk
3.7K views52 slides

What's hot(20)

Forms, Getting Your Money's Worth by Alex Gaynor
Forms, Getting Your Money's WorthForms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Alex Gaynor6.9K views
Flask patterns by it-people
Flask patternsFlask patterns
Flask patterns
it-people7.3K views
15.exemplu complet eloquent view add-edit-delete-search by Razvan Raducanu, PhD
15.exemplu complet eloquent view add-edit-delete-search15.exemplu complet eloquent view add-edit-delete-search
15.exemplu complet eloquent view add-edit-delete-search
Workshop: Symfony2 Intruduction: (Controller, Routing, Model) by Antonio Peric-Mazar
Workshop: Symfony2 Intruduction: (Controller, Routing, Model)Workshop: Symfony2 Intruduction: (Controller, Routing, Model)
Workshop: Symfony2 Intruduction: (Controller, Routing, Model)
Getting started with Rails (2), Season 2 by RORLAB
Getting started with Rails (2), Season 2Getting started with Rails (2), Season 2
Getting started with Rails (2), Season 2
RORLAB792 views
Custom post-framworks by Kiera Howe
Custom post-framworksCustom post-framworks
Custom post-framworks
Kiera Howe71 views
A Little Backbone For Your App by Luca Mearelli
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
Luca Mearelli2.5K views
Rest API using Flask & SqlAlchemy by Alessandro Cucci
Rest API using Flask & SqlAlchemyRest API using Flask & SqlAlchemy
Rest API using Flask & SqlAlchemy
Alessandro Cucci2.7K views
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python... by Edureka!
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
Python Flask Tutorial For Beginners | Flask Web Development Tutorial | Python...
Edureka!2.1K views
Apache Click by 오석 한
Apache ClickApache Click
Apache Click
오석 한374 views
WordPress plugin #2 by giwoolee
WordPress plugin #2WordPress plugin #2
WordPress plugin #2
giwoolee396 views
Using Geeklog as a Web Application Framework by Dirk Haun
Using Geeklog as a Web Application FrameworkUsing Geeklog as a Web Application Framework
Using Geeklog as a Web Application Framework
Dirk Haun894 views
Custom Signals for Uncoupled Design by ecomsmith
Custom Signals for Uncoupled DesignCustom Signals for Uncoupled Design
Custom Signals for Uncoupled Design
ecomsmith1.5K views

Viewers also liked

Plano de Estudos para Concurso INSS by
Plano de Estudos para Concurso INSSPlano de Estudos para Concurso INSS
Plano de Estudos para Concurso INSSEstratégia Concursos
107.2K views2 slides
Plano de Estudo para o TRE-SP (Técnico Judiciário) by
Plano de Estudo para o TRE-SP (Técnico Judiciário)Plano de Estudo para o TRE-SP (Técnico Judiciário)
Plano de Estudo para o TRE-SP (Técnico Judiciário)Ricardo Torques
43.1K views18 slides
The Naked Bundle - Symfony Live London 2014 by
The Naked Bundle - Symfony Live London 2014The Naked Bundle - Symfony Live London 2014
The Naked Bundle - Symfony Live London 2014Matthias Noback
4K views110 slides
Presentation1 by
Presentation1Presentation1
Presentation1D Yogendra Rao
422 views11 slides
Have you played this Symfony? Why Symfony is great choice for Web development by
Have you played this Symfony? Why Symfony is great choice for Web developmentHave you played this Symfony? Why Symfony is great choice for Web development
Have you played this Symfony? Why Symfony is great choice for Web developmentMike Taylor
1.7K views30 slides
Kotlin Developer Starter in Android projects by
Kotlin Developer Starter in Android projectsKotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projectsBartosz Kosarzycki
5.1K views29 slides

Viewers also liked(20)

Plano de Estudo para o TRE-SP (Técnico Judiciário) by Ricardo Torques
Plano de Estudo para o TRE-SP (Técnico Judiciário)Plano de Estudo para o TRE-SP (Técnico Judiciário)
Plano de Estudo para o TRE-SP (Técnico Judiciário)
Ricardo Torques43.1K views
The Naked Bundle - Symfony Live London 2014 by Matthias Noback
The Naked Bundle - Symfony Live London 2014The Naked Bundle - Symfony Live London 2014
The Naked Bundle - Symfony Live London 2014
Matthias Noback4K views
Have you played this Symfony? Why Symfony is great choice for Web development by Mike Taylor
Have you played this Symfony? Why Symfony is great choice for Web developmentHave you played this Symfony? Why Symfony is great choice for Web development
Have you played this Symfony? Why Symfony is great choice for Web development
Mike Taylor1.7K views
Kotlin Developer Starter in Android projects by Bartosz Kosarzycki
Kotlin Developer Starter in Android projectsKotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projects
Bartosz Kosarzycki5.1K views
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more by Ryan Weaver
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and moreSymfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Ryan Weaver32.1K views
Weaving aspects in PHP with the help of Go! AOP library by Alexander Lisachenko
Weaving aspects in PHP with the help of Go! AOP libraryWeaving aspects in PHP with the help of Go! AOP library
Weaving aspects in PHP with the help of Go! AOP library
Alexander Lisachenko72.6K views
Symfony: Your Next Microframework (SymfonyCon 2015) by Ryan Weaver
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
Ryan Weaver7.6K views
Plano de Estudos para o XIX Exame da OAB by Ricardo Torques
Plano de Estudos para o XIX Exame da OABPlano de Estudos para o XIX Exame da OAB
Plano de Estudos para o XIX Exame da OAB
Ricardo Torques8.2K views
Plano de Estudo para o TRE-SP (Analista Judiciário - Área Administrativa) by Ricardo Torques
Plano de Estudo para o TRE-SP (Analista Judiciário - Área Administrativa)Plano de Estudo para o TRE-SP (Analista Judiciário - Área Administrativa)
Plano de Estudo para o TRE-SP (Analista Judiciário - Área Administrativa)
Ricardo Torques40.4K views
Plano de Estudo para o TRE-SP (Analista Judiciário - Área Judiciária) by Ricardo Torques
Plano de Estudo para o TRE-SP (Analista Judiciário - Área Judiciária)Plano de Estudo para o TRE-SP (Analista Judiciário - Área Judiciária)
Plano de Estudo para o TRE-SP (Analista Judiciário - Área Judiciária)
Ricardo Torques39.3K views
Comentários à prova de Pessoas com Deficiência - TRT 11ª Região by Ricardo Torques
Comentários à prova de Pessoas com Deficiência - TRT 11ª RegiãoComentários à prova de Pessoas com Deficiência - TRT 11ª Região
Comentários à prova de Pessoas com Deficiência - TRT 11ª Região
Ricardo Torques3.9K views
Event management system by D Yogendra Rao
Event management systemEvent management system
Event management system
D Yogendra Rao39.7K views
Tabela Editais FCC de Raciocínio Lógico e Matemática by Estratégia Concursos
Tabela Editais FCC de Raciocínio Lógico e MatemáticaTabela Editais FCC de Raciocínio Lógico e Matemática
Tabela Editais FCC de Raciocínio Lógico e Matemática

Similar to Working With The Symfony Admin Generator

Simplify your professional web development with symfony by
Simplify your professional web development with symfonySimplify your professional web development with symfony
Simplify your professional web development with symfonyFrancois Zaninotto
2.7K views40 slides
Symfony2 Introduction Presentation by
Symfony2 Introduction PresentationSymfony2 Introduction Presentation
Symfony2 Introduction PresentationNerd Tzanetopoulos
10.5K views34 slides
Symfony2 revealed by
Symfony2 revealedSymfony2 revealed
Symfony2 revealedFabien Potencier
42.5K views135 slides
Zend Framework 1.9 Setup & Using Zend_Tool by
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolGordon Forsythe
8.5K views41 slides
CodeIgniter PHP MVC Framework by
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkBo-Yi Wu
27.4K views87 slides
Build powerfull and smart web applications with Symfony2 by
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Hugo Hamon
6.4K views59 slides

Similar to Working With The Symfony Admin Generator(20)

Simplify your professional web development with symfony by Francois Zaninotto
Simplify your professional web development with symfonySimplify your professional web development with symfony
Simplify your professional web development with symfony
Francois Zaninotto2.7K views
Zend Framework 1.9 Setup & Using Zend_Tool by Gordon Forsythe
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_Tool
Gordon Forsythe8.5K views
CodeIgniter PHP MVC Framework by Bo-Yi Wu
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
Bo-Yi Wu27.4K views
Build powerfull and smart web applications with Symfony2 by Hugo Hamon
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
Hugo Hamon6.4K views
Web internship Yii Framework by Noveo
Web internship  Yii FrameworkWeb internship  Yii Framework
Web internship Yii Framework
Noveo993 views
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss... by King Foo
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
King Foo1.2K views
WebNet Conference 2012 - Designing complex applications using html5 and knock... by Fabio Franzini
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Fabio Franzini1.6K views
Workshop quality assurance for php projects tek12 by Michelangelo van Dam
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
Folio3 - An Introduction to PHP Yii by Folio3 Software
Folio3 - An Introduction to PHP YiiFolio3 - An Introduction to PHP Yii
Folio3 - An Introduction to PHP Yii
Folio3 Software1.1K views
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later by Haehnchen
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
Haehnchen1.7K views
Drupal Best Practices by manugoel2003
Drupal Best PracticesDrupal Best Practices
Drupal Best Practices
manugoel20035.4K views
WordPress basic fundamental of plugin development and creating shortcode by Rakesh Kushwaha
WordPress basic fundamental of plugin development and creating shortcodeWordPress basic fundamental of plugin development and creating shortcode
WordPress basic fundamental of plugin development and creating shortcode
Rakesh Kushwaha3.5K views
Some tips to improve developer experience with Symfony by tyomo4ka
Some tips to improve developer experience with SymfonySome tips to improve developer experience with Symfony
Some tips to improve developer experience with Symfony
tyomo4ka1.9K views
Ctools presentation by Digitaria
Ctools presentationCtools presentation
Ctools presentation
Digitaria2.2K views
First Steps in Drupal Code Driven Development by Nuvole
First Steps in Drupal Code Driven DevelopmentFirst Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven Development
Nuvole7.5K views
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013) by arcware
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
arcware4.2K views
Getting started with WordPress development by Steve Mortiboy
Getting started with WordPress developmentGetting started with WordPress development
Getting started with WordPress development
Steve Mortiboy1.3K views
Codebits 2012 - Fast relational web site construction. by Nelson Gomes
Codebits 2012 - Fast relational web site construction.Codebits 2012 - Fast relational web site construction.
Codebits 2012 - Fast relational web site construction.
Nelson Gomes767 views

Recently uploaded

Powerful Google developer tools for immediate impact! (2023-24) by
Powerful Google developer tools for immediate impact! (2023-24)Powerful Google developer tools for immediate impact! (2023-24)
Powerful Google developer tools for immediate impact! (2023-24)wesley chun
10 views38 slides
Democratising digital commerce in India-Report by
Democratising digital commerce in India-ReportDemocratising digital commerce in India-Report
Democratising digital commerce in India-ReportKapil Khandelwal (KK)
15 views161 slides
PharoJS - Zürich Smalltalk Group Meetup November 2023 by
PharoJS - Zürich Smalltalk Group Meetup November 2023PharoJS - Zürich Smalltalk Group Meetup November 2023
PharoJS - Zürich Smalltalk Group Meetup November 2023Noury Bouraqadi
127 views17 slides
Scaling Knowledge Graph Architectures with AI by
Scaling Knowledge Graph Architectures with AIScaling Knowledge Graph Architectures with AI
Scaling Knowledge Graph Architectures with AIEnterprise Knowledge
30 views15 slides
Business Analyst Series 2023 - Week 3 Session 5 by
Business Analyst Series 2023 -  Week 3 Session 5Business Analyst Series 2023 -  Week 3 Session 5
Business Analyst Series 2023 - Week 3 Session 5DianaGray10
248 views20 slides
Ransomware is Knocking your Door_Final.pdf by
Ransomware is Knocking your Door_Final.pdfRansomware is Knocking your Door_Final.pdf
Ransomware is Knocking your Door_Final.pdfSecurity Bootcamp
55 views46 slides

Recently uploaded(20)

Powerful Google developer tools for immediate impact! (2023-24) by wesley chun
Powerful Google developer tools for immediate impact! (2023-24)Powerful Google developer tools for immediate impact! (2023-24)
Powerful Google developer tools for immediate impact! (2023-24)
wesley chun10 views
PharoJS - Zürich Smalltalk Group Meetup November 2023 by Noury Bouraqadi
PharoJS - Zürich Smalltalk Group Meetup November 2023PharoJS - Zürich Smalltalk Group Meetup November 2023
PharoJS - Zürich Smalltalk Group Meetup November 2023
Noury Bouraqadi127 views
Business Analyst Series 2023 - Week 3 Session 5 by DianaGray10
Business Analyst Series 2023 -  Week 3 Session 5Business Analyst Series 2023 -  Week 3 Session 5
Business Analyst Series 2023 - Week 3 Session 5
DianaGray10248 views
Special_edition_innovator_2023.pdf by WillDavies22
Special_edition_innovator_2023.pdfSpecial_edition_innovator_2023.pdf
Special_edition_innovator_2023.pdf
WillDavies2217 views
Unit 1_Lecture 2_Physical Design of IoT.pdf by StephenTec
Unit 1_Lecture 2_Physical Design of IoT.pdfUnit 1_Lecture 2_Physical Design of IoT.pdf
Unit 1_Lecture 2_Physical Design of IoT.pdf
StephenTec12 views
Five Things You SHOULD Know About Postman by Postman
Five Things You SHOULD Know About PostmanFive Things You SHOULD Know About Postman
Five Things You SHOULD Know About Postman
Postman33 views
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLive by Network Automation Forum
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLiveAutomating a World-Class Technology Conference; Behind the Scenes of CiscoLive
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLive
Piloting & Scaling Successfully With Microsoft Viva by Richard Harbridge
Piloting & Scaling Successfully With Microsoft VivaPiloting & Scaling Successfully With Microsoft Viva
Piloting & Scaling Successfully With Microsoft Viva
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas... by Bernd Ruecker
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...
iSAQB Software Architecture Gathering 2023: How Process Orchestration Increas...
Bernd Ruecker37 views
【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院 by IttrainingIttraining
【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院
【USB韌體設計課程】精選講義節錄-USB的列舉過程_艾鍗學院

Working With The Symfony Admin Generator

  • 1. Working with the admin generator
  • 2. My background John Cleveley Trained as a Systems Engineer with BAE Systems Started my own business in 2006 Created symfony apps for NHS, V&A Museum and Hornby. Currently work at the BBC using their Forge platform (ZF)
  • 4. Objectives Provide information beyond the docs Update on what’s new Suggest a few best practices Real world examples of customising How to get the best from the form framework Utilise the various ways of extending
  • 5. It’s super awesome. Saves huge amount of development time and costs Provides most common admin requirements out of the box Can be extended to provide bespoke needs Fully tested and documented It’s free!
  • 6. What’s new since 1.0? Completely re-written for the form framework Relationships including m2m work without configuration Generator.yml is validated Batch actions (delete) Less reliance on generator.yml (DRY) More templates and actions to override Different configuration for the edit and new form Adds a REST route for your module
  • 7. New PHP configuration file Configure generator via PHP to be more dynamic: lib/newsGeneratorConfiguration.class.php The generated class in the cache lists functions cache/backend/dev/modules/autoNews/lib/BaseNe wsGeneratorConfiguration.class.php You can also mix configuration between the two
  • 8. New helper file Provides html snippets for action links lib/[module]GeneratorHelper.class.php getUrlForAction () linkToDelete () linkToEdit () linkToList () linkToNew () linkToSave () linkToSaveAndAdd () Create custom links with extra javascript etc
  • 10. Is it the right tool? …maybe.
  • 11. Think requirements! Don’t jump to use the admin generator Analyse what’s needed first A bespoke solution may be more appropriate Misusing the admin generator could cause big problems in the future
  • 12. How do we decide? Admin Bespoke Normal CRUD operations Public interface to data Non – technical users Sophisticated sorting need to add data and searching of data Trusted site administrators Ownership of all records The admin site can take you a long way…. …. But be careful it doesn’t become a mess.
  • 14. 10 Commandments (1-5) 1. Understand the client’s workflow and customise admin to suit 2. Think about security from the start 3. Look through and understand the cached php files 4. Change table_method to reduce db calls 5. Use bespoke Form class for admin if different
  • 15. 10 Commandments (6-10) 6. Keep all form form configuration in the Form Class 7. If you need to make changes to multiple admin modules – create a theme. 8. Think about small screens and target browser 9. Create functional tests – guard against regression 10. Maintain good MVC and decoupling practices
  • 16. What’s the object-oriented way to become wealthy? Inheritance!
  • 18. 1. The URL Clients don’t like using: application.com/admin.php Option 1: application.com/admin Option 2: admin.application.com
  • 19. 1. The URL: /admin Modify web/.htaccess RewriteCond %{REQUEST_URI} ^/admin/? RewriteRule ^(.*)$ admin.php [QSA,L] RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php [QSA,L] Change all your standard routes – routing.yml homepage: url: /admin param: { module: default, action: index } test: url: /admin/test ...
  • 20. 1. The URL: /admin Change your route collections – routing.yml prefix_path: /admin/module_name Remove script name in urls – settings.yml prod: .settings: no_script_name: true
  • 21. 1. The URL: admin.app Create a new virtual host in httpd.conf <VirtualHost *:80> ServerName admin.application.com DirectoryIndex admin.php DocumentRoot "/path/to/web/folder" <Directory "/path/to/web/folder"> AllowOverride All Allow from All </Directory> </VirtualHost> Tell symfony not to output admin.php in urls Prod .settings: no_script_name: true
  • 22. 2. Dynamic MaxPerPage Add a select box within the _list_header.php js onchange submits to action Add an action to set a user attribute public function executeChangeMaxPage(sfWebRequest $request){ $this->getUser()->setAttribute('maxPage', $request->getParameter('maxPage')); $this->redirect($request->getReferer()); }
  • 23. 2. Dynamic MaxPerPage Override getPagerMaxPerPage() class employeeGeneratorConfiguration extends BaseEmployee { public function getPagerMaxPerPage() { $maxPage = sfContext::getInstance()->getUser() ->getAttribute('maxPage', 10); return $maxPage; } }
  • 24. 3. Adding relations Fewest clicks for common tasks Relevant data placed together Currently unsupported by the generator Symfony provides functions to help sfForm : : mergeForm() sfForm : : embedForm() sfFormDoctrine : : embedRelation()
  • 25. Employee has many phones Employee: Phone: columns: columns: id: id: type: integer(4) type: integer(4) primary: true primary: true autoincrement: true autoincrement: true name: number: type: string(255) type: string(255) notnull: true notnull: true relations: employee_id: Phones: type: integer(4) type: many notnull: true class: Phone type: local: id type: enum foreign: employee_id values: [mobile, home, work] onDelete: CASCADE
  • 26. 3. Adding relations Add ability to edit existing phone numbers from within employee form Embed the ‘Phones’ relation in EmployeeForm::configure class EmployeeForm extends BaseEmployeeForm { public function configure() { $this->embedRelation('Phones'); } }
  • 27. Hide employee_id in PhoneForm::configure() class PhoneForm extends BasePhoneForm { public function configure() { $this->widgetSchema['employee_id'] = new sfWidgetFormInputHidden(); ... No Delete? No Add?
  • 28. There’s a symfony plugin for that! Thanks to ahDoctrineEasyEmbeddedRelationsPlugin by Daniel Lohse
  • 29. 4. Translate admin interface Add chosen culture to settings.yml .all: .settings: i18n: on default_culture: fr ./symfony cc and delete browser cookies
  • 30. 4. Translate admin interface Create a new startrek catalogue Add vulcan XLIFF files to: apps/admin/il8n/ • startrek.vu.xml • startrek_forms.vu.xml
  • 31. 4. Translate admin interface <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis- open.org/committees/xliff/documents/xliff.dtd" > <xliff version="1.0"> <file original="global" source-language="en" target- language="vu_VU" datatype="plaintext"> <header /> <body> <!-- Actions --> <trans-unit> <source>New</source> startrek.vu.xml <target>Uzh</target> </trans-unit> <trans-unit> <source>Edit</source> <target>Ver-tor</target> </trans-unit> ...
  • 32. 4. Translate admin interface Tell admin generator to use alternative catalogue generator: class: sfDoctrineGenerator param: i18n_catalogue: startrek Tell the forms as well – sfFormDoctrine::setup() abstract class BaseFormDoctrine extends sfFormDoctrine { public function setup() { $this->widgetSchema->getFormFormatter() ->setTranslationCatalogue('startrek_forms'); } }
  • 33. 5. Tidy up filters Filters work great – but the default style is a bit off A few CSS tweaks
  • 34. #sf_admin_container #sf_admin_bar { float:none; margin-left: 0px; } #sf_admin_container #sf_admin_bar .sf_admin_filter table tr { clear: none; border: 1px solid #DDD; padding: 0px; } #sf_admin_container #sf_admin_bar .sf_admin_filter table tr td { height: 50px; vertical-align: middle; border: none; } #sf_admin_container #sf_admin_bar .sf_admin_filter table tbody { clear: none; float: left; } #sf_admin_container #sf_admin_bar .sf_admin_filter table tbody tr { float: left; border-right: none; } #sf_admin_container #sf_admin_bar .sf_admin_filter table tfoot { clear: none; float: right; } #sf_admin_container #sf_admin_bar .sf_admin_filter table tfoot tr { float: right; } Thanks to Sebastien
  • 35. What is the definition of programmer? Programmers are machines that turn coffee into code.
  • 36. 6. Timestampable fields Generally don’t need to edit these Simply unset them in form class class NewsForm extends BaseNewsForm { public function configure() { unset($this['created_at'], $this['updated_at']); } }
  • 37. 6. Timestampable fields What if you still need to see the value?
  • 38. 6. Timestampable fields Use sfWidgetFormPlain widget http://trac.symfony-project.org/attachment/ticket/7963/sfWidgetPlain.diff public function configure() { $this->setWidget('created_at', new sfWidgetFormPlain(array('value'=>$this->getObject()->created_at))); unset($this->validatorSchema['created_at']); $this->setWidget('updated_at', new sfWidgetFormPlain(array('value'=>$this->getObject()->updated_at))); unset($this->validatorSchema['updated_at']); ... Thanks to Stephen.Ostrow
  • 40. 7. Pre-filter list Add an object action to generator.yml list: object_actions: _edit: ~ viewPhones: { label: Phone numbers, action: viewPhones } Set filter atribute in user session class employeeActions extends autoEmployeeActions { public function executeViewPhones($request){ $this->getUser()->setAttribute( 'phone.filters', array('employee_id' => $request->getParameter('id')), 'admin_module' ); $this->redirect($this->generateUrl('phone')); } }
  • 41. 8. Row level ownership Only allow owners of objects access Example presumes: sfGuard plugin is installed Objects have a user_id field fk
  • 42. 8. Row level ownership Secure the list page - moduleActions::buildquery() protected function buildQuery(){ $query = parent::buildQuery(); $query->andWhere( 'user_id = ?', $this->getUser()->getId() ); return $query; } This belongs in the model!!
  • 43. 8. Row level ownership Secure all other actions - moduleActions::preExecute() public function preExecute(){ if($this->getActionName()!= 'new' && $this->getActionName()!= 'index'){ $this->forward404Unless( $this->getUser()->isOwner($this->getRoute()->getObject()) ); } parent::preExecute(); }
  • 44. 8. Row level ownership Add a new method to user class - myUser::isOwner() class myUser extends sfGuardSecurityUser { public function isOwner($obj){ if(is_object($obj)){ if($this->getId() == $obj->getUserId()) return true; } return false; } }
  • 45. 8. Row level ownership What about the user_id field in the form? Don’t want users to change owner Also be careful with injected data
  • 46. 8. Row level ownership We need to remove the widget - Form::configure() public function configure() { unset($this['user_id']); ... Set the user_id manually – Form::doUpdateObject() public function doUpdateObject($values){ $userId = sfContext::getInstance()->getUser()->getId(); $this->getObject()->setUserId($userId); return parent::doUpdateObject($values); } eatmymonkeydust.com
  • 47. 9. Custom filters Find out who has a birthday today Add the new filter name to generator.yml filter: display: [ name, birthday_today ] fields: birthday_today: help: Employees who have a birthday today! Based on info from Tomasz Ducin and dlepage
  • 48. 9. Custom filters Create a new widget in - xxFormFilter::configure() public function configure() { $this->widgetSchema['birthday_today'] = new sfWidgetFormInputCheckbox(); $this->validatorSchema['birthday_today'] = new sfValidatorPass(); } Filter form is now displayed
  • 49. 9. Custom filters Add a add*ColumnQuery to FormFilter class public function addBirthdayTodayColumnQuery($query,$field,$value) { if($value){ $query->andWhere("SUBSTRING(`birthday`, 6, 5) = SUBSTRING(NOW(), 6, 5)"); } return $query; } Now buy the presents!
  • 51. sfAdminDashPlugin Kevin Bond Joomla style admin Adds a dashboard Configurable admin navigation Replaces the admin css Manually add header component and footer partial to layout
  • 52. sfAdminThemejRollerPlugin Gerald Estadieu Looks stunning jQuery Theme roller system Popup filters Tabs in edit view Completely new admin theme
  • 53. Optimist : The glass is half full. Pessimist : The glass is half empty.. Coder: The glass is twice as big as it needs to be
  • 54. Extending Methods What degree of customisation do you need? Will you need to re-use the functionality?
  • 55. Extending - CSS Define an alternative CSS generator: class: sfDoctrineGenerator param: model_class: News theme: admin non_verbose_templates: true with_show: false singular: ~ plural: ~ route_prefix: news with_doctrine_route: 1 css: funkystyle
  • 56. Extending - Override code Override individual templates and actions Quick and easy Can’t be re-used between modules Can become untidy
  • 57. Extending – Create a theme More work upfront Can be used for multiple modules / projects Much more scope for customising Steep learning curve – PHP in PHP!
  • 58. Extending – Create a theme Create container folder for new theme mkdir -p data/generator/sfDoctrineModule/newtheme Copy the generator files from sfDoctrine plugin cp -r lib/vendor/symfony/lib/plugins/ → sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/* → data/generator/sfDoctrineModule/newtheme/
  • 59. Extending – Create a theme Name of theme Parts – Snippets of code included into cache Skeleton – copied to admin module Templates – generated into cache
  • 60. Extending – Create a theme Change theme name in generator.yml generator: class: sfDoctrineGenerator param: model_class: News theme: newtheme ... Clear cache You’ve made your own theme!
  • 61. Extending – Admin events admin.pre_execute: Notified before any action is executed. admin.build_criteria: Filters the Criteria used for the list view. admin.save_object: Notified just after an object is saved. admin.delete_object: Notified just before an object will be deleted.
  • 65. Future…. What do you want the admin generator to do? What should the scope of the generator be? Better support for embedded forms? More customisable list view (sfGrid)? Fulltext search in the fields? Saving goes back to list view? Dashboard? Nested sets? Ordering? Inherit from multiple themes?
  • 66. Thanks for listening! Twitter: @jcleveley