目录
1, 添加数据库访问配置参数
2,创建数据库
3,创建实体类
4,实体映射数据库表
5,命令行执行sql
6,控制器中访问数据层
1,直接访问
2,使用Repository访问
7,持久化数据
8,查询
访问数据库用到的组件是doctrine,这个堪比java界的hibernate,里面的很过概念都有相同之处,在下面的文章描述里面,有对这两者结合起来进行对比。
在项目的根目录下,不是config目录,打开里面的 .env文件,里面配置好访问数据库的参数。
# customize this line!
DATABASE_URL="mysql://db_user:[email protected]:3306/db_name"
# to use sqlite:
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db"
可以手工在数据库客户端命令行里面创建,也可以使用doctrine创建。
如果需为创建的数据库添加参数的话,建议使用命令行创建,比如:定义页面大小,数据存放位置等等。
php bin/console doctrine:database:create
可以手工在开发环境里面创建,也可以使用symfony自带的命令进行创建。
php bin/console make:entity
在这新建的实体类为Product:
// src/Entity/Product.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\ProductRepository")
*/
class Product
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="integer")
*/
private $price;
public function getId()
{
return $this->id;
}
// ... getter and setter 方法省略掉
}
每个实体类必须有一个id,用注解 @ORM\Id ,
实体类的每个属性都有注解ORM\Column)进行标注,证明它是一个表的列。
@ORM\Column(type="string", length=255)
这个注解是标注这个列的数据类型是string,最大长度是255,对应的数据库的类型不见得是string,这个看各个数据库厂商的规范,一般都是varchar。
跟数据库的实际类型的对应表,可以看doctrine文档。
https://www.doctrine-project.org/projects/doctrine-dbal/en/2.10/reference/types.html#types
@ORM\Column(type="integer")
这个注解是标注这个列的数据类型是integer,对应的数据库的类型可以从doctrine的官方文档里面看到。
Product这个实体类信息跟数据库中的表数据是对应的,这个工作是由orm框架doctrine来完成的。
php bin/console doctrine:query:sql 'SELECT * FROM product'
这个是在命令行里面,执行sql。
$product = $this->getDoctrine()
->getRepository(Product::class)
->find($id);
上面这行代码,就是直接使用doctrine对象,访问数据层。
Repository相当于java里面的Dao,数据访问层。
// src/Controller/ProductController.php
// ...
use App\Repository\ProductRepository;
/**
* @Route("/product/{id}", name="product_show")
*/
public function show($id, ProductRepository $productRepository)
{
$product = $productRepository
->find($id);
// ...
}
上面代码就是创建了ProductRepository这个类,这也是我们在项目中常用的方法,这个类的对象注入容器中,在控制器中就能很方便获取到。、
也可以使用上面第一种,利用doctrine对象获取。
$repository = $this->getDoctrine()->getRepository(Product::class);
使用doctrine对象管理者持久化数据:
包括对增加,删除,修改。
$entityManager->flush();
对象是有状态的,这个类似hibernate里面的对象状态:transient(瞬时状态),persistent(持久化状态)以及detached(游离状态)。
在doctrine里面,没有文档明确这样对状态定义,实际上是一回事。如果读过hibernate源码的时候,能明白,这种被hibernate管理的对象并不是一个原生的对象,是一个利用字节码生成的对象,这种对象里面才能持有数据访问会话。
初学的时候,对 cascade ,inverse 这两个关键字都感觉很难理解,学个orm框架使用,还被强制要求理解这么多概念,这就加大了学习的曲线。
在doctrine里面,也是有着cascade ,inverse ,跟hibernate是一回事。
具体的怎么理解,后面文章再解释,doctrine是一个独立的框架,不是几句话就能说明白,我们这里只是关心,怎样和symfony紧密结合调用。
doctrine提供了一个查询接口,看下这个代码:
$qb = $this->createQueryBuilder('p')
->where('p.price > :price')
->setParameter('price', $price)
->orderBy('p.price', 'ASC');
创建了一个查询构造器,里面传递了where参数,查询参数,排序方式。
doctrine底层会把这种东西翻译成数据库的查询sql。
同时也支持使用原生sql ,代码如下:
$conn = $this->getEntityManager()->getConnection();
$sql = '
SELECT * FROM product p
WHERE p.price > :price
ORDER BY p.price ASC
';
$stmt = $conn->prepare($sql);
$stmt->execute(['price' => $price]);
// returns an array of arrays (i.e. a raw data set)
return $stmt->fetchAll();
注: 老班长开始更新录制的symfony视频教程,可以关注公众号查看。
文章持续更新,可以微信搜索公众号「 程序员老班长 」查看更多文章。