THINKPHP5 Source code parsing (1) database

Source: Internet
Author: User

Objective

TP5 database operations are all done through the DB class, more in line with the habits of the people, such as Simple db::query (),Db::execute (), and complex chain Operation db::table (' user ')- >where (' id=1 ')->select (), the following is the source to understand its work flow

Before looking at the code, let's look at what classes are involved, and TP5 database-related classes have the following:

    • Db (User interface)

    • Connection (connector)

    • Query (Finder)

    • Builder (SQL Builder)

Db::query () What happened? Assuming that the configuration file settings are driven to MySQL, how does the TP5 database class work when the following code is executed?
Db::query ("SELECT * from user where id=?", [1]);

To save the chapters and better understand the process, just the core code is shown below, some of the code is simplified or modified, let's take a look at the DB class:

class db{    private static  $instance  = [];         private static function parseconfig ($config)      {        if  (Empty ($config))  {              $config  = config::get (' database ');         } else {              $config  = config::get ($config);        }         return  $config;    }     public static function connect ($config  = [])     {$name  = MD5 (Serialize ($config));        if  (!isset (self::$ instance[$name])  {$options &Nbsp;= self::p arseconfig ($config); Self:: $instance [$name] = new \think\db\connector\mysql ($ options);     }        return self:: $instance [ $name];    }    public static function __callstatic ($ method,  $params)     {return call_user_func_array ([Self::connect (),  $method] ,  $params);     }}

Because the DB class does not define query (), it triggers __callstatic (), __callstatic () and calls its own connect (), connect () instantiates the MySQL connector (incoming database configuration $options), and then saves to $instance (an array of database connection instances), and then look at the MySQL connector:

namespace Think\db\connector;class Mysql extends connection{protected $builder = ' \\think\\db\\builder\\Mysql '; }

MySQL connector also does not define query () Yes, it inherits connection and see if connection has:

abstract class connection{        protected $ pdostatement;    protected  $linkID;    protected  $config  = [];    public function __construct (array  $config  = [ ])     {        if  (!empty ($config))  {              $this->config = array_ Merge ($this->config,  $config);        }     }    protected function getresult ()     {         return  $this->pdostatement->fetchall (PDO::FETCH_ASSOC);     }        protected function bindvalue ( array  $bind  = [])     {        foreach  ($bind  as  $key  =>   $val)  {             $param  =  Is_numeric ($key)  ?  $key  + 1 :  ': '  .  $key;             if  (Is_array ($val))  {                 if  (PDO::P aram_int ==  $val [1]  &&  " ===  $val [0])  {                      $val [0] = 0;                 }                  $result  =  $this->pdostatement- >bindvalue ($param,   $val [0],  $val [1]);             } else  {                 $result  =  $this->pdostatement->bindvalue ($param,  $val);             }        }     }        public function connect ()     {         if  (! $this->linkid)  {              $config  =  $this->config;              $this->linkid = new pdo ($config [' DSN '],   $config [' username '],  $config [' Password ']);        }         return  $this->linkid;    }             public function query ($sql,  $bind  = [])      {         $this->connect ();         if  (Empty ($this->pdostatement))  {              $this->pdostatement =  $this->linkid->prepare ($sql);         }                  $this->bindvalue ($bind);          $this->pdostatement->execute ();        return  $this- >getresult ();            }     }
Conclusion

Db::query () triggers db::__callstatic (), instantiates the MySQL connector and calls Mysql->query (), and the MySQL connector inherits connection, so it is actually called connection- >query ()

What happened to db::table (' user ')->where (' id=1 ')->select ()?

Both DB and MySQL connectors do not have a table () method defined, and connection also has a __call ():

protected function Getquery () {return new \think\db\query ($this);} Public Function __call ($method, $args) {return Call_user_func_array ([$this->getquery (), $method], $args);}

So db::table (' user ') actually triggered the __call () Magic method, and then instantiated a query object (the constructor passed in to the current MySQL connector object) to see what the query was doing:

namespace think\db;class query{    protected  $connection;     protected  $builder;         public function __ Construct (connection  $connection)     {          $this->connection =  $connection;         $this Setbuilder ();     }        protected function  setbuilder ()     {         $this->builder  = new \think\db\builder\mysql ($this->connection,  $this);     }         public function table ($table)      {         $this->options[' table '] =  $table;         return  $this;    }        public  Function where ($where)     {         $this options[' where '] =  $where;        return  $this;     }        public function query ($sql)      {        return  $this->connection->query ( $sql);    }        public function  Select ()     {         $options  =  $this- >options;         $this->options = [];          $sql  =  $this->builder->select ($options);return  $this- >query ($sql);     }} 

The constructor first saves the current Mysql connector object and instantiates the Think\db\builder\mysql

Query->table () Saves the table name to the $options array, and then returns $this (the current instance) for a chained operation, where () again, focus on select (), it gets $options and empties it for next use, Then call the Builder->select () to get the assembled SQL, by the Connection->query () query the database to obtain the result set, the entire process to this end, then builder is how to assemble SQL?

namespace Think\db\builder;class Mysql extends builder{protected function Parserand () {return ' rand () '; }}

think\db\builder\mysql does not define select (), but it inherits from builder and looks at the builder code:

namespace think\db;abstract class builder{    protected  $connection;     protected  $query;    protected  $selectSql      =  ' select %field% from %table% %where% ';     public  function select ($options  = [])     {          $sql  = str_replace (             ['%table% ',  '%field% ',  '%where% '],             [                  $options [' table '],                  $options [' field '] ?:  ' * ',                  $options [' where '] ?  ' where '. $options [' WHERE '] :  ',             ],  $this->selectsql);         return  $sql;     }    }

Builder replaces SQL templates with $options to get SQL

Conclusion

Db::table () triggers the __callstatic () Instantiation connection and invokes table (), because connection also does not define table (), and it triggers its own __call () instantiation of query and calls table () , table () returns $this to implement the chained Operation Db::table ()->where ()->select (), and select calls Builder->select () to get SQL, and finally calls connection- >query () Gets the result of the query, the solid complete class diagram is represented as follows:


THINKPHP5 Source code parsing (1) database

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.