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");
}

 

...