V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
caoyangmin
V2EX  ›  PHP

PhpBoot 入门(二) 面向对象的方式编写 SQL

  •  
  •   caoyangmin · 2017-08-24 13:58:55 +08:00 · 2214 次点击
    这是一个创建于 2641 天前的主题,其中的信息可能已经有所发展或是发生改变。

    PhpBoot 是一款为快速开发 RESTful API 而设计的 PHP 框架(加星请点这里>>>PbpBoot Github<<<)。

    PhpBoot\DB 对 PDO 进行了封装,使开发者可以更方便的编写正确和安全的 SQL。下面将继续上一篇: 快速开发 RESTful 接口的示例,介绍PhpBoot\DB的使用。

    配置

    可以通过依赖注入的方式,对数据库进行配置。

    1. 在需要数据库的类中加入依赖注入代码:

      use PhpBoot\DB\DB;
      use PhpBoot\DI\Traits\EnableDIAnnotations;
      
      class Books
      {
          use EnableDIAnnotations; //启用通过 @inject 标记注入依赖
      
          /**
           * @inject
           * @var DB
           */
          private $db;
      
          public function getBooks()...
      }
      

      框架在实例化Books后,根据@inject注释, 自动给属性$db赋值,其逻辑等价于:

      $books->db = $app->get(DB::class);
      
    2. 修改数据库配置

      在 config.php 中加入以下配置(数据库地址等需根据实际情况修改):

      'DB.connection'=> 'mysql:dbname=phpboot-example;host=127.0.0.1',
      'DB.username'=> 'root',
      'DB.password'=> 'root',
      'DB.options' => [],
      

    编写 SQL

    下面将通过实现 createBook、deleteBook、updateBook、findBooks 方法,演示 insert、delete、update、select 的使用。

    INSERT

    public function createBook(Book $book)
    {
        $newId = $this->db->insertInto('books')
            ->values([
    	        'name'=>$book->name,
    	        'brief'=>$book->brief,
    	        ...
            ])
            ->exec()
            ->lastInsertId(); 
        return $newId;
    }
    

    DELETE

    public function deleteBook($id)
    {
        $this->db->deleteFrom('books')
            ->where(['id'=>$id])
            ->exec();
    }
    

    UPDATE

    public function updateBook(Book $book)
    {
        $this->db->update('books')
            ->set([
    	        'name'=>$book->name,
    	        'brief'=>$book->brief,
    	        ...
            ])
            ->where(['id'=>$book->id])
            ->exec(); 
    }
    

    SELECT

    public function findBooks($name, $offsit, $limit)
    {
        $books = $this->db->select('*')
            ->from('books')
            ->where('name LIKE ?', "%$name%")
            ->orderBy('id')
            ->limit($offsit, $limit)->get();
            
        return $books;
    }
    

    高级用法

    上述示例展示了PhpBoot\DB的基础用法,PhpBoot\DB同时也支持更复杂的 SQL。

    复杂 WHERE

    类似 SQL WHERE a=1 OR (b=2 and c=3), 可以以下代码实现:

    ->where(['a'=>1])
    ->orWhere(function(ScopedQuery $query){
        $query->where(['b'=>2, 'c'=>3])
    })
    

    上面例子中,ScopedQuery 中还能再嵌套 ScopedQuery

    JOIN

    $db->select('books.*', DB::raw('authors.name as author'))
        ->from('books')
        ->where(['books.id'=>1])
        ->leftJoin('authors')->on('books.authorId = authors.id')
        ->get()
    

    WHERE ... IN ...

    使用PDO时,WHERE IN的预处理方式很不方便,需要为IN的元素预留数量相等的?, 比如:

    $pdo->prepare(
        'SELECT * FROM table WHERE a IN (?,?,?)'
    )->execute([1,2,3])
    

    而使用PhpBoot\DB可以解决这个问题:

    $db->select()->from('table')->where('a IN (?)', [1,2,3]);
    

    使用 SQL 函数

    默认情况下,框架会对输入做转换, 如会在表名和列名外加上``,会把变量作为绑定处理,比如下面的语句

    $db->select('count(*) AS count')
        ->from('table')
        ->where(['time'=>['>'=>'now()']]);
    

    等价 的 SQL:

    SELECT `count(*) AS count` FROM `table` where `time` > 'now()'
    

    如果希望框架不做转换,需要使用DB::raw(),比如:

    $db->select(DB::raw('count(*) AS count'))
        ->from('table')
        ->where(['time'=>['>'=>DB::raw('now()')]]);
    

    与下面 SQL 等价

    SELECT count(*) AS count FROM `table` where `time` > now()
    

    子查询

    下面代码演示子查询用法:

    $parent = $db->select()->from('table1')->where('a=1');
    $child = $db->select()->from($parent);
    

    与下面 SQL 等价

    SELECT * FROM (SELECT * FROM `table1` WHERE a=1)
    

    事务

    $db->transaction(
        function(DB $db){
            $db->update('table1')->...
            $db->update('table1')->...
        }
    )
    

    事务允许嵌套,但只有最外层的事务起作用,内部嵌套的事务与最外层事务将被当做同一个事务。

    使用多个数据库

    PhpBoot 为DB 类定义了默认的构造方式,形式如下:

    DB::class => \DI\factory([DB::class, 'connect'])
        ->parameter('dsn', \DI\get('DB.connection'))
        ->parameter('username', \DI\get('DB.username'))
        ->parameter('password', \DI\get('DB.password'))
        ->parameter('options', \DI\get('DB.options')),
    

    所以如果你的业务只使用连接一个数据库,只需要对DB.connection, DB.username ,DB.password, DB.options进行配置即可。但有的时候可能需要对在应用中连接不同的数据库,这时可以通过依赖注入配置多个库,如:

    1. 先配置另一个数据库连接

      'another_db' => \DI\factory([DB::class, 'connect'])
          ->parameter('dsn', 'mysql:dbname=phpboot-example;host=127.0.0.1')
          ->parameter('username', 'root')
          ->parameter('password', 'root')
          ->parameter('options', [])
      
    2. 在需要的地方注入此连接

      use PhpBoot\DB;
      
      class Books
      {
          /**
           * @inject another_db
           * @var DB
           */
          private $db2;
      }
      ```	
      
      

    帮助和文档

    2 条回复    2017-08-31 12:22:14 +08:00
    gouchaoer
        1
    gouchaoer  
       2017-08-29 19:47:10 +08:00 via Android
    php 框架已经非常成熟了
    lyhiving
        2
    lyhiving  
       2017-08-31 12:22:14 +08:00
    感觉轮子了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1105 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 19:17 · PVG 03:17 · LAX 11:17 · JFK 14:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.