One hour application
                            with symfony




vendredi 13 novembre 2009                  1
Aim



                 • Present symfony in an original way
                 • Make an application in one hour




vendredi 13 novembre 2009                               2
Who am I?
            • Philippe Gamache
              •PHP security expert at
               Parler Haut, Interagir
               Librement
              •Author of the book
               « Sécurité PHP 5 et MySQL »
               with Damien Seguy, at
               Eyrolles
              •http://www.ph-il.ca
              •http://www.phportail.net
              •http://lapageamelkor.org
              •naheulbeukauquebec.ca


vendredi 13 novembre 2009                    3
Questions?


                            ?
       Please wait at the
         end, we don’t
        have much time



vendredi 13 novembre 2009       4
The application


                 • Blog
                        • Comments
                        • Clean URLs




vendredi 13 novembre 2009                      5
Install symfony

         http://www.symfony-project.org/installation
                 • Source
                 • Sandbox
                 • PEAR
                 • SVN
                 • Linux Package (Debian and SUSE)

vendredi 13 novembre 2009                              6
Install using PEAR
      pear channel-discover pear.symfony-project.com
                            pear install symfony/symfony-1.2.4




vendredi 13 novembre 2009                                        7
Create the project
              • Create directory project
                     $ mkdir -p blog
                $ cd blog
              • Check symfony’s version
                $ symfony -V
              • Create project
                $ symfony generate:project blog




vendredi 13 novembre 2009                         8
Create the project
              • Create an application
                     $ symfony generate:app /
                       --escaping-strategy=on /
                       --csrf-secret=Unique$ecr3t1 /
                       frontend
              • Adjust your web server




vendredi 13 novembre 2009                              9
http://blog.local/frontend_dev.php/


vendredi 13 novembre 2009                                10
Activating sfDoctrine
                      // config/ProjectConfiguration.class.php
                      public function setup()
                      {
                        $this->enableAllPluginsExcept(
                          array('sfPropelPlugin',
                                'sfCompat10Plugin'));
                      }




vendredi 13 novembre 2009                                        11
The database
                 • Creating the database
                     $ mysqladmin -uroot -pmYsEcret /
                       create blog
                 • Configure the project
                     $ symfony configure:database /
                       --name=doctrine /
                       --class=sfDoctrineDatabase /
                       "mysql:host=localhost;dbname=blog" /
                       root mYsEcret
                 • Clear Propel connection

vendredi 13 novembre 2009                                     12
Plugins
                 • Installing plugins
             http://www.symfony-project.org/plugins/
                 • sfDoctrineGuardPlugin
                       $ symfony plugin:install /
                         sfDoctrineGuardPlugin /
                         --release=3.0.0




vendredi 13 novembre 2009                              13
The database diagram




vendredi 13 novembre 2009                   14
The databade model
     # config/doctrine/schema.yml
     actAs: [Timestampable]
                                       relations:
     BlogPost:                           Author:
       actAs:                              class: sfGuardUser
         Timestampable: ~                  local: author_id
         Sluggable:                        foreign: id
           fields: [title]                 type: one BlogComment:
           unique: true                columns:
       columns:                          blog_post_id: integer
         is_published:                   author_name:
           type: boolean                   type: string(255)
           default: false                  notnull: true
         allow_comments:                 author_email: string(255)
           type: boolean                 author_url: string(255)
           default: true                 content:
         author_id: integer(4)             type: string(5000)
         title:                            notnull: true
           type: string(255)           relations:
           notnull: true                 BlogPost:
         content:                          local: blog_post_id
           type: string(500000)            foreign: id
           notnull: true                   type: one
         published_at: date                foreignAlias: Comments




vendredi 13 novembre 2009                                            15
Database fixtures
               # data/fixtures/fixtures.yml
               sfGuardUser:
                 philippeg:
                   username: Philippe Gamache
                   password: password
                   is_super_admin: true

               sfGuardPermission:
                 sgp_admin:
                   name:            admin
                   description:     Administrator permission

               sfGuardGroup:
                 sgg_admin:
                   name:            admin
                   description:     Administrator group

               sfGuardGroupPermission:
                 sggp_admin:
                   sfGuardGroup:       sgg_admin
                   sfGuardPermission: sgp_admin

               sfGuardUserGroup:
                 sgug_admin:
                   sfGuardGroup:        sgg_admin
                   sfGuardUser:         philippeg


vendredi 13 novembre 2009                                      16
Database fixtures
          BlogPost:
            post_1:
              Author: philippeg
              title: Lorem ipsum dolor sit amet
              content: |
                <p>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut...</p>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do...</p>
              is_published: true
              published_at: 09-01-07
            post_2:
              Author: philippeg
              title: Ut enim ad minim veniam
              content: |
                <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris...</p>
                <p>Duis aute irure dolor in reprehenderit in voluptate velit esse...</p>
              is_published: true
              published_at: 09-01-07
            post_3:
              Author: philippeg
              title: Duis aute irure dolor in reprehenderit in voluptate
              content: |
                <p>Duis aute irure dolor in reprehenderit in voluptate velit esse...</p>
                <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris...</p>
              is_published: true
              published_at: 09-01-07
          ...


vendredi 13 novembre 2009                                                                      17
Database fixtures
               BlogComment:
                 comment_1:
                   BlogPost: post_1
                   author_name: lorem
                   content: Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut
               labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
               ullamco laboris nisi ut aliquip ex ea commodo consequat.
                 comment_2:
                   BlogPost: post_1
                   author_name: elit
                   content: Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
               dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident,
               sunt in culpa qui officia deserunt mollit anim id est laborum.
                 comment_3:
                   BlogPost: post_3
                   author_name: aute
                   content: Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
               officia deserunt mollit anim id est laborum.
                 comment_4:
                   BlogPost: post_3
                   author_name: aute
                   content: ESunt in culpa qui officia deserunt mollit anim id est laborum.




vendredi 13 novembre 2009                                                                           18
Create the tables
                 • Create the tables and load all fixtures
                       $ symfony doctrine:build-all-load




vendredi 13 novembre 2009                                   19
Creating the code
                 • Use the code generator
                       $ symfony doctrine:generate-crud /
                         --with-show frontend post BlogPost
                 • Delete unnecessary actions
                        • executeNew()
                        • executeEdit()
                        • executeUpdate()
                        • executeDelete()
                        • processForm()

vendredi 13 novembre 2009                                 20
Creating the code
                 • Delete unnecessary files
                        • templates/_form.php
                        • templates/editSuccess.php
                        • templates/newSuccess.php
                 • Clear links to other functions




vendredi 13 novembre 2009                             21
Creating the code
                 • Edit templates/indexSuccess.php
                       <?php foreach ($blog_post_list as $blog_post): ?>
                         <h2><?php echo link_to($blog_post->gettitle(), '@post_show?slug=' .
                       $blog_post->getslug()) ?></h2>
                         <div>By <?php echo $blog_post->getAuthor() ?> on <?php echo $blog_post-
                       >getpublished_at() ?></div>
                         <p>
                           <?php echo $blog_post->getContentSuccess() ?>
                         </p>
                         <p><?php echo link_to('Show more...', '@post_show?slug=' . $blog_post-
                       >getslug()) ?></p>
                         <br /><br />
                       <?php endforeach; ?>




vendredi 13 novembre 2009                                                                          22
Creating the code
                 • Edit templates/showSuccess.php
                       <h2><?php echo $blog_post->gettitle() ?></h2>
                       <div>By <?php echo $blog_post->getAuthor() ?> on <?php echo $blog_post-
                       >getpublished_at() ?></div>

                       <p><?php echo nl2br($blog_post->getcontent()) ?></p>

                       <hr /><br /><br />

                       <?php echo link_to('List', '@homepage') ?>




vendredi 13 novembre 2009                                                                        23
Creating the code
                 • Add to templates/layout.php
                       <div id="header">
                         <h1><?php echo link_to('My blog', '@homepage') ?></h1>
                       </div>

                       <div id="content">
                         <?php echo $sf_data->getRaw('sf_content') ?>
                       </div>
                       <div id="footer"></div>


                 • Modify web/css/main.css with blog.css




vendredi 13 novembre 2009                                                         24
Creating the code
                 • Edit actions.class.php
                            public function executeIndex(sfWebRequest $request)
                            {
                              $this->blog_post_list = Doctrine::getTable('BlogPost')
                                ->createQuery('a')
                                ->where('a.is_published = 1')
                                ->execute();
                            }

                            public function executeShow(sfWebRequest $request)
                            {
                              $this->blog_post = Doctrine::getTable('BlogPost')
                                ->findOneBySlug($request->getParameter('slug'));
                              $this->forward404Unless($this->blog_post);
                            }




vendredi 13 novembre 2009                                                              25
Creating the code
                 • Edit BlogPost.class.php
                            public function getContentSummary()
                            {
                              $out = explode('<', nl2br(substr($this->getcontent(), 0, 500)));
                              return $out[0] . '...';
                            }


                 • Modify to routing.yml
                       homepage:
                         url:    /
                         param: { module: post, action: index }

                       post_show:
                         url:   /:slug
                         param: { module: post, action: show }




vendredi 13 novembre 2009                                                                        26
Add comments
                 • Use the code generator
                       $ symfony doctrine:generate-crud /
                         frontend comment BlogComment
                 • Copy the code you’ll need




vendredi 13 novembre 2009                                   27
Add comments
                 • Edit code in actions.class.php
                            public function executeIndex(sfWebRequest $request)
                            {
                              $this->blog_post_list = Doctrine::getTable('BlogPost')
                                ->createQuery('p')
                                ->groupBy('p.published_at, p.id')
                                ->where('p.is_published = 1')
                                ->execute();
                            }

                            public function executeShow(sfWebRequest $request)
                            {
                              $this->blog_post = Doctrine::getTable('BlogPost')
                                ->findOneBySlug($request->getParameter('slug'));
                              $this->forward404Unless($this->blog_post);

                                $this->form = new BlogCommentForm();
                            }




vendredi 13 novembre 2009                                                              28
Add comments
                 • Add the code in actions.class.php
                            public function executeCreate(sfWebRequest $request)
                            {
                              $this->forward404Unless($request->isMethod('post'));
                              $this->blog_post = Doctrine::getTable('BlogPost')
                                ->findOneBySlug($request->getParameter('slug'));
                              $this->forward404Unless($this->blog_post);

                                $comment = new BlogComment();
                                $comment->setBlogPost($this->blog_post);

                                $this->form = new BlogCommentForm($comment);
                                $this->processForm($request, $this->form);

                                $this->setTemplate('show');
                            }




vendredi 13 novembre 2009                                                            29
Add comments
                 • Add the code in actions.class.php
                            public function processForm(sfWebRequest $request, sfForm $form)
                            {
                              $form->bind($request->getParameter($form->getName()));
                              if ($form->isValid())
                              {
                                $blog_comment = $form->save();
                                $this->redirect('@post_show?slug=' .
                                    $request->getParameter('slug'));
                              }
                            }

                 • Add to routing.yml
                        comment:
                          url:   /comment/:slug
                          param: { module: post, action: create }




vendredi 13 novembre 2009                                                                      30
Add comments
                 • Edit templates/showSuccess.php
                       ...
                       <p><?php echo nl2br($blog_post->getcontent()) ?></p>
                       <?php if (count($blog_post->getComments())): ?>
                         <ul id="comments">
                         <?php foreach ($blog_post->getComments() as $comment): ?>
                           <li class="comments">
                           <br />
                           <div class="bold">Posted on <?php echo $comment->getcreated_at() ?>
                       by <?php echo $comment->getauthor_name() ?> </div>
                           <p>
                              <?php echo $comment->getcontent() ?>
                           </p>
                           </li>
                         <?php endforeach; ?>
                         </ul>
                       <?php endif ?>
                       <br />
                       ...




vendredi 13 novembre 2009                                                                        31
Add comments
                 • Edit templates/showSuccess.php
                       ...

                       <p class="bold">Add your comment</p>
                       <br />
                       <?php include_partial('form',
                           array('form' => $form, 'blog_post' => $blog_post)) ?>
                       <hr /><br /><br />

                       <?php echo link_to('List', '@homepage') ?>




vendredi 13 novembre 2009                                                          32
Add comments
                 • Edit templates/indexSuccess.php
                       ...
                         <p>
                           <?php echo $blog_post->getContentSummary() ?>
                         </p>
                         <p>Comments (<?php echo count($blog_post->getComments()) ?>) :
                         <?php echo link_to('Show more', '@post_show?slug=' . $blog_post-
                       >getslug()) ?></p>
                         <br /><br />
                       <?php endforeach; ?>


                 • Move _form.php




vendredi 13 novembre 2009                                                                   33
Add comments
                 • Edit templates/_form.php
                       ...
                       <form action="<?php echo url_for('@comment?slug=' .
                         $blog_post->getSlug()) ?>" method="POST">
                       <?php if (!$form->getObject()->isNew()): ?>
                       <input type="hidden" name="sf_method" value="PUT" />
                       <?php endif; ?>
                         <table>
                       ...

                 • Keep only
                   • author_name
                   • author_email
                   • author_url
                   • content

vendredi 13 novembre 2009                                                     34
Add comments
                 • Edit BlogCommentForm.class.php
                            public function configure()
                            {
                              unset(
                                 $this['created_at'], $this['updated_at'],
                                 $this['blog_post_id']
                              );

                                $this->validatorSchema['author_email'] =
                                    new sfValidatorEmail(array('required' => false));
                                $this->validatorSchema['author_url'] =
                                    new sfValidatorUrl(array('required' => false));

                                $this->widgetSchema->setLabels(array(
                                  'author_email' => 'Your email ',
                                  'author_name'   => 'Your name ',
                                  'author_url'    => 'Web site ',
                                  'content'       => 'Comment ',
                                ));
                            }




vendredi 13 novembre 2009                                                               35
Backend creation
              • Create an application
                     $ symfony generate:app /
                       --escaping-strategy=on /
                       --csrf-secret=UniqueSecret /
                       backend




vendredi 13 novembre 2009                             36
Backend creation
              • Create modules
                     $ symfony doctrine:generate-admin /
                       --module=post backend BlogPost
                     $ symfony doctrine:generate-admin /
                       --module=comment backend /
                       BlogComment




vendredi 13 novembre 2009                                  37
Backend creation
              • Edit routing.yml
                        sf_guard_signin:
                          url:   /login
                          param: { module: sfGuardAuth, action: signin }

                        sf_guard_signout:
                          url:   /logout
                          param: { module: sfGuardAuth, action: signout }

                        sf_guard_password:
                          url:   /request_password
                          param: { module: sfGuardAuth, action: password }

                        # default rules
                        homepage:
                          url:    /
                          param: { module: post, action: index }




vendredi 13 novembre 2009                                                    38
Backend creation
                 • Add to templates/layout.php
                       <div id="header">
                         <h1><?php echo link_to('My blog', '@homepage') ?></h1>
                       </div>

                       <div id="menu">
                         <ul>
                           <li><?php echo link_to('Posts', '@blog_post_post') ?></li>
                           <li><?php echo link_to('Comments', '@blog_comment_comment') ?></li>
                         </ul>
                       </div>

                       <div id="content">
                         <?php echo $sf_data->getRaw('sf_content') ?>
                       </div>

                       <div id="footer"></div>


                 • Edit apps/frontend/config/view.yml

vendredi 13 novembre 2009                                                                        39
Backend creation
              • Edit setting.yml
                        ...
                        all:
                          .actions:
                             login_module:       sfGuardAuth
                             login_action:       signin

                            secure_module:       sfGuardAuth
                            secure_action:       secure
                          .settings:
                            enabled_modules:   [default, sfGuardAuth]
                        ...

              • Edit security.yml
                        default:
                          is_secure: on




vendredi 13 novembre 2009                                               40
Backend creation
              • Edit post generator.yml
                        ...
                              config:
                                actions: ~
                                fields: ~
                                list:
                                  title:   Message list
                                  display: [is_published, author_id, =title, published_at]
                                filter:
                                  display: [is_published]
                                form:    ~
                                edit:
                                  title: Edit post : "%%title%%"
                                  display: [is_published, author_id, title, content, published_at]
                                new:
                                  title: New post
                                  display: [is_published, author_id, title, content, published_at]




vendredi 13 novembre 2009                                                                            41
Backend creation
              • Edit comment generator.yml
                        ...
                              config:
                                actions: ~
                                  _delete: ~
                                  _list: ~
                                fields:
                                  ContentSummary:
                                     label: Comments
                                list:
                                  object_actions:
                                     _delete: ~
                                  actions:
                                     __: ~
                                  title:    Comments list
                                  display: [blog_post_id, =author_name, =ContentSummary]
                                filter:
                                  display: [blog_post_id]
                                form:     ~
                                edit:     ~
                                new:      ~



vendredi 13 novembre 2009                                                                  42
Backend creation
              • Edit myUser.class.php
                        class myUser extends sfGuardSecurityUser
                        {
                        }




vendredi 13 novembre 2009                                          43
To go further

                 • Add tags
                 • Add a mini-calendar
                 • Display posts per month
                 • Add search
                 • Add feeds (RSS, ATOM) via
                        sfFeed2plugins


vendredi 13 novembre 2009                      44
Questions?

  philippe.gamache@symfony-project.com
                 info@ph-il.ca
       http://www.symfoy-project.org
          http://www.phportail.net


vendredi 13 novembre 2009                45
vendredi 13 novembre 2009   46

One hour application - PHP Quebec Conference 2009

  • 1.
    One hour application with symfony vendredi 13 novembre 2009 1
  • 2.
    Aim • Present symfony in an original way • Make an application in one hour vendredi 13 novembre 2009 2
  • 3.
    Who am I? • Philippe Gamache •PHP security expert at Parler Haut, Interagir Librement •Author of the book « Sécurité PHP 5 et MySQL » with Damien Seguy, at Eyrolles •http://www.ph-il.ca •http://www.phportail.net •http://lapageamelkor.org •naheulbeukauquebec.ca vendredi 13 novembre 2009 3
  • 4.
    Questions? ? Please wait at the end, we don’t have much time vendredi 13 novembre 2009 4
  • 5.
    The application • Blog • Comments • Clean URLs vendredi 13 novembre 2009 5
  • 6.
    Install symfony http://www.symfony-project.org/installation • Source • Sandbox • PEAR • SVN • Linux Package (Debian and SUSE) vendredi 13 novembre 2009 6
  • 7.
    Install using PEAR pear channel-discover pear.symfony-project.com pear install symfony/symfony-1.2.4 vendredi 13 novembre 2009 7
  • 8.
    Create the project • Create directory project $ mkdir -p blog $ cd blog • Check symfony’s version $ symfony -V • Create project $ symfony generate:project blog vendredi 13 novembre 2009 8
  • 9.
    Create the project • Create an application $ symfony generate:app / --escaping-strategy=on / --csrf-secret=Unique$ecr3t1 / frontend • Adjust your web server vendredi 13 novembre 2009 9
  • 10.
  • 11.
    Activating sfDoctrine // config/ProjectConfiguration.class.php public function setup() { $this->enableAllPluginsExcept( array('sfPropelPlugin', 'sfCompat10Plugin')); } vendredi 13 novembre 2009 11
  • 12.
    The database • Creating the database $ mysqladmin -uroot -pmYsEcret / create blog • Configure the project $ symfony configure:database / --name=doctrine / --class=sfDoctrineDatabase / "mysql:host=localhost;dbname=blog" / root mYsEcret • Clear Propel connection vendredi 13 novembre 2009 12
  • 13.
    Plugins • Installing plugins http://www.symfony-project.org/plugins/ • sfDoctrineGuardPlugin $ symfony plugin:install / sfDoctrineGuardPlugin / --release=3.0.0 vendredi 13 novembre 2009 13
  • 14.
    The database diagram vendredi13 novembre 2009 14
  • 15.
    The databade model # config/doctrine/schema.yml actAs: [Timestampable] relations: BlogPost: Author: actAs: class: sfGuardUser Timestampable: ~ local: author_id Sluggable: foreign: id fields: [title] type: one BlogComment: unique: true columns: columns: blog_post_id: integer is_published: author_name: type: boolean type: string(255) default: false notnull: true allow_comments: author_email: string(255) type: boolean author_url: string(255) default: true content: author_id: integer(4) type: string(5000) title: notnull: true type: string(255) relations: notnull: true BlogPost: content: local: blog_post_id type: string(500000) foreign: id notnull: true type: one published_at: date foreignAlias: Comments vendredi 13 novembre 2009 15
  • 16.
    Database fixtures # data/fixtures/fixtures.yml sfGuardUser: philippeg: username: Philippe Gamache password: password is_super_admin: true sfGuardPermission: sgp_admin: name: admin description: Administrator permission sfGuardGroup: sgg_admin: name: admin description: Administrator group sfGuardGroupPermission: sggp_admin: sfGuardGroup: sgg_admin sfGuardPermission: sgp_admin sfGuardUserGroup: sgug_admin: sfGuardGroup: sgg_admin sfGuardUser: philippeg vendredi 13 novembre 2009 16
  • 17.
    Database fixtures BlogPost: post_1: Author: philippeg title: Lorem ipsum dolor sit amet content: | <p>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut...</p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do...</p> is_published: true published_at: 09-01-07 post_2: Author: philippeg title: Ut enim ad minim veniam content: | <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris...</p> <p>Duis aute irure dolor in reprehenderit in voluptate velit esse...</p> is_published: true published_at: 09-01-07 post_3: Author: philippeg title: Duis aute irure dolor in reprehenderit in voluptate content: | <p>Duis aute irure dolor in reprehenderit in voluptate velit esse...</p> <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris...</p> is_published: true published_at: 09-01-07 ... vendredi 13 novembre 2009 17
  • 18.
    Database fixtures BlogComment: comment_1: BlogPost: post_1 author_name: lorem content: Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. comment_2: BlogPost: post_1 author_name: elit content: Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. comment_3: BlogPost: post_3 author_name: aute content: Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. comment_4: BlogPost: post_3 author_name: aute content: ESunt in culpa qui officia deserunt mollit anim id est laborum. vendredi 13 novembre 2009 18
  • 19.
    Create the tables • Create the tables and load all fixtures $ symfony doctrine:build-all-load vendredi 13 novembre 2009 19
  • 20.
    Creating the code • Use the code generator $ symfony doctrine:generate-crud / --with-show frontend post BlogPost • Delete unnecessary actions • executeNew() • executeEdit() • executeUpdate() • executeDelete() • processForm() vendredi 13 novembre 2009 20
  • 21.
    Creating the code • Delete unnecessary files • templates/_form.php • templates/editSuccess.php • templates/newSuccess.php • Clear links to other functions vendredi 13 novembre 2009 21
  • 22.
    Creating the code • Edit templates/indexSuccess.php <?php foreach ($blog_post_list as $blog_post): ?> <h2><?php echo link_to($blog_post->gettitle(), '@post_show?slug=' . $blog_post->getslug()) ?></h2> <div>By <?php echo $blog_post->getAuthor() ?> on <?php echo $blog_post- >getpublished_at() ?></div> <p> <?php echo $blog_post->getContentSuccess() ?> </p> <p><?php echo link_to('Show more...', '@post_show?slug=' . $blog_post- >getslug()) ?></p> <br /><br /> <?php endforeach; ?> vendredi 13 novembre 2009 22
  • 23.
    Creating the code • Edit templates/showSuccess.php <h2><?php echo $blog_post->gettitle() ?></h2> <div>By <?php echo $blog_post->getAuthor() ?> on <?php echo $blog_post- >getpublished_at() ?></div> <p><?php echo nl2br($blog_post->getcontent()) ?></p> <hr /><br /><br /> <?php echo link_to('List', '@homepage') ?> vendredi 13 novembre 2009 23
  • 24.
    Creating the code • Add to templates/layout.php <div id="header"> <h1><?php echo link_to('My blog', '@homepage') ?></h1> </div> <div id="content"> <?php echo $sf_data->getRaw('sf_content') ?> </div> <div id="footer"></div> • Modify web/css/main.css with blog.css vendredi 13 novembre 2009 24
  • 25.
    Creating the code • Edit actions.class.php public function executeIndex(sfWebRequest $request) { $this->blog_post_list = Doctrine::getTable('BlogPost') ->createQuery('a') ->where('a.is_published = 1') ->execute(); } public function executeShow(sfWebRequest $request) { $this->blog_post = Doctrine::getTable('BlogPost') ->findOneBySlug($request->getParameter('slug')); $this->forward404Unless($this->blog_post); } vendredi 13 novembre 2009 25
  • 26.
    Creating the code • Edit BlogPost.class.php public function getContentSummary() { $out = explode('<', nl2br(substr($this->getcontent(), 0, 500))); return $out[0] . '...'; } • Modify to routing.yml homepage: url: / param: { module: post, action: index } post_show: url: /:slug param: { module: post, action: show } vendredi 13 novembre 2009 26
  • 27.
    Add comments • Use the code generator $ symfony doctrine:generate-crud / frontend comment BlogComment • Copy the code you’ll need vendredi 13 novembre 2009 27
  • 28.
    Add comments • Edit code in actions.class.php public function executeIndex(sfWebRequest $request) { $this->blog_post_list = Doctrine::getTable('BlogPost') ->createQuery('p') ->groupBy('p.published_at, p.id') ->where('p.is_published = 1') ->execute(); } public function executeShow(sfWebRequest $request) { $this->blog_post = Doctrine::getTable('BlogPost') ->findOneBySlug($request->getParameter('slug')); $this->forward404Unless($this->blog_post); $this->form = new BlogCommentForm(); } vendredi 13 novembre 2009 28
  • 29.
    Add comments • Add the code in actions.class.php public function executeCreate(sfWebRequest $request) { $this->forward404Unless($request->isMethod('post')); $this->blog_post = Doctrine::getTable('BlogPost') ->findOneBySlug($request->getParameter('slug')); $this->forward404Unless($this->blog_post); $comment = new BlogComment(); $comment->setBlogPost($this->blog_post); $this->form = new BlogCommentForm($comment); $this->processForm($request, $this->form); $this->setTemplate('show'); } vendredi 13 novembre 2009 29
  • 30.
    Add comments • Add the code in actions.class.php public function processForm(sfWebRequest $request, sfForm $form) { $form->bind($request->getParameter($form->getName())); if ($form->isValid()) { $blog_comment = $form->save(); $this->redirect('@post_show?slug=' . $request->getParameter('slug')); } } • Add to routing.yml comment: url: /comment/:slug param: { module: post, action: create } vendredi 13 novembre 2009 30
  • 31.
    Add comments • Edit templates/showSuccess.php ... <p><?php echo nl2br($blog_post->getcontent()) ?></p> <?php if (count($blog_post->getComments())): ?> <ul id="comments"> <?php foreach ($blog_post->getComments() as $comment): ?> <li class="comments"> <br /> <div class="bold">Posted on <?php echo $comment->getcreated_at() ?> by <?php echo $comment->getauthor_name() ?> </div> <p> <?php echo $comment->getcontent() ?> </p> </li> <?php endforeach; ?> </ul> <?php endif ?> <br /> ... vendredi 13 novembre 2009 31
  • 32.
    Add comments • Edit templates/showSuccess.php ... <p class="bold">Add your comment</p> <br /> <?php include_partial('form', array('form' => $form, 'blog_post' => $blog_post)) ?> <hr /><br /><br /> <?php echo link_to('List', '@homepage') ?> vendredi 13 novembre 2009 32
  • 33.
    Add comments • Edit templates/indexSuccess.php ... <p> <?php echo $blog_post->getContentSummary() ?> </p> <p>Comments (<?php echo count($blog_post->getComments()) ?>) : <?php echo link_to('Show more', '@post_show?slug=' . $blog_post- >getslug()) ?></p> <br /><br /> <?php endforeach; ?> • Move _form.php vendredi 13 novembre 2009 33
  • 34.
    Add comments • Edit templates/_form.php ... <form action="<?php echo url_for('@comment?slug=' . $blog_post->getSlug()) ?>" method="POST"> <?php if (!$form->getObject()->isNew()): ?> <input type="hidden" name="sf_method" value="PUT" /> <?php endif; ?> <table> ... • Keep only • author_name • author_email • author_url • content vendredi 13 novembre 2009 34
  • 35.
    Add comments • Edit BlogCommentForm.class.php public function configure() { unset( $this['created_at'], $this['updated_at'], $this['blog_post_id'] ); $this->validatorSchema['author_email'] = new sfValidatorEmail(array('required' => false)); $this->validatorSchema['author_url'] = new sfValidatorUrl(array('required' => false)); $this->widgetSchema->setLabels(array( 'author_email' => 'Your email ', 'author_name' => 'Your name ', 'author_url' => 'Web site ', 'content' => 'Comment ', )); } vendredi 13 novembre 2009 35
  • 36.
    Backend creation • Create an application $ symfony generate:app / --escaping-strategy=on / --csrf-secret=UniqueSecret / backend vendredi 13 novembre 2009 36
  • 37.
    Backend creation • Create modules $ symfony doctrine:generate-admin / --module=post backend BlogPost $ symfony doctrine:generate-admin / --module=comment backend / BlogComment vendredi 13 novembre 2009 37
  • 38.
    Backend creation • Edit routing.yml sf_guard_signin: url: /login param: { module: sfGuardAuth, action: signin } sf_guard_signout: url: /logout param: { module: sfGuardAuth, action: signout } sf_guard_password: url: /request_password param: { module: sfGuardAuth, action: password } # default rules homepage: url: / param: { module: post, action: index } vendredi 13 novembre 2009 38
  • 39.
    Backend creation • Add to templates/layout.php <div id="header"> <h1><?php echo link_to('My blog', '@homepage') ?></h1> </div> <div id="menu"> <ul> <li><?php echo link_to('Posts', '@blog_post_post') ?></li> <li><?php echo link_to('Comments', '@blog_comment_comment') ?></li> </ul> </div> <div id="content"> <?php echo $sf_data->getRaw('sf_content') ?> </div> <div id="footer"></div> • Edit apps/frontend/config/view.yml vendredi 13 novembre 2009 39
  • 40.
    Backend creation • Edit setting.yml ... all: .actions: login_module: sfGuardAuth login_action: signin secure_module: sfGuardAuth secure_action: secure .settings: enabled_modules: [default, sfGuardAuth] ... • Edit security.yml default: is_secure: on vendredi 13 novembre 2009 40
  • 41.
    Backend creation • Edit post generator.yml ... config: actions: ~ fields: ~ list: title: Message list display: [is_published, author_id, =title, published_at] filter: display: [is_published] form: ~ edit: title: Edit post : "%%title%%" display: [is_published, author_id, title, content, published_at] new: title: New post display: [is_published, author_id, title, content, published_at] vendredi 13 novembre 2009 41
  • 42.
    Backend creation • Edit comment generator.yml ... config: actions: ~ _delete: ~ _list: ~ fields: ContentSummary: label: Comments list: object_actions: _delete: ~ actions: __: ~ title: Comments list display: [blog_post_id, =author_name, =ContentSummary] filter: display: [blog_post_id] form: ~ edit: ~ new: ~ vendredi 13 novembre 2009 42
  • 43.
    Backend creation • Edit myUser.class.php class myUser extends sfGuardSecurityUser { } vendredi 13 novembre 2009 43
  • 44.
    To go further • Add tags • Add a mini-calendar • Display posts per month • Add search • Add feeds (RSS, ATOM) via sfFeed2plugins vendredi 13 novembre 2009 44
  • 45.
    Questions? philippe.gamache@symfony-project.com info@ph-il.ca http://www.symfoy-project.org http://www.phportail.net vendredi 13 novembre 2009 45
  • 46.