DoctrineDBALQueryBuilder教程展示了如何使用Doctrine的QueryBuilder在PHP中对数据库进行编程。
学说
Doctrine是一组PHP库,主要专注于在PHP中提供持久性服务。它的主要项目是对象关系映射器(ORM)和数据库抽象层(DBAL)。Doctrine是一个开源项目,在MIT许可下免费提供。
Doctrine查询生成器
DoctrineQueryBuilder提供了一个方便、流畅的界面来创建和运行数据库查询。它是对运行SQL语句的低级细节的抽象。它使程序员免受复杂过程的影响。
Doctrine有两种查询构建器;一个用于ORM,一个用于DBAL。在本教程中,我们介绍了DBAL的QueryBuilder。
Doctrine数据库抽象层(DBAL)是一个位于PDO之上的抽象层,它提供了一个直观且灵活的API,用于与最流行的关系数据库进行通信。
PostgreSQL数据库
在本教程中,我们使用PostgreSQL数据库。
-- cars.sql for PostgreSQL database DROP TABLE IF EXISTS cars; CREATE TABLE cars(id SERIAL PRIMARY KEY, name VARCHAR(255), price INT); INSERT INTO cars(name, price) VALUES('Audi',52642); INSERT INTO cars(name, price) VALUES('Mercedes',57127); INSERT INTO cars(name, price) VALUES('Skoda',9000); INSERT INTO cars(name, price) VALUES('Volvo',29000); INSERT INTO cars(name, price) VALUES('Bentley',350000); INSERT INTO cars(name, price) VALUES('Citroen',21000); INSERT INTO cars(name, price) VALUES('Hummer',41400); INSERT INTO cars(name, price) VALUES('Volkswagen',21600);
这些SQL命令创建了一个cars
表。
学说安装
我们安装了Doctrine和一些辅助工具。
$ composer req doctrine/dbal
我们安装Doctrine。请注意,DBAL层包含在doctrine/dbal
包中。
$ composer req symfony/var-dumper $ composer req tightenco/collect
我们安装Symfony的dumper和Laravel集合。我们将在示例中使用它们。
$ composer dumpautoload
我们生成需要包含在项目中的所有类的列表。composer
重新读取composer.json
文件以构建文件列表自动加载。
引导DoctrineCLI示例
我们创建了一个将包含在所有示例中的引导文件。
<?php require_once "vendor/autoload.php"; use Doctrine\DBAL\DriverManager; $attrs = ['driver' => 'pdo_pgsql', 'host' => 'localhost', 'dbname' => 'testdb', 'port' => 5432, 'user' => 'postgres', 'password' => 's$cret']; $conn = DriverManager::getConnection($attrs);
在引导文件中,我们包含自动加载文件并设置与PostgreSQL数据库的连接。
获取PostgreSQL版本
在第一个示例中,我们获取了PostgreSQL的版本。
<?php require_once "bootstrap.php"; $queryBuilder = $conn->createQueryBuilder(); $queryBuilder = $queryBuilder->select('version()'); $version = $queryBuilder->execute()->fetchColumn(0); echo $version . "\n";
该示例打印PostgreSQL数据库的版本。
$queryBuilder = $conn->createQueryBuilder();
从连接对象,我们使用createQueryBuilder()
创建一个查询生成器。
$queryBuilder = $queryBuilder->select('version()');
我们使用select()
执行version()
函数。
$version = $queryBuilder->execute()->fetchColumn(0);
我们执行查询并使用fetchColumn()
获取结果。注意方法调用的链接;这称为流畅的API。
$ php version.php PostgreSQL 11.1, compiled by Visual C++ build 1914, 64-bit
这是输出。
DoctrineQueryBuilderfetchall
fetchall()
方法返回表中的所有行。
<?php require_once "bootstrap.php"; $queryBuilder = $conn->createQueryBuilder(); $queryBuilder->select('*')->from('cars'); $stm = $queryBuilder->execute(); $data = $stm->fetchAll(); $coll = collect($data); $sorted = $coll->sortBy('price'); $sorted->each(function($item, $key) { echo sprintf("Id: %d Name: %s Price: %d\n", $item['id'], $item['name'], $item['price']); });
该示例从cars
表中检索所有行。
$queryBuilder->select('*')->from('cars');
我们从cars
表中选择所有行。select()
将列名显示为参数。
$stm = $queryBuilder->execute(); $data = $stm->fetchAll();
我们执行查询并使用fetchAll()
获取所有行。
$coll = collect($data); $sorted = $coll->sortBy('price');
我们使用Laravel集合对数据进行排序。
$sorted->each(function($item, $key) { echo sprintf("Id: %d Name: %s Price: %d\n", $item['id'], $item['name'], $item['price']); });
排序后的数据打印到控制台。
$ php fetch_all.php Id: 3 Name: Skoda Price: 9000 Id: 6 Name: Citroen Price: 21000 Id: 8 Name: Volkswagen Price: 21600 Id: 4 Name: Volvo Price: 29000 Id: 7 Name: Hummer Price: 41400 Id: 1 Name: Audi Price: 52642 Id: 2 Name: Mercedes Price: 57127 Id: 5 Name: Bentley Price: 350000
这是输出。数据按price
列排序。
DoctrineQueryBuilder表别名
我们可以给数据库表起别名。当表名很长并且我们使用多个表时,这很有用。
<?php require_once "bootstrap.php"; $queryBuilder = $conn->createQueryBuilder(); $queryBuilder = $queryBuilder->select('*')->from('cars', 'c') ->where('c.price < 30000'); $selected = $queryBuilder->execute()->fetchAll(); dump($selected);
该示例打印所有价格低于30000的汽车。
$queryBuilder = $queryBuilder->select('*')->from('cars', 'c') ->where('c.price < 30000');
我们给cars
表别名c
。稍后,我们通过别名引用该表。
dump($selected);
我们用dump()
输出数据。
$ php table_alias.php array:4 [ 0 => array:3 [ "id" => 3 "name" => "Skoda" "price" => 9000 ] 1 => array:3 [ "id" => 4 "name" => "Volvo" "price" => 29000 ] 2 => array:3 [ "id" => 6 "name" => "Citroen" "price" => 21000 ] 3 => array:3 [ "id" => 8 "name" => "Volkswagen" "price" => 21600 ] ]
有四辆价格低于30000的汽车。输出使用Symfony的自卸车进行了很好的格式化。输出在终端上也是彩色的。
DoctrineQueryBuildersetParameter
setParameter()
用于将参数设置为查询占位符。Doctrine支持位置参数和命名参数。
参数化查询用于保护代码免受SQL注入攻击并提高查询效率。
<?php require_once "bootstrap.php"; $id = 6; $queryBuilder = $conn->createQueryBuilder(); $queryBuilder = $queryBuilder->select('name')->from('cars') ->where('id = ?')->setParameter(0, $id); $car_name = $queryBuilder->execute()->fetchColumn(0); echo $car_name . "\n";
在示例中,我们获取了ID为6的行。我们使用参数化查询来获取该列。
$queryBuilder = $queryBuilder->select('name')->from('cars') ->where('id = ?')->setParameter(0, $id);
占位符用?
字符标识。这种类型称为位置参数。使用setParameter()
,我们将值映射到占位符。
$ php fetch_column.php Citroen
这是输出。
DoctrineQueryBuilderorderBy
可以使用orderBy()
对数据进行排序。有时我们无法控制数据发送给我们的方式;在这种情况下,我们可以使用LaravelCollections对数据进行排序,就像我们在fetchall示例中所做的那样。
<?php require_once "bootstrap.php"; $queryBuilder = $conn->createQueryBuilder(); $queryBuilder ->select('*') ->from('cars') ->orderBy('name', 'desc'); $stm = $queryBuilder->execute(); $data = $stm->fetchAll(); $coll = collect($data); $coll->each(function($item, $key) { echo sprintf("id: %d name: %s price: %d\n", $item['id'], $item['name'], $item['price']); });
该示例从cars
表中检索所有行,并按汽车名称降序对它们进行排序。
$queryBuilder ->select('*') ->from('cars') ->orderBy('name', 'desc');
数据被选择和排序。
$ php order_by.php id: 4 name: Volvo price: 29000 id: 8 name: Volkswagen price: 21600 id: 3 name: Skoda price: 9000 id: 2 name: Mercedes price: 57127 id: 7 name: Hummer price: 41400 id: 6 name: Citroen price: 21000 id: 5 name: Bentley price: 350000 id: 1 name: Audi price: 52642
这是输出。
(adsbygoogle=window.adsbygoogle||[]).push({});
DoctrineQueryBuilder在哪里
以下示例显示如何使用WHEREIN
子句构建查询。
<?php require_once "bootstrap.php"; use Doctrine\DBAL\Connection; $ids = [2, 4, 6]; $queryBuilder = $conn->createQueryBuilder(); $queryBuilder->select('*')->from('cars') ->where('id IN (?)')->setParameter(0, $ids, Connection::PARAM_INT_ARRAY); $cars = $queryBuilder->execute()->fetchAll(); $data = collect($cars); $data->each(function ($e) { dump($e); });
该示例打印具有指定ID的汽车:2、4和6。
$queryBuilder->select('*')->from('cars') ->where('id IN (?)')->setParameter(0, $ids, Connection::PARAM_INT_ARRAY);
我们需要告诉Doctrine我们使用一个数组作为带有Connection::PARAM_INT_ARRAY
标志的参数。
$ php where_in.php array:3 [ "id" => 2 "name" => "Mercedes" "price" => 57127 ] array:3 [ "id" => 4 "name" => "Volvo" "price" => 29000 ] array:3 [ "id" => 6 "name" => "Citroen" "price" => 21000 ]
这是输出。
结合WHERE子句的DoctrineQueryBuilder
我们可以通过添加andWhere()
来组合WHERE
子句。
<?php require_once "bootstrap.php"; $minPrice = 10000; $maxPrice = 50000; $queryBuilder = $conn->createQueryBuilder(); $queryBuilder ->select('*') ->from('cars') ->where('price > ?') ->andWhere('price < ?') ->setParameter(0, $minPrice) ->setParameter(1, $maxPrice); $stm = $queryBuilder->execute(); $data = $stm->fetchAll(); $coll = collect($data); $coll->each(function($item, $key) { echo sprintf("id: %d name: %s price: %d\n", $item['id'], $item['name'], $item['price']); });
该示例显示了价格介于给定的最低价和最高价之间的所有汽车。
$ php and_where.php id: 4 name: Volvo price: 29000 id: 6 name: Citroen price: 21000 id: 7 name: Hummer price: 41400 id: 8 name: Volkswagen price: 21600
有四辆车满足条件。
DoctrineQueryBuilder插入行
使用insert()
和values()
插入新行。
<?php require_once "bootstrap.php"; $name = 'Oldsmobile'; $price = 28800; $queryBuilder = $conn->createQueryBuilder(); $queryBuilder = $queryBuilder->insert('cars') ->values(['name' => '?', 'price' => '?']) ->setParameters([0 => $name, 1 => $price]); $queryBuilder->execute(); $sql = $queryBuilder->getSQL(); echo "Executed: $sql\n";
该示例将一辆新车插入到cars
表中。
$queryBuilder = $queryBuilder->insert('cars') ->values(['name' => '?', 'price' => '?']) ->setParameters([0 => $name, 1 => $price]);
可以使用setParameters()
指定多个参数。
$sql = $queryBuilder->getSQL();
getSQL()
获取Doctrine生成的SQL语句。
$ php insert_row.php Executed: INSERT INTO cars (name, price) VALUES(?, ?)
输出显示生成的SQL语句。
DoctrineQueryBuilder删除
使用delete()
删除数据。
<?php require_once "bootstrap.php"; $name = 'Oldsmobile'; $price = 26600; $queryBuilder = $conn->createQueryBuilder(); $queryBuilder = $queryBuilder->delete('cars') ->where('id IN (1, 2, 3)'); $n = $queryBuilder->execute(); echo "The query deleted $n rows\n";
该示例删除ID为1、2和3的行。
$n = $queryBuilder->execute();
execute()
方法返回删除的行数。
$ php delete_rows.php The query deleted 3 rows
这是输出。
DoctrineQueryBuilder更新行
使用udpate()
和set()
更新一行。
<?php require_once "bootstrap.php"; $name = 'Oldsmobile'; $price = 26600; $queryBuilder = $conn->createQueryBuilder(); $queryBuilder = $queryBuilder->update('cars') ->set('price', $queryBuilder->createNamedParameter($price)) ->where('id = 9'); $queryBuilder->execute(); $sql = $queryBuilder->getSQL(); echo "Executed: $sql\n";
该示例更新了ID为9的汽车的价格。
Symfony原则示例
以下示例是一个简单的Symfony网络应用程序。Symfony使用Doctrine来实现持久化。
$ composer create-project symfony/skeleton symfapp $ cd symfapp
我们创建一个新的Symfony骨架应用程序。
$ composer require symfony/orm-pack
我们安装Doctrine。
$ composer require maker --dev $ composer require server --dev
我们安装了maker
和server
组件。
doctrine: dbal: # configure these for your database server driver: pdo_pgsql charset: utf8
我们将Doctrine配置为使用PostgreSQL。默认情况下,Symfony具有MySQL的配置。
... DATABASE_URL=pgsql://postgres:s$cret@127.0.0.1:5432/testdb
在.env
文件中,我们设置了DATABASE_URL
。
$ php bin/console doctrine:query:sql "select version()" array(1) { [0]=> array(1) { ["version"]=> string(58) "PostgreSQL 11.1, compiled by Visual C++ build 1914, 64-bit" } }
我们验证PostgreSQL设置。
$ php bin/console make:controller HomeController
通过maker,我们创建了一个新的控制器。
<?php namespace App\Controller; use Doctrine\DBAL\Connection; use Symfony\Component\Routing\Annotation\Route; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; class HomeController extends AbstractController { /** * @Route("/home", name="home") */ public function index(Connection $conn) { $queryBuilder = $conn->createQueryBuilder(); $data = $queryBuilder->select('*')->from('cars')->execute()->fetchAll(); return $this->json($data); } }
index()
方法返回数据库表中的所有行。请注意,为了简单起见,我们已将查询构建器放在控制器中。在生产应用程序中,还应该有一个服务层和一个存储库。
return $this->json($data);
数据以JSON格式发送回客户端。
$ php bin/console server:run
我们运行开发服务器。
$ curl localhost:8000/home [{"id":4,"name":"Volvo","price":29000},{"id":5,"name":"Bentley","price":350000}, {"id":6,"name":"Citroen","price":21000},{"id":7,"name":"Hummer","price":41400}, {"id":8,"name":"Volkswagen","price":21600},{"id":9,"name":"Oldsmobile","price":26600}]
使用curl
,我们向应用程序生成请求。
您可能还对以下相关教程感兴趣:PHPPDO教程、Symfony简介、PHP教程,或列出所有PHP教程。
(adsbygoogle=window.adsbygoogle||[]).push({});
在本教程中,我们使用了DoctrineQueryBuilder和PostgreSQL数据库。