php折腾模拟实现ORM-2

前面我们已经完成了orm最核心部分–拼凑字符串,接下来我们需要执行拼凑完成的sql语句。这里只完成了insert操作

折腾(二)-与pdo进行组合,实现执行拼凑完成的sql语句

我们先建立两张表

user

类型长度小数点允许空值
user_idint110false
user_namevarchar200false
user_pwdvarchar320false

order

类型长度小数点允许空值
order_idint110false
user_idint110false
order_pricedecimal52false

执行insert后的效果

这里写图片描述
这里写图片描述
与pdo组合之后的代码如下,所示,有兴趣可以研究下:

<?php
ini_set('display_errors',1);
ini_set('error_reporting',E_ALL);

$map=function ($items) {
    if (!is_array($items)) {
        return $items;
    } else {
        $result="";
        foreach ($items[1] as $item) {
            if ($result!="")
                $result.=",";
            $result.=$item.$this->_aliastb($item);//类似news,news_class 添加到form后面
        }
        return $items[0].$result;
    }
};
class orm
{
    public $sql=array(
        "select"=>"select ",
        "from"=>array("from ",array()),
        "where"=>" where ",
        "orderby"=>" order by ",
        "insertinto"=>"insert into ",//insert操作
        "insertfields"=>"",
        "values"=>" values"
    );
    public $errorCode="";//错误代码
    public $sql_bak=[];
    public function __construct()
    {
        $this->sql_bak=$this->sql;
        $this->db=new PDO("mysql:host=127.0.0.1;dbname=testOrm","root","hello2016");//初始化数据库连接

    }

    public function select()
    {
        $fields=func_get_args();
        foreach ($fields as $field) {
            if (is_array($field)) {
                $get_key=key($field);//获取数组的key,其实就是表的名字,还需要在字段前面加上表前缀
                $this->__add(__FUNCTION__, $this->_aliastb($get_key).'.'.$field[$get_key]);
            } else {
                $this->__add(__FUNCTION__, $field);
            }
        }
        return $this;
    }
    //插入数据
    public function insert() {
        $params=func_get_args();//获取可变参数
        $fields=[];
        $fields_values=[];
        $callback=[];
        foreach ($params as $param) {
            if (is_array($param)) {//代表要拼接的是字段和值
                foreach ($param as $item) {
                    //取出字段名
                    $field=key($item);
                    //取出字段的值
                    $field_value=$item[$field];

                    //把上面的字段和字段值插入相对应的数组
                    $fields[]=$field;
                    //拼凑字符串的时候,判断是否是字符串,如果是字符串则要加上单引号
                    if (is_string($field_value)) {
                        $field_value="'".$field_value."'";
                    }
                    $fields_values[]=$field_value;
                }
                //处理完参数之后,构造要插入字段的拼凑
                $this->__add("insertfields", '('.implode($fields,',').')');
                $this->__add("values", '('.implode($fields_values,',').')');
            }
            //如果是字符串说明传的是表名
            if (is_string($param)) {
                $this->__add("insertinto", $param);
            }
            if(is_bool($param) && $param) //如果传过来的参数是 布尔型,且为true,则默认开启事务
            {

                $this->db->beginTransaction();
            }
            if (is_callable($param)) {
                $callback[]=$param;
            }
        }
        if(count($callback)>0)
        {
            $this->exec();//如果有匿名函数,则先执行SQL
            $this->clearConfig();  //恢复配置到最开始状态,防止执行其他SQL时产生冲突。大家可以把SQL保存到 某个类属性中
            foreach($callback as $call)//最后统一执行各个回调函数
            {
                $call=Closure::bind($call,$this);//这样在匿名函数中就可以使用$this ,且这个$this就是orm对象
                $call();//手工调用 匿名函数,这就是回调
            }
        }
        return $this;
    }
    //避免sql语句相互干扰
    function clearConfig()//恢复到原有配置
    {
        $this->sql=$this->sql_bak;

    }
    //排序
    function orderby($str, $order)
    {
        $order=' '.$order;
        if (is_array($str)) {
            $tb=key($str);
            $this->__add(__FUNCTION__, $this->_aliastb($tb).'.'.$str[$tb].$order);
        } else {
            $this->__add(__FUNCTION__, $str.$order);
        }
        return $this;
    }
    //给表加别名
    public function _aliastb($tbName) {
        return ' _'.$tbName;
    }
    public function from($tableName)//处理from过程
    {
        if (is_array($tableName)) {//是数组的话就是代表多张表关联
            if (count($tableName)!=2) return $this;//参数值类似[["name"=>classid""],["name_class"]=>"id"],小于2灭有意义
            $tb1=current($tableName);
            $tb2=next($tableName);

            //第一步,把表的key值作为from参数进行处理
            $tb1_key=key($tb1);
            $tb1_value=$tb1[$tb1_key];

            $tb2_key=key($tb2);
            $tb2_value=$tb2[$tb2_key];

            $this->__add(__FUNCTION__, $tb1_key);
            $this->__add(__FUNCTION__, $tb2_key);

            //第二步,拼凑where条件
            $whereString=' _'.$tb1_key.'.'.$tb1_value.'='."_".$tb2_key.'.'.$tb2_value;
            $this->where($whereString);
            return $this;

        } else { //字符串则表示单张表查询
            $this->__add(__FUNCTION__, $tableName);
            return $this;
        }

    }

    public function where($str) {
        $this->__add(__FUNCTION__, $str, " and ");
        return $this;
    }

    public function  __add($key,  $str,  $spliter=",")//实现字符串的累加
    {
        //调用不存在的方法,直接返回
        if(!array_key_exists($key, $this->sql))   return ;
        if (is_array($this->sql[$key])) {
            //如果已经存在该项表明我们不做什么处理
            if (!in_array($str, $this->sql[$key][1])) {
                $this->sql[$key][1][]=$str;
            }
        } else {
            //如果是字符串,直接进行字符串累加
//            if (trim($this->sql[$key])!=$key)
            if (preg_replace('/\s/', '', $this->sql[$key])!=$key && preg_replace("/\s/", '', $this->sql[$key])!="")
                $this->sql[$key].=$spliter;
            $this->sql[$key].=$str;
        }

    }
    public function __toString()
    {
        global $map;

        $map=Closure::bind($map ,$this);
        //
        $filter=function ($value, $key) {
//            if(!is_string($value)) return true;
            if(is_array($value)) {
                if(count($value[1])>0) return true;
                return false;
            }
            //如果是空字符串也不参与累加
            if(preg_replace("/\s/", '', $value)==$key || preg_replace("/\s/", "", $value )=="")
                return false;
            return true;
        };
        $this->sql=array_filter($this->sql, $filter, ARRAY_FILTER_USE_BOTH );
        $res=array_map($map, array_values($this->sql));//
        $this->sql=$this->sql_bak;
        return implode(array_values($res), ' ');//把新的数组重新构建成一个字符串
    }
    public function exec()
    {
        //测试执行方法
        $sql=strval($this); //会自动调用 _tostring方法

        $stmt=$this->db->prepare($sql);
        if(!$stmt->execute())//执行失败,
        {
            if($this->db->inTransaction()) //判断是否开启了事务
            {
                $this->db->rollBack();//执行回滚
            }
            $this->errorCode=$stmt->errorCode();

            echo "执行Sql".$sql.'出错,错误代码:'.$this->errorCode.",错误信息:".$stmt->errorInfo()[2];
        }

        return $this;
    }
    function getLastInsertID() //获取上一条SQL执行情况
    {
        return $this->db->lastInsertId();
    }

    function getAll() //获取全部取出的结果
    {
        return $this->db->fetchAll();
    }
    function commit()
    {
        //提交事务
        if($this->db->inTransaction())
            $this->db->commit();

    }
}
    $orm=new orm();
    echo $orm->insert(true,[
        ['user_name'=>"seven"],
        ['user_pwd'=>md5('123')]
    ],"user",function(){
        $userid=$this->getLastInsertID(); //获取用户注册后的自增ID
        $this->insert([
            ['user_id'=>intval($userid)],
            ['order_price'=>100],
        ],"orders",function(){
            if($this->errorCode=="")
            {
                $this->commit();
                echo "sucess!";
            }
            else
            {
                echo "fail!";
            }
        });

    });
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值