动手创建自己第一个MVC框架项目【三】-中级篇(完)

[ORM篇]
什么是ORM,百度的解释:

对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换[1] 。从效果上说,它其实是创建了一个可在编程语言里使用的--“虚拟对象数据库”。

说了一大堆,不懂。简单来如果用在我们数据库呢就是,让Model(数据库所有的操作对象)与数据表产生对应关系(关联)的一种方法,或者说一种思想,比如你来了个User.php就是对User表的操作


我们现在开始吧,首先我们更改原本的文件路径,把Home、Back里面的Model抽出来,放到App下取名为Entity,以后这个Entity就是我们的Model目录,意思就是Model不分前后台,区别只要同一个Model区分不同的方法名即可。

Entity就是实体的意思。现在开始创建父类模型,Core/Orm.php。 我们实现类名与表名的对应关系的方法是通过父类Orm.php在其构造方法里获取有谁继承了的类名,PHP自带了一个方法可以获取继承类的类名----
get_called_class(); //App\Entity\Users

这样就获取了包含命名空间的类名,现在我们要处理这个包含命名空间的类名,让其仅仅剩下Users

<?php
/**
 *
 * Orm.php
 * User: kalvin
 * Date: 2018/2/1
 * Time: 下午3:02
 */

namespace Core;


/**
 * Class Orm
 * @package Core
 * ORM 父类方法
 */
class Orm
{
    private $className;
    private $server;
    private $type;
    private $username;
    private $password;
    private $port;
    private $dbname;
    private $charset;
    private $_pdo;
    public function __construct()
    {

        $holeClassName=get_called_class(); //App\Entity\Users
        $arr=explode('\\',$holeClassName);
        $this->className=strtolower($arr[count($arr)-1]);
        //根据配置文件项连接数据库
        $this->server=$GLOBALS['conf']['mysql']['server'];
        $this->type=$GLOBALS['conf']['mysql']['type'];
        $this->username=$GLOBALS['conf']['mysql']['username'];
        $this->password=$GLOBALS['conf']['mysql']['password'];
        $this->port=$GLOBALS['conf']['mysql']['port'];
        $this->dbname=$GLOBALS['conf']['mysql']['dbname'];
        $this->charset=$GLOBALS['conf']['mysql']['charset'];
        $this->connect();
    }
    public function connect(){
        $dsn="$this->type:host=$this->server;dbname=$this->dbname;port=$this->port;charset=$this->charset";
        $this->_pdo=new \PDO($dsn,$this->username,$this->password);
    }

}

这样就能连接了,现在我们只要把上面私有化的变量拼接到sql语句中即可

<?php
/**
 *
 * Orm.php
 * User: kalvin
 * Date: 2018/2/1
 * Time: 下午3:02
 */

namespace Core;


/**
 * Class Orm
 * @package Core
 * ORM 父类方法
 */
class Orm
{
    private $className;
    private $server;
    private $type;
    private $username;
    private $password;
    private $port;
    private $dbname;
    private $charset;
    private $_pdo;
    public function __construct()
    {

        $holeClassName=get_called_class(); //App\Entity\Users
        $arr=explode('\\',$holeClassName);
        $this->className=strtolower($arr[count($arr)-1]);
        //根据配置文件项连接数据库
        $this->server=$GLOBALS['conf']['mysql']['server'];
        $this->type=$GLOBALS['conf']['mysql']['type'];
        $this->username=$GLOBALS['conf']['mysql']['username'];
        $this->password=$GLOBALS['conf']['mysql']['password'];
        $this->port=$GLOBALS['conf']['mysql']['port'];
        $this->dbname=$GLOBALS['conf']['mysql']['dbname'];
        $this->charset=$GLOBALS['conf']['mysql']['charset'];
        $this->connect();
    }
    public function connect(){
        $dsn="$this->type:host=$this->server;dbname=$this->dbname;port=$this->port;charset=$this->charset";
        $this->_pdo=new \PDO($dsn,$this->username,$this->password);
        $this->_pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    }

    public function select()
    {
        $sql='select * from '.$this->className;
        $res=$this->query($sql);
        return $res->fetchAll(\PDO::FETCH_ASSOC);
    }

    public function query($sql)
    {
        try{
            $resObj=$this->_pdo->query($sql);
        }catch (\PDOException $e){
           $resObj=$this->errors($e,$sql);
        }
        return $resObj;
    }

    public function errors($e,$sql)
    {
        echo '错误信息为:'.$e->getMessage().'<br/>';
//        echo '错误代码为:'.$e->errorCode() ().'<br/>';
        echo '错误语句为:'.$sql.'<br/>';
        return false;
    }

}

上面的select方法就是拼接了继承的类名的方法

[连贯操作]

我们在使用其他框架的时候发现我们存在着一些连贯操作,那么这个连贯操作怎么实现呢?

比如说laravel有个 Users->where(‘id’,’>’,’2’)->get(); 又或者我们还有Users->where(‘id’,’>’,’2’)->orderby(‘id’)->first().

我们可以动手试试,无论tp还是laravel,他们的连贯操作还有一个关键点,就是如果只有$Useres->where(.....),返回值是什么?一般这个返回值是对象,也就是保留了某些操作的对象。我们看看怎么实现吧。

我们首先先定义

private $where=’ 1 ‘;

用于存放拼接好的字符串

/**
 * @return mixed
 * 连贯操作的 get方法
 */
public function get()
{
    $sql='select * from '.$this->className.' where';
    $sql.=$this->where;
    $res=$this->query($sql);
    return $res->fetchAll(\PDO::FETCH_ASSOC);
}

注意:$this->className后面需要拼接一个空格以防与where语句连接在一起

重头戏来了我们开始写where方法用于连贯操作!

/**
 * @param $field 字段名
 * @param $operator 符号,> < = >= eq等等。。
 * @param $condition 数值或字符串
 * 用户连贯操作的where方法
 */
public function where($field,$operator,$condition)
{
    $this->where.=' '.$field.' '.$operator.' '.$condition.' ';
    return $this;
}

关键在于return this; 返回了当前对象,也正是这个this也保存了上面拼接的结果。

但是我们使用中发现,where只能用一次,如果我有多个where条件就不行了。会报语法错误!

我们继续完善

结果

<?php
/**
 *
 * Orm.php
 * User: kalvin
 * Date: 2018/2/1
 * Time: 下午3:02
 */

namespace Core;


/**
 * Class Orm
 * @package Core
 * ORM 父类方法
 */
class Orm
{
    private $className;
    private $server;
    private $type;
    private $username;
    private $password;
    private $port;
    private $dbname;
    private $charset;
    private $_pdo;
    private $where=' 1 ';
    private $limit='';
    public function __construct()
    {

        $holeClassName=get_called_class(); //App\Entity\Users
        $arr=explode('\\',$holeClassName);
        $this->className=strtolower($arr[count($arr)-1]);
        //根据配置文件项连接数据库
        $this->server=$GLOBALS['conf']['mysql']['server'];
        $this->type=$GLOBALS['conf']['mysql']['type'];
        $this->username=$GLOBALS['conf']['mysql']['username'];
        $this->password=$GLOBALS['conf']['mysql']['password'];
        $this->port=$GLOBALS['conf']['mysql']['port'];
        $this->dbname=$GLOBALS['conf']['mysql']['dbname'];
        $this->charset=$GLOBALS['conf']['mysql']['charset'];
        $this->connect();
    }
    public function connect(){
        $dsn="$this->type:host=$this->server;dbname=$this->dbname;port=$this->port;charset=$this->charset";
        $this->_pdo=new \PDO($dsn,$this->username,$this->password);
        $this->_pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    }

    public function select()
    {
        $sql='select * from '.$this->className;
        $res=$this->query($sql);
        return $res->fetchAll(\PDO::FETCH_ASSOC);
    }

    public function query($sql)
    {
        try{
            $resObj=$this->_pdo->query($sql);
        }catch (\PDOException $e){
           $resObj=$this->errors($e,$sql);
        }
        return $resObj;
    }

    public function errors($e,$sql)
    {
        echo '错误信息为:'.$e->getMessage().'<br/>';
//        echo '错误代码为:'.$e->errorCode() ().'<br/>';
        echo '错误语句为:'.$sql.'<br/>';
        return false;
    }

    /**
     * @return mixed
     * 连贯操作的 get方法
     */
    public function get()
    {
        $sql='select * from '.$this->className.' where';
        $sql.=$this->where;
        $res=$this->query($sql);
        return $res->fetchAll(\PDO::FETCH_ASSOC);
    }

    /**
     * @param $field 字段名
     * @param $operator 符号,> < = >= eq等等。。
     * @param $condition 数值或字符串
     * 用户连贯操作的where方法
     */
    public function where($field,$operator,$condition)
    {
        //如果strlen==3 就是说 之前无where 条件不然就直接
        if (strlen($this->where)==3){
            $this->where=' '.$field.' '.$operator.' '.$condition.' ';
            return $this;
        }
        $this->where.=' and '.$field.' '.$operator.' '.$condition.' ';
        return $this;
    }
}

我们在上面做where做了判断,为什么长度为3因为前后各有一个空格加上数字就是三,如果是第一次where就直接覆盖之前定义的$this->where=’ 1 ‘

如果不是就是拼接上 and 以及条件。我们这章的orm就结束了,如果有什么疑惑可以在评论中留言,详细代码也可以查看我的码云上会有哦

Ecframe链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容