看澳洲眼科医生玩转ZendFramework和AJAX

上一篇 / 下一篇  2007-09-30 10:16:13 / 个人分类:ZendFramework

原文出处:http://www.vernona.com/ZTUTE/menus/menus/menus

(本文中所有源代码在上述链接均有下载)

这位仁兄写的软件不是很专业,但他的作品在他的诊所得到了实际应用,解放了他的秘书。我觉得有三点值得回味:

1. 忙碌的眼科医生竟然是个PHP爱好者,也可以看出象PHPer第六期上介绍的PHPOpenbiz在年轻西方白领阶层中会很有前途;

2. ZF很好用;

3. 如果向他推荐使用我们国内优秀的框架象THINKPHP或FLEAPHP他会不会觉得更爽(因为开发更快捷,会有更多的时间多看两个病人

A ZEND FRAMEWORK DEMONSTRATION

 


These are brief notes on the CRUD and Ajax demo using the Zend Framework.


The original demo was setup on 31.3.06 using the preview release 0.1.2 . However, as stated earlier I was anxious to move the demonstration to a subdirectory. This is now achievable using release 0.1.5 where the excellent RewriteRouter of Martel has been incorporated into the core library. This new demonstration is now set up in a subdir named 'MARTEL'  and a further subdir named 'subdirMARTEL' within 'MARTEL'. A few changes have been made to the index.php file to use the new RewriteRouter. The actual library used in this current demo is from the trunk cvs release of 23.7.06. I have not tested it with 0.1.5. The current cvs releases should be totally compatible. ( the changes in green  throughout this document have been made for this current demonstration )

 

 

The tutorial has been reworked, 12/8/2007, using the conventional modular directory structure of ZF and using the ZF 1.0.1 library. The original post_codes demo is still available athttp://www.vernona.com/zend/docv8menu.php.

This is meant to demonstrate the ease of using the framework. I am not a programmer but a busy eye doctor from Wollongong , near Sydney, Australia. I am a programming dummy who dabbles a little in web design. So you too can do the same!

The ease of using CRUD in the framework would be nothing new to programmers. However, this is meant to show simple users such as myself how it can be done.

You could setup CRUD for any table using the source of this tuturial and substituting your own site details and database.

By far the biggest feature is the use of AJAX within the framework to multi-edit the index or listing of the memos used here for the demonstration. I dreamt this up from scratch because I needed such a feature for updating eye doctor fees (in a fees table) which change every year according to the Australian Government regulations. To edit each row individually, as is usually done with CRUD, would take my secretary too long and while updating each row  is without penalty on a local intranet over the phone lines it would be time penalized big time! Now she simply changes each field in the whole form and updates it in one bang.  This was my solution. The code is all pure.

The essence  is mainly the js in the file MemosMultiedit.php. The js function is called AIC(me).

//Add ID To idchanged
function AIC(me){
me.style.background = "#0AFF00"; //background-color to green to let user know must use ajax
var melength=me.name.length; // had to use length bec autoid can get larger than just 1 ,2,3,4, or 5 digits.
var id=(me.name.substr(3,melength)); // will always be 3(f00) then autoid digits.
if (id){
var str=document.getElementById("idchanged").value; // if not sure how works then unhide the field on the form
if (str==""){
document.getElementById("idchanged").value=str + id;}else{
if (!str.match(id)){
document.getElementById("idchanged").value=str + ","  + id;
}}
// this added for ajax
//var c=me.name;
if (pars==""){
pars=me.name + "=" + me.value;
}else{
pars=pars+"&"+me.name+"="+me.value;
}}
}

Each time a change is made to a field this function is called. It adds the id of the row changed to a hidden input text field called 'idchanged'.

Of course one must have a unique name and id for each field in the table. The unique name is needed for the ajax call (using prototype.js) .


The unique id is also needed for the js function AIC(me) discussed above.

This "uniqueness"  is accomplished by the following html/php spaghetti code from the list view (MemosMultiEdit.phtml):

<TD>
<input type="text" style="width:20px;"name="fid<?echo$val['id']?>"value="<?echo$val['id']?>"readonly></TD>
<TD>
<input style="width:70px;"class="boldblue"name="f02<?echo$val['id']?>"value="<?echo$val['f02']?>"
onchange="AIC(this)"></TD>
<TD>
<textarea rows="3" cols="93"class="boldblue"style="font:arial;"name="f03<?echo$val['id']?>"WRAP="virtual" ōnchange="AIC(this)" ōnclick="SetActiveID(this,this.form)"onFocus="SetActiveID(this,this.form)"><?echo$val['f03']?></textarea>
</TD>
<TD>Action
<input style="width:85px;"name="f04<?echo$val['id']?>"value="<?echo$val['f04']?>"
onchange="AIC(this)"></TD>


The unique name is achieved for the id field using: name="fid<?echo$val['id']?>". Note the 'fid' at the beginning. This will mean that the first id field will be called fid1 and the second will be called fid2 etc. A similar result is achieved for the f02(date) field by using: name="f02<?echo$val['id']?>"  and for the f03(memo) field using: name="f03<?echo$val['id']?>". You may note that there is no space used between input parameters. This was deliberately done because with a large form each space adds to the download volume. The unique ids are achieved using almost identical html/php code as listed above. 

When ajax is called it uses the updateajaxAction() in the MemosController.php to explode 'idchanged' into an array. It then iterates through the array to pull the field changes from the $_POST and save these rows into the memos table. Having done this asynchronously you are returned to the original page.

Here is the listing of the /postcodes/updateajaxAction()action found in MemosController.php:

    function updateajaxAction()
    {
// turn of  rendering when using ajax
    $this->_helper->viewRenderer->setNoRender();

    unset($_REQUEST['_']);
    $table = new $this->generictable();
    $idchanged=( $_POST['idchanged']);   
    $changedarray=explode(",",$idchanged);
    // Go around for each idchanged. On each iteration the $table is updated
        if ($_REQUEST['idchanged']){
            foreach ($changedarray as $key => $value)
            {
            $idvariable=null;
            $idvariable="changes".$value;
            ${$idvariable}=array();
            $id="fid".$value;

        //IF DATE NEEDED IN GENERIC TABLES f02 is the field name used
        $f02="f02".$value;
                if(isset($_POST[$f02])){
                    list($xday, $xmonth, $xyear) = explode("/", $_POST[$f02]);
         // make sure that date uses double digits
                    if (strlen($xday)==1)$xday="0".$xday;if (strlen($xmonth)==1)$xmonth="0".$xmonth;
          // reassemble date from British day/mon/year to MySql ISO format
                    $date = $xyear."-".$xmonth."-".$xday;                   
                    ${$idvariable}['f02']=$date;}

            $f03="f03".$value;
            if(isset($_POST[$f03])){${$idvariable}['f03']=$_POST[$f03];}
            $f04="f04".$value;       
            if(isset($_POST[$f04])){${$idvariable}['f04']=$_POST[$f04];}      

            ### etc for more fields       
            $where = $table->getAdapter()->quoteInto("id= ?", $value);
            $rows_affected =$table->update($$idvariable, $where);
            }
        }   
    }
   

The other fairly interesting feature of the demonstration is the pagination. This is simply achieved by the hyperlinks at the top of the main listing page 'MemosMultiedit.phtml'.
The other interesting problem with pagination is how to achieve a return to the same page that was listed after a delete of a record is done. This was achieved by the code
<td ALIGN='left' width='5%'><a href='http://<?php echo $_SERVER['HTTP_HOST']. REWRITEBASE .'/'.$this->module.'/'.$this->controller?>/delete/id/<?echo $this->escape($val['id'])?>/page/<?echo $this->page?>'> Del </A></td>
 which passes the page number on the end of the other parameters called by the delete.


Which translates into the url  /memos/memos/delete/id/91/page/6 which breaks down to memos(the module), memos(the controller),delete(the action in the controller),id/91(the id and its value pair) and finally page/6 ( the page and its value pair). The memos controller uses its deleteAction to obtain the page and its value from the url using the following code:

 $paramsurl=$this->_getAllParams();
 $page=$paramsurl['page'];
The redirector is used to return to the same page:


$this->_redirector->goto('list', 'memos','memos', array('page' => $page));  
It seems round-about; but,  it works without much overhead and also without pagination black-boxes. Morever, you can always see where you are exactly by looking at the URI in your address bar.

 

 

SETTING UP YOUR OWN SITE

Setup your .htaccess file in the way recommended by Chris Shiflett in his excellent tutorial published in the php architect magazine.
The .htaccess code that I use is:
 RewriteEngine on
 RewriteRule !\.(js|ico|gif|jpg|png|css|php|html|txt|src|htm)$ index.php


The directory structure that I have used is:

-webroot
        /ztute


index.php

.htaccess (for enabling  mod rewrite and enabling certain files to pass without redirection eg html)

library/( the Zend Framework library 1.0.1)
scrīpts/ prototype.js (for ajax; download from their site
http://prototype.conio.net/)
images/
application/


modules/

                                                       default/
                                                                   controllers/
                                                                            indexcontroller.php
                                                                   views/
                                                                            scrīpts/
                                                                                    index.phtml
                                                       menus/
                                                                 controllers/
                                                                                 menuscontroller.php
                                                                  views/
                                                                           scrīpts/
                                                                                    menus/
                                                                                                menus.phtml
                                                       memos/
                                                                 controllers/
                                                                                  memoscontroller.php
                                                                  views/
                                                                            scrīpts/
                                                                                        memos/
                                                                                                    memosmultiedit.phtml
                                                                  

 

CONVENTIONAL MODULAR DIRECTORY STRUCTURE


The optional folders are marked (of course modules are all optional anyway):

application/

    modules/

        default/


            controllers/

                    IndexController.php

            models/ (optional)

            views/

        scrīpts/

                index/

                        index.phtml

        helpers/ (optional)

        filters/ (optional)

 


// THE NEXT MODULES ARE ALL OPTIONAL BUT CAN // BE ADDED AD INFINITUM

        modulename1/

                controllers/

                    ControllernameController.php

                models/ (optional)

                views/

                scrīpts/

                            Controllername/

                                        actionname.phtml

                helpers/ (optional)

                filters/ (optional)

 

html/

.htaccess

index.php

 

To make all this work all one needs to do is add the following line to the bootstrap(index.php):


$front->addModuleDirectory('application/modules');

 


To see the demonstration of the memos demo point your browser tohttp://vernona.com/ztute/menus/menus/menusor go to the home page of the demohttp://www.vernona.com/ztute.


The MySql database Sql create for the memos table is as follows:

 

memos   CREATE TABLE `memos` (                                                                                                                                                                                         
          `id` int(11) NOT NULL,                                                                                                                                                                                       
          `f02` date default NULL,                                                                                                                                                                                     
          `f03` mediumtext,                                                                                                                                                                                            
          `f04` varchar(255) default NULL,                                                                                                                                                                             
          PRIMARY KEY  (`id`)                                                                                                                                                                                          
        ) ENGINE=MyISAM DEFAULT CHARSET=latin1
The table(s) can be placed in any database but in this code it is named 'vernonac_zftest' with a user name of 'vernonac_demo' and a password of 'demo'. You could replicate this using PhpMyAdmin, SqlYog or equivalent if you did not wish to change any code at all.

 


The source files can be downloaded from the site by using the menu to download each one that you need. You will need to change the file type from 'src' to php on most so that you can view them in your favourite editor. I have not found it possible to provide a directory download because of the need of placing the .htaccess rewrite file in the root of the site. It is said that this constraint will be removed from the Zend Framework in time.

Once you have the source files place them into the directory structure outlined above. Change the table name and field names in your SQL create to what you want. There should be no trouble adding more fields to your table. You will then have to add to or change these names in the code. If you add more tables in the database you will have to add a controller for each and of course the corresponding views. However, by using cut and paste this is not a very difficult job. Scaffolding could do some of this automatically; but, again another black-box.

The source files are only partially commented because of my lack of time. However, for a programmer they should be fairly obvious. They are not formatted according to strict ZF recommendations; again, using the lack of time as the excuse (mea culpa).
The new source files are being uploaded shortly and should be available from the same home page demo.


This is not meant to be a real tutorial; but, rather could be described as notes on the demonstration provided. With time I hope to add to these notes and make them more explicit and clearer.

This demonstraion will not be available for too long as I need the website which is wholly taken over by the .htaccess rewrite necessity. Once, the directory structure of ZF is finalized one's webroot will be freed up by subdirectory hosting of a demonstration such as this.


The demo has been moved to a subdirectory as discussed earlier...see green print for changes.


If programmers ask me cryptic questions in all probability I won't be able to answer them . I am appalled at my lack of knowledge, so severely exposed when reading the ZF mailing list archives.

I will try to look at comments sent to postmaster@vernona.com

My domain name vernona.com is hosted on NEXCESS.NET Web Hosting.

NEXCESS.NET Internet Solutionshttp://nexcess.net304 1/2 S. State St.Ann Arbor, MI 48104-2445info@nexcess.net
They provide PHP 5.1.2 / MySQL 4.1.x with PDO and pdo_mysql among many other options. If you go tohttp://vernona.com/phpinfo.phpyou can see that they are running on a linux server. This is important because I set my demonstraion up on a windows box and was too loose with the case of file names. They are case sensitive in linux.

 

 

Dr Allan Vernon MBBS(Syd),FRANZCO

 

 


TAG: PHP ajax Ajax zendFramework zf ZF tutorial ZendFramework

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

数据统计

  • 访问量: 18030
  • 日志数: 87
  • 建立时间: 2007-09-29
  • 更新时间: 2008-04-15

RSS订阅

Open Toolbar