94hwan-PHP框架基本原理

Source:94hwan 与众不同  Author:网络部
2010-06-17 11:05

 1、概述  2、基本數據庫操作類(cls_lurd)  2、全自動操作類(cls_lurd_control)
1、概述  

  Lurd類實際是對數據庫操作的search(list/query)、insert、update、delete操作的簡化處理,與常規的CURD類比,這個類去除了沒必要的create功能(因爲實際開發工程中,每個數據表都應該是預先規劃的,直接用數據庫類去創建數據表是不明智的),與常規的高級db類對比,增加了一個預先對數據表結構的分析的功能,如果說效率方面的影響,這裏會有輕微的影響,但是它是犧牲極小的性能開支來提升開發效率和安全性,特別是在自動操作類中,只需簡單的十幾行代碼就能完成普通數據操作的所有功能(包括自動生成模板),此外,由于在操作數據前,對字段的值進行了嚴格的檢驗,因此也大大提高了安全性。
本著簡便的原則,這個類沒有有查詢條件方式使用更複雜的組合,而是除了使用固定的查詢模式外,允許用戶用戶手工指定查詢條件,而系統會對這條件進行前置分析(尚未完全實現),這樣會更利于開發者習慣。
爲了使開發更規範,本數據庫類並不會直接操作數據庫,最終的操作仍然是通過cls_database類進行操作的,以便于在更底層應用中達到統一。

2、基本數據庫操作類  

  基本执行流程为: lurd::factory($tablename) 初始化,初始化后系统会调用 analyse_table() 分析表结构,如果不用factory方法初始化,那么初始化后应该调用 set_table( $tablename ) 指定表,如果是比较简单的情况,如:单纯进行更新、插入、删除等操作,也可以不初始化,直接调用相关方法。
lurd類只能對同時對單個表進行更新、插入、刪除操作,但可以聯合多個表進行查詢,常用的方法如下:

(1) 插入記錄
$lurd_obj->insert($key_value_array, $tablename='');
$key_value_array 是字段值的键值对,对于自动递增类型,可以不指定主键的值,否则如果出现重复值,会出错,程序的处理方式是:除了这个数组不能为空之外,不管你指定多个字段,它都能成功插入数据,系统会自动补充不存在的字段值,因此,在一些安全要求比较严格的地方,不允许直接把POST或GET传递过来的数据直接作为$key_value_array,除非你预先对可能会对权限、级别等造成影响的字段先行处理,update操作时类同。
$tablename 是表名称,如果初始化时已经指定,可不必管这个参数。
例:
cls_request::$forms['userpwd'] = md5(cls_request::$forms['userpwd']);
cls_request::$forms['rank'] = 0;
cls_request::$forms['sta'] = 1;
$lurd_obj->insert(cls_request::$forms, 'users');
lurd類裏對字段的值進行了足夠嚴格的安全檢查,因此你是不必要在前端檢查數據合法性的,只需檢查那些必填或需特殊控制即可。

$lurd_obj->insert_id();

获取上次插入記錄的id。

(2) 更新記錄
$lurd_obj->update( $key_value_array, $condition='', $tablename='' );
$key_value_array 是字段值的键值对
$condition 是更新条件(实际就是 sql 的 where 后面的部份),程序里对查询条件过滤的语法不完善,需要在前台注册这查询条件的安全性。
$tablename 是表名称,如果初始化时已经指定,可不必管这个参数。

(3) 限制插入記錄和更新記錄的键值对
$lurd_obj->set_lock_fields( $fieldstr );
$fieldstr 键列表(字段名列表),用','分开,这样限定insert或update时 $key_value_array 只使用 $fieldstr指定的键名,这样可以防止用户恶意提交并不需要更新的字段。

(4) 刪除記錄
$lurd_obj->delete( $primarykey_values, $tablename='' );
$primarykey_values 为主键数组
刪除指定主鍵的多個記錄
$lurd_obj->delete_one( $condition='', $tablename='' );
$condition 即是sql where 后面的部份
刪除指定查詢條件的記錄

(5) 查詢數據
(在查询中需要指定 condition 的,这个condition必须带 where ,如 where user_id='abc',但在update和delete_one的condition是不须要带where的[因为查询里的条件是可选的,更新时则是必须的,因此前者查询时要带where,更新时会在condition前强制加上where因此不必带])
$lurd_obj->join_table($tablename, $mylinkid, $linkid, $linkfields='*');
$tablename  要联结的表名(根据SQL查询标准不允许联结当前表)
$mylinkid 要聯結的表使用的連結字段名
$linkid  当前表联结字段名
$linkfields 要联结的表查询后需要列出的字段

$lurd_obj->get_one( $condition='', $tablename='', $listfield = '*')
獲取單個記錄

$lurd_obj->add_search_parameter($fieldname, $fieldvalue, $condition, $linkmode='and')
添加查詢條件(只能全都是and或全都是or模式,由于這個並不是很完善,所以建議手寫condition)
$fieldvalue 传入的 value 值必须先经过转义
$condition 条件 >、<、=、<> 、like、%like%、%like、like%
$linkmode and 或 or

$lurd_obj->get_datas2( $start = 0, $listfield = '*', $orderquery ='', $condition='', $tablename='' )
查詢數據,返回的数据为:array('data'=>数据array, 'total_result'=>符合查询条件的记录总数, 'total_page'=>总页数, 'page_no'=>当前页)

string $lurd_obj->get_pagination( $url = '', $style = "94hwan-page" );
執行查詢後可以用這個方法獲得分頁符列表。
$url: 注意使用的分页参数是start,而不是当前页码page。如果为空,则会默认为当前url,并过滤多余的start参数。
$style: 分页样式

$lurd_obj->get_pagination_datas($start = 0, $url='?', $listfield = '*', $orderquery ='', $condition='', $tablename='')
查詢數據,并同时得到分页符列表(相当于 $lurd_obj->get_datas2$lurd_obj->get_pagination 的簡化操作)
返回的数据为:array('data'=>数据array, 'pagination'=>分页符HTML串, 'total_result'=>符合查询条件的记录总数, 'total_page'=>总页数, 'page_no'=>当前页)
 

3、全自動操作類  

  Lurd全自動操作類(cls_lurd_control),實際上是對Lurd類的進一步封裝,對于簡單的數據庫操作,它實現了對指定的數據表列出、查詢、增加數據、修改數據、刪除數據等基本功能,而且這一切都是自動操作的,它會對每步操作生成相應的模板,而不需要用戶自己去單獨制作每一個模型的模板。
在cls_lurd_control的工厂创建方法是:cls_lurd_control::factory($tablename, $form_url='?ct--lurd/', $template_path='', $always_make=false),参数分别为:表名、控制器网址、模板路径、是否一直生成模板(通常是测试的情况才会使用这选项,因为大多数情况用户还是会对生成的模板进行人性化改动的,因为不能开启一直生成的选项)。
初始化对象实例之后,可以进一步对相关参数进行处理,最后用 $lurd_ctl_obj->listen($request_array); 把操作控制权交给类去处理。
由于考虑安全原因,大多数据情况,我们是不可能直接把 $request_array 交给模型类的,所以一般需要在 listen 前进行一些处理,常见的操作如下:
1、对事件进行截获,以便对相应操作进行一些预先处理,这个类的事件变量是: even(由request传递),默认值为: list(即是列出数据),其它值有:'add'(显示增加数据的表单),'saveadd'(保存增加的数据),'edit'(显示修改数据的表单),'saveedit'(保存修改的数据),'delete'(删除数据)
我们在必要时,可以通过 $even = cls::request.item('even', 'list') 这种方式对提交过了的even进行截获,然后对request的数据进行一些必要的预处理才交由cls_lurd_control处理。
2、指定生成的模板名,在没指定的情况下,默认生成的模板名为:lurd.tablename.even.tpl ,为了使模板名与实际开发工程的规则保持一致,这里允许用户自己进行指定,操作方法为:$lurd_ctl_obj->set_tplfiles($list='', $add='', $edit='') 。
3、指定查询条件:$lurd_ctl_obj->set_list_config($listfield='*', $orderquery='', $wherequery='', $searchfield='*')
4、手动指定某些字段的属性,因为mysql中,很多用习惯用int表示时间戳的,所以有必要,需要手工把这字段指定为自己想要的类型,以保证生成模板时按你想要的意愿。这里利用到的函数是lurd基类的bind_type($fieldname, $ftype, $format='')方法,如:$lurd_obj->bind_type('pubdate', 'TIMESTAMP'')。
最後舉一下例子說明具體的應用:
以下源碼就是後台短消息管理的源碼,簡單三十多行代碼卻完成了列出所有信息、按關鍵字查詢、增加信息、刪除、修改信息等所有操作,這就是這個類的強大之處。

 

  1. /** 
  2.  * 消息管理(由lurd托管) 
  3.  */ 
  4.  public function index() 
  5.  { 
  6.      global $config
  7.      cls_template::assign('msg_types'$config['msg_types'] ); 
  8.      //攔截特定事件 
  9.      $even = cls_request::item('even'''); 
  10.      //攔截保存信息的事件,使用通用的調接口 
  11.      if$even=='saveadd' ) 
  12.      { 
  13.          if( cls_request::item('title''')=='' ) 
  14.          { 
  15.              cls_access::show_message ('系統提示''請填寫信息標題!''-1'); 
  16.              exit(); 
  17.          } 
  18.          if( cls_request::item('uid', 0)==0 &amp;&amp; cls_request::item('is_public', 0)==0 ) 
  19.          { 
  20.              cls_access::show_message ('系統提示''私人信息必須指定數字的用戶id!''-1'); 
  21.              exit(); 
  22.          } 
  23.          cls_message::send_message( stripslashes(cls_request::item('uid', 0)), 
    stripslashes(cls_request::item('title''')), 
    stripslashes(cls_request::item('msg''')), 
    stripslashes(cls_request::item('is_public', 0)), 
    stripslashes(cls_request::item('sender','')) );
  24.          cls_access::show_message ('系統提示''成功發送一條消息!'''); 
  25.          exit();                           
  26.      } 
  27.      //攔截刪除消息事件(刪除消息同時刪除閱讀記錄) 
  28.      if$even=='delete' ) 
  29.      { 
  30.          if( cls_request::item('id''')=='' ) 
  31.          { 
  32.              cls_access::show_message ('系統提示''請選擇要刪除的消息!''-1'); 
  33.              exit(); 
  34.          } 
  35.          $ids = join(',', cls_request::item('id''')); 
  36.          cls_database::query(" Delete From `message_sta` where id in($ids) ", true); 
  37.      } 
  38.      //轉由Lurd控制 
  39.      $tb = cls_lurd_control::factory('message'); 
  40.      $tb->list_config['orderquery'] = " order by id desc "; 
  41.      $tb->form_url = '?ct--message/'
  42.      $tb->set_tplfiles('message.index.tpl''message.add.tpl''message.edit.tpl'); 
  43.      $tb->listen(cls_request::$forms); 
  44.  } 

 5、自定操作

 在实际使用中,我们会遇到几种问题:(1) 可能删除某个东西的同时,会删除它关连的其它表的内容;(2) 某个操作完成后,我需要自行指定它的后续操作。这些情况使用下面的两个参数:$tb->end_need_done = false; 默认的情况下,所有操作完全由lurd类完成,这种模式下,通常会直接在lurd类操作完之后 exit(); ,如果你想自行进行后续操作,应该把它设置为 true,这样可以在 $tb->listen 后进行其它操作。

$tb->end_display   这个仅操作lurd类里是否使用display方法。

(3) 需要自行指定内容列出条件

通常的做法是把 form_url 变量和 add_search_condition 方法相结合,如:

$tb->form_url = '?ct--member/';
if( !empty($notcheck) ) {
    $tb->form_url .= "&notcheck={$notcheck}";
    $tb->add_search_condition(" (`sta` = 0 Or `sta` = -1) ", "and");
}

 

...