日历

« 2008-07-07  
  12345
6789101112
13141516171819
20212223242526
2728293031  

统计信息

  • 访问量: 24
  • 日志数: 2
  • 建立时间: 2008-02-25
  • 更新时间: 2008-02-25

RSS订阅

我的最新日志

  • 建立灵巧结构的PHP程序

    2008-2-25

     很早就想写这篇文章了,但一直没有时间完成它。不是说我来告诉大家如何做,我更希望本文只是做为一个引子,与大家来讨论关于如何建立一个有效地、灵活的网络应用程序英语学习网

      经过了2-3年的网络应用程序开发工作,我的开发经验变得更加生动了,回过头来看我以前为Geocrawler写的代码,简直不敢相信这是我的维拉克斯。由于GPL的原因,在PHPBuilder中的源码也是良莠不齐的。

      最近我做为一个有经验的PHP开发者,一直在帮着写SourceForge,我想这显示出了最终结果的一个范围。好的代码应被分成了多个部分,合适的库及函数调用,清楚的数据库结构,站点的每一个部分与其它部分都是相对独立的。

      但是,这仍不是最好的。如果我可以重做kvm,我将更多的关注于HTML层与数据层的分离,通过对象及清楚的函数库实现这一点。

    优美的图形

      我知道经理们喜欢用优美的图形及图表来描述它们,这将给我们留下最好的印象。用这种隐藏在一个结构后的想法,你可以把你的逻辑与外观分离,这意味着任何一个复杂的程序都可以用"API/Data Access Layer"来表述。

      与其你把安全检测、更新的句子等放在HTML层中,不如把它们整体地放在你的API层里。而这个HTML层只含有简单的函数调用和返回的数组、对象或自定的其它什么租车,以及一些数据库的检索结果的集合等。

      如果你这样做了,顶层将是非常的瘦小,你可以方便地创建及维护它。

      如下的例子中,这个HTML接口中只有一些API层中的函数的直接调用,一些HTML工具库(它能生成一个弹出框等等),和一些从数据库抽象层中调用的数据库操作方法(你不需要绑定某一个特别的数据库)。

    灵活的PHP程序结构最基本的方面有以下几点:

    数据库无关性
    界面无关性
    可移植性
    面向对象或至少应由函数库组成

    还有其它的?
    当然还有一些其它的东西,但我认为那都是太大了,或许你自己能指出它们。


    让我们详细地谈谈它们每一条吧。

    1、数据库无关性

      你从不知道你的站点将会在哪里运行,当然在你创建它时,你希望它变和得很大并且有很高的流量。所以你不想把你自己约束在 MS Access 上面或者其它什么轻便的数据库系统。虽然你不能立刻地插入各种不同的数据库系统,但是你有可能很方便地在它们中间切换。你有一些不同的选择可以把你的数据库调用抽象出来。在PHP中一个奇特的方法是你不得不为每个不同的数据库系统写出不同的代码,因为在PHP中对每一种不同的数据库的访问函数是不同的。为了避开这点,你可以使用一个抽象地数据库访问层,就象PHPLib、下一个版本的PEAR、及我们在SourceForge中描述的那样有机玻璃加工

    2、界面无关性

      一个应用程序是它的技术更重要还是它所运行的站点更重要?我们并不能真正地知道。我从来不相信这一点--HTML是一个标准。特别是对于一个网络应用程序而言,界面发生了改动,意味着我们不得不总是重写。但是如果你的应用程序是很大很复杂的,你就要为你的数据库建立一些其它的接口了,只要你不想在你的站点程序中到处copy&paste你的访问检查等代码。这也意味着,如果你正确地设计了你的应用程序,你可以很容易地改写你的站点让它适应WAP,只要简单地写一个小的WAP界面,并让它调用你的数据库访问对象而已。但若你没有很好地设计你的程序,你把你的HTML版改成WAP版是一个复杂的工程。

      我把这个想法也带入了SourceForge中车棚,我们有一个巨大的用户群,为我们发送/接收bugs、任务等。首先,我们指出所有的这些将通过我们的web页面接口,然后,由于Eric Raymond 和其他人给的压力,我们决定用XML来做数据库的外部接口。

      幸运的是我们曾在四月已把程序的核心逻辑代码与它的界面分离了。我将试着表达我们是如何做的,希望对你的工作有所帮助。

      这个SourceForge的bugs跟踪器和其它的一些工具被分成两个库 - 这个HTML库和数据访问库。这个数据访问库检查输入的值的正确性,处理安全校验,并且当成功/失败时返回TRUE 或 FALSE。

      由于简化的原因,这个例子并没有基于一个完善的对象模式,那样我还要解释这个基类和它的一些衍生类等等,我想这个例子将给你一个最普通的想法。
    HTML 库的例子


    //connect to database
    require ("database.php");

    //common utils like header/footer HTML
    require ("html.php");

    //data access library
    require ("bug_data.php");

    echo site_header("Page Title");

    echo "

    Updating A Bug


     

    ";

    if (bug_data_update($field1,$field2,$field3)) {

    echo "

    Update Failed!

    ";

    } else {

    echo "

    Updated Bug Successfully

    ";
    //echo the global error string
    echo $feedback;
    }

    echo site_footer();

    ?>


    Data 访问库的例子

    /**
    *
    * controls access to updating a bug in the
    * database. Validates data and checks security
    * Returns true on success, false on failure
    *
    */

    function bug_data_update ($field1,$field2,$field3) {
    //global string to report back errors
    global $feedback;

    //$field1 and $field2 are required
    if (!$field1 || !$field2) {
    $feedback="Field 1 And Field 2 Are Required";
    return false;
    }

    //make sure this user has permission to update
    if (!user_isadmin()) {
    $feedback="You Must Be An Admin To Update a Bug";
    return false;
    }

    //now let's update the bug

    $result=db_query("UPDATE bug ".
    "SET field2='$field2',".
    "field3='$field3' ".
    "WHERE id='$field1'");

    //now check your query for success/failure
    if (!$result) {
    //update failed
    return false;
    } else {
    return true;
    }
    }

    ?>


    3、可移植性

      毫无疑问,你不想让你的代码只能用于一个固定的站点,将来我们可能改变色彩的选择、元素的名称、字体或其它一些什么,这样应设置一个config文件,它被多个页面所包含。更好的观点是你的站点被模块化,你不需要copy&paste任何一个HTML文件,我倾向于把这些放入一个函数,在任何需要的地方调用它们车棚

      同样的方法可用于数据库的密码、数据库连接字串等,这些可以放入一个数据库处理的抽象层中。


    4、面向对象/函数化

      我们不是用COBOL开发,所以这意味着我们可以把进程分成多个函数的调用。每个调用都是一个自动的行为,有时仅仅是调用一小段其它的函数并返回这个结果。 安装卫星电视

      一个好的例子是在每一个页面校验用户是否登录,你可以用cookie或查询数据库来完成这个功能,但一旦你想改变你的验证系统,你不得不改动每一个页面,其实你应该可以通过改动函数库里一个普通的函数就完成这个变动的。任何时候,你写一段代码,如果它将会被用于多于一个地方,你就要考虑把它放入一个库里了。

  • 用PHP和SQL Sever实现分页显示

    2008-2-25

    我们在浏览网页时,经常看到分页显示的页面。如果想把大量数据提供给浏览者,分页显示是个非常实用的方法。在下面的文章中,我们将介绍如何用PHP和MS SQL Server实现对数据库中纪录的分页显示。

        在本例中,我们用mssql_num_rows()函数得到当前查询的记录数,结合页面大小SgPageSize,得到当前记录集要显示的页面数,为分页显示打下了基础。mssql_data_seek()函数是分页显示的关键函数,该函数的第二个参数标示当前纪录的偏移量,根据这个偏移量就可以找到要显示的页面。


      分页显示源程序:


    <br><html>

    <head>

    <title>PHP分页</title>

    </head>

    <body>

    <?

    //为了便于理解和更快地应用到工作中去,我们以MS SQL Server的NorthWind数据库Customers表为例。

    $gPageSize= 10; //每页显示的记录数

    $hostname = "localhost"; //MSSQL Server

    $dbuser = "sa"; //用户名

    $dbpasswd = "1111111"; //密码

    //连接数据库

    $id = mssql_connect($hostname,$dbuser,$dbpasswd) or die("无法连接数据库服务器!");

    //选择数据库,为了方便,这里以MSSQL Server的NorthWind数据库为例

    $db = mssql_select_db("northwind",$id) or die("无法连接数据库!");

    //以Customers表为例,构建查询字符串

    $query = "select * from Customers";

    //执行查询语句

    $rresult = mssql_query($query) or die("无法执行SQL:$query");

    //$page变量标示当前显示的页

    if(!isset($page)) $page=1;

    if($page==0) $page=1;

    //得到当前查询到的纪录数 $nNumRows

    if(($nNumRows= mssql_num_rows($rresult))<=0)

    {

    echo "<p align=center>没有纪录";

    exit;

    };

    //得到最大页码数MaxPage

    $MaxPage = (int)ceil($nNumRows/$gPageSize);

    if((int)$page > $MaxPage)

    $page=$maxPage;

    ?>

    <table align="center" width="80%" border=0> <tr><td><? echo "<font size=2>第
    $page 页,共 $MaxPage 页</font>";?></td><td></td></tr></table>

    <table align="center" width="80%" border="1" cellspacing="0" cellpadding="4" bordercolorlight="#CC9966" bgcolor="#00F2EE" bordercolordark="#FFFFFF" class="LZH">

    <tr bgcolor="#F7F2ff" style="font-size:14.8px;font-weight:bold">

    <?

    //显示表格头

    for($iCnt = 0; $iCnt < mssql_num_fields($rresult); $iCnt++)

    {

    echo "<td>".mssql_field_name($rresult,$iCnt)."</td>" ;

    }

    ?>

    </tr>

    <?

    //根据偏移量($page - 1)*$gPageSize,运用mssql_data_seek函数得到要显示的页面

    if( mssql_data_seek($rresult,($page-1)*$gPageSize) )

    {

    $i=0;

    //循环显示当前纪录集

    for($i;$i<$gPageSize;$i++)

    {

    echo "<tr style=\"font-size:12px\">";

    //得到当前纪录,填充到数组$arr;

    $arr= mssql_fetch_row($rresult);

    if($arr)

    {

    //循环显示当前纪录的所有字段值

    for($nOffSet = 0;$nOffSet < count($arr);$nOffSet++)

    {

    echo "<td>".$arr[$nOffSet]."</td>";

    }

    }

    echo "</tr>";

    }

    }

    ?>

    </table>

    <br>

    <hr size=1 width=80%>

    <div align=center style="font-size:12px">

    <?

    //首页和上一页的链接

    if( $nNumRows>1 && $page>1)

    {

    $prevPage=$page-1;

    echo " <a href=$PHP_SELF?page=1>首页</a> ";

    echo " <a href=$PHP_SELF?page=$prevPage >上一页</a> ";

    }

    //下一页和末页的链接

    if( $page>=1 && $page<$MaxPage)

    {

    $nextPage= $page+1;

    echo " <a href=$PHP_SELF?page=$nextPage >下一页</a> ";

    echo " <a href=$PHP_SELF?page=$MaxPage >末页</a> ";

    }

    ?>

    </div>

    </body>

    </html>


Open Toolbar