ZF 2

Zend Framework 2 tutorial (Album project)

I had a very enjoyable time at ZendCon 2013. IBM i folks were great as always. A few people asked me about the ZF2 album tutorial, so with a little help from Zend folks, here are my notes and modified example running on IBM i (this machine).

Notes after this page published for Zend Framework 2 tutorial (Album project below)

  • I have two configurations that work fine with Album demo
  • Some folks do not like UPPER case public data in Album model ($this→ID). I believe you can choose to map IBM i returned associative array $data[‘ID’] anyway you please, but i have not tested this idea.
    ** Note from customer …
    • I tested the idea. In the script file zf2-tutorial-ibmi/config/autoload/global.php, for ‘driver_options’ => array(), one option is the ‘DB2_ATTR_CASE’, it can be set to return either lower case or upper case by setting 'DB2_ATTR_CASE' => DB2_CASE_LOWER or 'DB2_ATTR_CASE' => DB2_CASE_UPPER . By default, upper case is returned, but if ‘DB2_CASE_LOWER’ is set in the ‘driver_options’, then lower case is returned. then we don’t need to change all the lower cases to upper cases from the original album project.
  • I received a recommendation to use __DIR__ for config/application.config.php, which works well (you may change after zip download)
     'config_glob_paths' => array(
                __DIR__ . '/autoload/{,*.}{global,local}.php', 
    

My running version of the Album project (just click the link to run completed project) …

  • see original document http://framework.zend.com/manual/2.0/en/user-guide/overview.html
    • http://174.79.32.155:86/album ← click here to run (VirtualHost based)
       
      Listen *:86
      <VirtualHost *:86>
        DocumentRoot /www/zendsvr6/htdocs/zf2-tutorial-ibmi/public
        SetEnv APPLICATION_ENV "development"
        <Directory /www/zendsvr6/htdocs/zf2-tutorial-ibmi/public>
          DirectoryIndex index.php
          AllowOverride All
          Order allow,deny
          Allow from all
          # FollowSymLinks is required for RewriteEngine On
          Options FollowSymLinks
        </Directory>
      </VirtualHost>
      # IMPORTANT: 
      # ZF2 Album "as is" public/.htaccess, or move into Directory httpd.conf.
      # Setting DocumentRoot works around failing IBM i .htaccess rule. 
      
    • http://174.79.32.155:10081/ZendMe/album ← click here to run (Alias based)
      Alias /ZendMe /www/zendsvr6/htdocs/zf2-tutorial-alias/public
      <Directory /www/zendsvr6/htdocs/zf2-tutorial-alias/public>
          DirectoryIndex index.php
          AllowOverride All
          Order allow,deny
          Allow from all
          Options FollowSymLinks
          RewriteEngine on  
      
          RewriteCond %{REQUEST_FILENAME} -s [OR]
          RewriteCond %{REQUEST_FILENAME} -l [OR]
          RewriteCond %{REQUEST_FILENAME} -d
          RewriteRule ^.*$ - [NC,L]
      
          RewriteCond %{REQUEST_URI}  !^index.php(.*)$ [NC]
          RewriteRule ^(.*)$ /ZendMe/index.php [L]
      </Directory>
      # IMPORTANT: 
      # Remove ZF2 Album public/.htaccess, and replace with above 
      # or leave in httpd.conf (demonstrated above).
      
      • Note: This is an education machine , therefore Zend Server 6 may start/stop, so retry later if run fails.
    • Attach:zf2-tutorial-ibmi.tar.zip - download completed application (without unit tests)
    • missing in notes (maybe)
      • we play with this education machine a lot, so i can’t remember if we changed php.ini file zendsvr6 for ZF2 (here you go)
      • bash-3.00$ grep Frame /usr/local/zendsvr6/etc/php.ini
        ;include_path = ".:/usr/local/zendsvr6/share/ZendFramework/library:/usr/local/zendsvr6/share/pear"
        include_path=".:/usr/local/zendsvr6/var/libraries/Zend_Framework_2/default/library:/usr/local/zendsvr6/share/pear:/usr/local/zendsvr6/share/ToolkitApi"
        
        
  • Follow instructions ZF2 tutorial for album project, but you need a few changes (see zf2-tutorial-ibmi/README_IBM_i)
    • ***********************************
      ***********************************
      ***********************************
      ***********************************
      http://framework.zend.com/manual/2.0/en/user-guide/overview.html
      Notes running zf2-tutorial-ibmi.tar.zip on IBM i
      ***********************************
      ***********************************
      ***********************************
      ***********************************
      
      installation:
      ======================
      PC or IBM i:
      unzip zf2-tutorial-ibmi.tar.zip
      IBM i:
      cd /www/zendsvr6/htdocs/
      tar -xf zf2-tutorial-ibmi.tar
      
      configuration:
      ======================
      /www/zendsvr6/conf/httpd.conf
      
      Choose the configuration suits your needs (note default zend deploy not work)
      
      -- or Virtual Host based http://174.79.32.155:86/album ---
      
      # ZF2 Tony Cairns
      Listen *:86
      <VirtualHost *:86>
        DocumentRoot /www/zendsvr6/htdocs/zf2-tutorial-ibmi/public
        SetEnv APPLICATION_ENV "development"
        <Directory /www/zendsvr6/htdocs/zf2-tutorial-ibmi/public>
          DirectoryIndex index.php
          AllowOverride All
          Order allow,deny
          Allow from all
          # FollowSymLinks is required for RewriteEngine On
          Options FollowSymLinks
        </Directory>
      </VirtualHost>
      # IMPORTANT: Leave .htaccess included in ZF2 Album "as is" in public/.htaccess.
      
      -- or Alias based http://174.79.32.155:10081/ZendMe/album ---
      
      Alias /ZendMe /www/zendsvr6/htdocs/zf2-tutorial-alias/public
      <Directory /www/zendsvr6/htdocs/zf2-tutorial-alias/public>
          DirectoryIndex index.php
          AllowOverride All
          Order allow,deny
          Allow from all
          Options FollowSymLinks
          RewriteEngine on  
      
          RewriteCond %{REQUEST_FILENAME} -s [OR]
          RewriteCond %{REQUEST_FILENAME} -l [OR]
          RewriteCond %{REQUEST_FILENAME} -d
          RewriteRule ^.*$ - [NC,L]
      
          RewriteCond %{REQUEST_URI}  !^index.php(.*)$ [NC]
          RewriteRule ^(.*)$ /ZendMe/index.php [L]
      </Directory>
      # IMPORTANT: Remove .htaccess included in ZF2 Album in public/.htaccess.
      
      create schema and table
      ============================
      web: http://myibmi:10080/zf2-tutorial-ibmi/public/ranger_create.php
      -- command line --
      cd zf2-tutorial-ibmi/public
      php ranger_create.php
      Note: 
      change ... $MYDB,$MYUID,$MYPWD
      
      change DB2 connection application:
      ======================
      zf2-tutorial-ibmi/config/autoload/global.php
      ------------
      return array(
          'db' => array(
              'driver' => 'IbmDb2',
              'db'     => '*LOCAL',
              // 'driver_options' => array(),
          ),
          'service_manager' => array(
              'factories' => array(
                  'Zend\Db\Adapter\Adapter'
                          => 'Zend\Db\Adapter\AdapterServiceFactory',
              ),
          ),
      );
      
      zf2-tutorial-ibmi/config/autoload/local.php:
      ------------
      return array(
          'db' => array(
              'username' => 'YOUR USERNAME HERE',
              'password' => 'YOUR PASSWORD HERE',
          ),
      );
      
      stop/start Apache ZENDSVR6
      =======================
      endTCPSVR SERVER(*HTTP) INSTANCE(ZENDSVR6)
      strTCPSVR SERVER(*HTTP) INSTANCE(ZENDSVR6)
      
      Optional -- mini web server test phase (if you do not want Apache configuration)
      ======================
      cd zf2-tutorial-ibmi/public
      php -S 0.0.0.0:8080 index.php
      
      ***********************************
      ***********************************
      ***********************************
      ***********************************
      http://framework.zend.com/manual/2.0/en/user-guide/overview.html
      Notes editing ZF2 tutorial example for IBM i
      (make demo work on IBM i with DB2)
      ***********************************
      ***********************************
      ***********************************
      ***********************************
      
      dirs
      ======================
      cd zf2-tutorial-ibmi
      mkdir -p module
      mkdir -p module/Album
      mkdir -p module/Album/config
      mkdir -p module/Album/src
      mkdir -p module/Album/src/Album
      mkdir -p module/Album/src/Album/Controller
      mkdir -p module/Album/src/Album/Form
      mkdir -p module/Album/src/Album/Model
      mkdir -p module/Album/view
      mkdir -p module/Album/view/album
      mkdir -p module/Album/view/album/album
      
      Routing
      =========================
      zf2-tutorial-ibmi/config/application.config.php
      ------------
        'config_glob_paths' => array(
                  '/www/zendsvr6/htdocs/zf2-tutorial-ibmi/config/autoload/{,*.}{global,local}.php',
        ),
      
      
      Driver and Credentials
      ======================
      zf2-tutorial-ibmi/config/autoload/global.php
      ------------
      return array(
          'db' => array(
              'driver' => 'IbmDb2',
              'db'     => 'MY IBM i SYSTEM',
              // 'driver_options' => array(),
          ),
          'service_manager' => array(
              'factories' => array(
                  'Zend\Db\Adapter\Adapter'
                          => 'Zend\Db\Adapter\AdapterServiceFactory',
              ),
          ),
      );
      
      zf2-tutorial-ibmi/config/autoload/local.php:
      ------------
      return array(
          'db' => array(
              'username' => 'YOUR USERNAME HERE',
              'password' => 'YOUR PASSWORD HERE',
          ),
      );
      
      Attribute & Index Changes
      =========================
      zf2-tutorial-ibmi/module/Album/Module.php
      ------------
                           $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                           $resultSetPrototype = new ResultSet();
                           $resultSetPrototype->setArrayObjectPrototype(new Album());
      -                    return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
      +                    return new TableGateway('ALBUM', $dbAdapter, null, $resultSetPrototype);
                       },
                   ),
               );
      
      zf2-tutorial-ibmi/module/Album/view/album/album/add.phtml
      ------------
       $form->prepare();
      
       echo $this->form()->openTag($form);
      -echo $this->formHidden($form->get('id'));
      -echo $this->formRow($form->get('title'));
      -echo $this->formRow($form->get('artist'));
      +echo $this->formHidden($form->get('ID'));
      +echo $this->formRow($form->get('TITLE'));
      +echo $this->formRow($form->get('ARTIST'));
       echo $this->formSubmit($form->get('submit'));
       echo $this->form()->closeTag();
      
      zf2-tutorial-ibmi/module/Album/view/album/album/delete.phtml
      ------------
       <h1><?php echo $this->escapeHtml($title); ?></h1>
      
       <p>Are you sure that you want to delete
      -'<?php echo $this->escapeHtml($album->title); ?>' by
      -'<?php echo $this->escapeHtml($album->artist); ?>'?
      +'<?php echo $this->escapeHtml($album->TITLE); ?>' by
      +'<?php echo $this->escapeHtml($album->ARTIST); ?>'?
       </p>
       <?php
       $url = $this->url('album', array(
                  'action' => 'delete',
      -           'id'     => $this->id,
      +           'id'     => $this->ID,
              ));
       ?>
       <form action="<?php echo $url; ?>" method="post">
           <div>
      -    <input type="hidden" name="id" value="<?php echo (int) $album->id; ?>" />
      +    <input type="hidden" name="id" value="<?php echo (int) $album->ID; ?>" />
           <input type="submit" name="del" value="Yes" />
           <input type="submit" name="del" value="No" />
           </div>
      
      zf2-tutorial-ibmi/module/Album/view/album/album/edit.phtml
      ------------
               'album',
               array(
                   'action' => 'edit',
      -            'id'     => $this->id,
      +            'id'     => $this->ID,
               )
           ));
       $form->prepare();
      
       echo $this->form()->openTag($form);
      -echo $this->formHidden($form->get('id'));
      -echo $this->formRow($form->get('title'));
      -echo $this->formRow($form->get('artist'));
      +echo $this->formHidden($form->get('ID'));
      +echo $this->formRow($form->get('TITLE'));
      +echo $this->formRow($form->get('ARTIST'));
       echo $this->formSubmit($form->get('submit'));
       echo $this->form()->closeTag();
      
      zf2-tutorial-ibmi/module/Album/view/album/album/index.phtml
      ------------
      </tr>
       <?php foreach ($albums as $album) : ?>
       <tr>
      -<td><?php echo $this->escapeHtml($album->title);?></td>
      -<td><?php echo $this->escapeHtml($album->artist);?></td>
      +<td><?php echo $this->escapeHtml($album->TITLE);?></td>
      +<td><?php echo $this->escapeHtml($album->ARTIST);?></td>
       <td>
       <a href="<?php echo $this->url('album',
      -            array('action'=>'edit', 'id' => $album->id));?>">Edit</a>
      +            array('action'=>'edit', 'id' => $album->ID));?>">Edit</a>
           <a href="<?php echo $this->url('album',
      -            array('action'=>'delete', 'id' => $album->id));?>">Delete</a>
      +            array('action'=>'delete', 'id' => $album->ID));?>">Delete</a>
           </td>
           </tr>
       <?php endforeach; ?>
      
      zf2-tutorial-ibmi/module/Album/src/Album/Model/Album.php
      ------------
       class Album
       {
      -    public $id;
      -    public $artist;
      -    public $title;
      +    public $ID;
      +    public $ARTIST;
      +    public $TITLE;
           protected $inputFilter;
      
           public function exchangeArray($data)
           {
      -        $this->id     = (!empty($data['id'])) ? $data['id'] : null;
      -        $this->artist = (!empty($data['artist'])) ? $data['artist'] : null;
      -        $this->title  = (!empty($data['title'])) ? $data['title'] : null;
      +        $this->ID     = (!empty($data['ID'])) ? $data['ID'] : null;
      +        $this->ARTIST = (!empty($data['ARTIST'])) ? $data['ARTIST'] : null;
      +        $this->TITLE  = (!empty($data['TITLE'])) ? $data['TITLE'] : null;
           }
      
           public function getArrayCopy()
      
      and
      
                   $factory     = new InputFactory();
      
                   $inputFilter->add($factory->createInput(array(
      -                        'name'     => 'id',
      +                        'name'     => 'ID',
                               'required' => true,
                               'filters'  => array(
                                   array('name' => 'Int'),
      
      and
      
                           )));
      
                   $inputFilter->add($factory->createInput(array(
      -                        'name'     => 'artist',
      +                        'name'     => 'ARTIST',
                               'required' => true,
                               'filters'  => array(
                                   array('name' => 'StripTags'),
      
      and
      
                           )));
      
                   $inputFilter->add($factory->createInput(array(
      -                        'name'     => 'title',
      +                        'name'     => 'TITLE',
                               'required' => true,
                               'filters'  => array(
                                   array('name' => 'StripTags'),
      
      zf2-tutorial-ibmi/module/Album/src/Album/Model/AlbumTable.php
      ------------
           public function getAlbum($id)
           {
               $id  = (int) $id;
      -        $rowset = $this->tableGateway->select(array('id' => $id));
      +        $rowset = $this->tableGateway->select(array('ID' => $id));
               $row = $rowset->current();
               if (!$row) {
                   throw new \Exception("Could not find row $id");
      
      and
      
           public function saveAlbum(Album $album)
           {
               $data = array(
      -            'artist' => $album->artist,
      -            'title'  => $album->title,
      +            'ARTIST' => $album->ARTIST,
      +            'TITLE'  => $album->TITLE,
               );
      
      -        $id = (int)$album->id;
      +        $id = (int)$album->ID;
               if ($id == 0) {
                   $this->tableGateway->insert($data);
               } else {
                   if ($this->getAlbum($id)) {
      -                $this->tableGateway->update($data, array('id' => $id));
      +                $this->tableGateway->update($data, array('ID' => $id));
                   } else {
                       throw new \Exception('Form id does not exist');
                   }
      
      and
      
           public function deleteAlbum($id)
           {
      -        $this->tableGateway->delete(array('id' => $id));
      +        $this->tableGateway->delete(array('ID' => $id));
           }
       }
      
      zf2-tutorial-ibmi/module/Album/src/Album/Form/AlbumForm.php
      ------------
               parent::__construct('album');
               $this->setAttribute('method', 'post');
               $this->add(array(
      -                'name' => 'id',
      +                'name' => 'ID',
                       'type' => 'Hidden',
                   ));
               $this->add(array(
      -                'name' => 'title',
      +                'name' => 'TITLE',
                       'type' => 'Text',
                       'options' => array(
                           'label' => 'Title',
                       ),
                   ));
               $this->add(array(
      -                'name' => 'artist',
      +                'name' => 'ARTIST',
                       'type' => 'Text',
                       'options' => array(
                           'label' => 'Artist',
      
      zf2-tutorial-ibmi/module/Album/src/Album/Controller/AlbumController.php
      ------------
               }
      
               return array(
      -            'id' => $id,
      +            'ID' => $id,
                   'form' => $form,
               );
           }
      
      and
      
               }
      
               return array(
      -            'id'    => $id,
      +            'ID'    => $id,
                   'album' => $this->getAlbumTable()->getAlbum($id)
               );
           }
      

Author(s)

Tony “Ranger” Cairns - IBM i PHP / PASE