php设计模式之数据对象映射模式

  所谓的数据对象映射模式,就是用对象与数据库中的字段一一对应,这样操作对象就可以操作数据实体。也就是我们常用的ORM。下面我来展示一个建议的php的ORM,主要参考了一些TP框架的思路,很简易。还有好多东西待完善,给那些想研究ORM的同学提供一些思路吧。 

  1 <?php
  2 /**
  3  * author: NickBai
  4  * createTime: 2016/11/28 0028 下午 4:00
  5  */
  6 class MyOrm implements ArrayAccess
  7 {
  8     public $host = '127.0.0.1';  //数据库地址
  9     public $dbname = 'test';   //数据库名
 10     public $user = 'root';  //数据库用户名
 11     public $pwd = 'root';   //数据库密码
 12     public $port = '3306';  //数据库端口
 13     public $charset = 'utf8';   //数据库编码
 14     private $conn = null;    //数据库链接资源
 15     private $alias = [];  //记录全局的语句参数
 16     private $sql;    //存储最后一条sql
 17 
 18     public function __construct()
 19     {
 20         if( is_null( $this->conn ) ){
 21 
 22             $dsn = "mysql:host=$this->host;dbname=$this->dbname;charset=$this->charset;port=$this->port";
 23             $this->conn = new PDO( $dsn, $this->user, $this->pwd );
 24         }
 25     }
 26 
 27     //field语句
 28     public function field( $field )
 29     {
 30         if( !is_string( $field ) ){
 31             throw new exception("field语句的参数必须为字符串");
 32         }
 33 
 34         $this->alias['field'] = $field;
 35         return $this;
 36     }
 37 
 38     //table语句
 39     public function table( $table )
 40     {
 41         if( !is_string( $table ) ){
 42             throw new exception("table语句的参数必须为字符串");
 43         }
 44 
 45         $this->alias['table'] = $table;
 46         return $this;
 47     }
 48 
 49     //where语句
 50     public function where( $where )
 51     {
 52         $this->alias['where'] = '';
 53         if( is_array( $where ) ){
 54 
 55             foreach( $where as $key=>$vo ){
 56                 $this->alias['where'] .= " `$key`" . ' = ' . $vo . ' and ';
 57             }
 58             $this->alias['where'] = rtrim( $this->alias['where'], 'and ' );
 59 
 60         }else if( is_string( $where ) ){
 61 
 62             $this->alias['where'] = $where;
 63         }else{
 64 
 65             throw new exception("where语句的参数必须为数组或字符串");
 66         }
 67 
 68         return $this;
 69     }
 70 
 71     //limit语句
 72     public function limit( $limit )
 73     {
 74         $this->alias['limit'] = '';
 75         if( is_numeric( $limit ) ){
 76            $this->alias['limit'] = '0,' . $limit;
 77         }else if( is_string( $limit ) ){
 78             $this->alias['limit'] = $limit;
 79         }else{
 80             throw new exception("limit语句的参数必须为数字或字符串");
 81         }
 82 
 83         return $this;
 84     }
 85 
 86     //order语句
 87     public function order( $order )
 88     {
 89         if( !is_string( $order ) ){
 90             throw new exception("order语句的参数必须为字符串");
 91         }
 92 
 93         $this->alias['order'] = $order;
 94         return $this;
 95     }
 96 
 97     //group语句
 98     public function group( $group )
 99     {
100         if( !is_string( $group ) ){
101             throw new exception("group语句的参数必须为字符串");
102         }
103 
104         $this->alias['group'] = $group;
105         return $this;
106     }
107 
108     //解析查询sql语句
109     public function ParseSelectSql()
110     {
111         $this->sql = 'select *';
112         if( !empty( $this->alias['field'] ) ){
113             $this->sql = str_replace( '*', $this->alias['field'], $this->sql );
114         }
115 
116         if( empty( $this->alias['table'] ) ){
117             throw new exception("请用table子句设置查询表");
118         }else{
119 
120             $this->sql .= ' from ' . $this->alias['table'];
121         }
122 
123         if( !empty( $this->alias['where'] ) ){
124             $this->sql .= ' where ' . $this->alias['where'];
125         }
126 
127         if( !empty( $this->alias['group'] ) ){
128             $this->sql .= ' group by ' . $this->alias['group'];
129         }
130 
131         if( !empty( $this->alias['order'] ) ){
132             $this->sql .= ' order by ' . $this->alias['order'];
133         }
134 
135         if( !empty( $this->alias['limit'] ) ){
136             $this->sql .= ' limit ' . $this->alias['limit'];
137         }
138 
139     }
140 
141     //解析添加sql语句
142     public function ParseAddSql()
143     {
144         $this->sql = 'insert into ';
145         if( empty( $this->alias['table'] ) ){
146             throw new exception("请用table子句设置添加表");
147         }else{
148 
149             $this->sql .= $this->alias['table'] . ' set ';
150         }
151 
152         return $this->sql;
153     }
154 
155     //解析更新sql语句
156     public function ParseUpdateSql()
157     {
158         $this->sql = 'update ';
159         if( empty( $this->alias['table'] ) ){
160             throw new exception("请用table子句设置修改表");
161         }else{
162 
163             $this->sql .= $this->alias['table'] . ' set ';
164         }
165 
166         if( empty( $this->alias['where'] ) ){
167             throw new exception("更新语句必须有where子句指定条件");
168         }
169 
170         return $this->sql;
171     }
172 
173     //解析删除sql语句
174     public function ParseDeleteSql()
175     {
176         $this->sql = 'delete from ';
177         if( empty( $this->alias['table'] ) ){
178             throw new exception("请用table子句设置删除表");
179         }else{
180 
181             $this->sql .= $this->alias['table'];
182         }
183 
184         if( empty( $this->alias['where'] ) ){
185             throw new exception("删除语句必须有where子句指定条件");
186         }
187 
188         $this->sql .= ' where ' . $this->alias['where'];
189 
190         return $this->sql;
191     }
192 
193 
194     //查询语句
195     public function select()
196     {
197         $this->ParseSelectSql();
198         $row = $this->conn->query( $this->sql )->fetchAll( PDO::FETCH_ASSOC );
199         $result = [];
200 
201         foreach( $row as $key=>$vo ){
202 
203             $arrObj = clone $this;  //clone当前对象防止对this对象造成污染
204             $arrObj->data = $vo;
205             $result[$key] = $arrObj;
206             unset( $arrObj );
207         }
208 
209         return $result;
210     }
211 
212     //查询一条
213     public function find()
214     {
215         $this->ParseSelectSql();
216         $row = $this->conn->query( $this->sql )->fetch( PDO::FETCH_ASSOC );
217 
218         $arrObj = clone $this;  //clone当前对象防止对this对象造成污染
219         $arrObj->data = $row;
220         $result = $arrObj;
221         unset( $arrObj );
222 
223         return $result;
224     }
225 
226     //添加数据
227     public function add( $data )
228     {
229         if( !is_array( $data ) ){
230             throw new exception("添加数据add方法参数必须为数组");
231         }
232 
233         $this->ParseAddSql();
234         foreach( $data as $key=>$vo ){
235             $this->sql .= " `{$key}` = '" . $vo . "',";
236         }
237 
238         $this->conn->exec( rtrim( $this->sql, ',' ) );
239         return $this->conn->lastInsertId();
240     }
241 
242     //更新语句
243     public function update( $data )
244     {
245         if( !is_array( $data ) ){
246             throw new exception("更新数据update方法参数必须为数组");
247         }
248 
249         $this->ParseUpdateSql();
250         foreach( $data as $key=>$vo ){
251             $this->sql .= " `{$key}` = '" . $vo . "',";
252         }
253 
254         $this->sql = rtrim( $this->sql, ',' ) . ' where ' . $this->alias['where'];
255         return $this->conn->exec( $this->sql );
256 
257     }
258 
259     //删除语句
260     public function delete()
261     {
262         $this->ParseDeleteSql();
263         return $this->conn->exec( $this->sql );
264     }
265 
266     //获取查询数据
267     public function getData()
268     {
269         return $this->data;
270     }
271 
272     //获取最后一次执行的sql语句
273     public function getLastSql()
274     {
275         return $this->sql;
276     }
277 
278     public function __get($name)
279     {
280         return $this->getData()[$name];
281     }
282 
283     public function offsetExists($offset)
284     {
285         if( !isset( $this->getData()[$offset] ) ){
286             return NULL;
287         }
288     }
289 
290     public function offsetGet($offset)
291     {
292         return $this->getData()[$offset];
293     }
294 
295     public function offsetSet($offset, $value)
296     {
297         return $this->data[$offset] = $value;
298     }
299 
300     public function offsetUnset($offset)
301     {
302         unset( $this->data[$offset] );
303     }
304 }

  我们怎么使用它呢?首先实例化。

1 <?php
2 $orm = new MyOrm();

  我本地演示的表机构和数据如下:

  接下来展示一下它有那些用法,熟悉TP的同学肯定感觉很熟悉。

 1 <?php
 2 //查询语句
 3 $res = $orm->table('user')->order('id desc')->select();
 4 $res = $orm->table('user')->where("name='test'")->order('id desc')->select();
 5 $res = $orm->table('user')->where(['id' => 1])->order('id desc')->find();
 6 $res = $orm->table('user')->where("age > 20")->group('group by name')->order('id desc')->limit(2)->select();
 7 $res = $orm->table('user')->where("age > 20")->group('group by name')->order('id desc')->limit('2,2')->select();
 8 
 9 //你可以这样处理数据
10 foreach( $res as $key=>$vo ){
11     echo $vo->name . '<br/>';
12 }
13 //也可以这样处理
14 foreach( $res as $key=>$vo ){
15     echo $vo['name'] . '<br/>';
16 }
17 //还可以这样
18 foreach( $res as $key=>$vo ){
19     print_r( $vo->getData() ) . '<br/>';
20 }
21 
22 //添加数据
23 $data = [
24     'name' => 'test1',
25     'age' => 20,
26     'password' => '21232f297a57a5a743894a0e4a801fc3',
27     'salt' => 'domain'
28 ];
29 $res = $orm->table('user')->add( $data );
30 
31 //更新数据
32 $res = $orm->table('user')->where(['id' => 4])->update( ['name' => 'sdfdsfdsd', 'salt' => '111'] );
33 
34 //删除数据
35 $res = $orm->table('user')->where(['id' => 7, 'id' => 6])->delete();
36 
37 //获取执行的sql语句
38 echo $orm->getLastSql();
39 
40 var_dump($res);

 

  

posted @ 2016-11-29 11:55  NickBai  阅读(267)  评论(0编辑  收藏  举报