[031] Symfony4 数据库入门 Part02

在之前已经完成了数据库连接和创建实体后, 接下来对数据库的增删改查进行简单的使用. 主要是了解一下 Doctrine 的数据持久化操作. 操作非常简单. 先创建一个Product控制器来接收浏览器操作.

bin/console make:controller ProductController

增加/插入 数据

打开 src/Controller/ProductController.php, 添加一个 add 方法, 来实现添加数据接口.

<?php

namespace App\Controller;

use App\Entity\Product;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class ProductController extends AbstractController
{

    /**
     * @Route("/product/add", name="url_product_add")
     *
     * @return Response
     */
    public function add()
    {
        //获取实体管理器
        $entityManager = $this->getDoctrine()->getManager();

        //创建商品实体
        $product = new Product();
        $product->setName('Product-' . mt_rand(100, 999));
        $product->setPrice(mt_rand(10, 9999));

        //标记准备持久化实体数据
        $entityManager->persist($product);

        //写入到数据库中
        $entityManager->flush();

        return new Response('Added new product with id: ' . $product->getId() );
    }
}

启动服务器 bin/console server:run, 访问: http://localhost:8000/product/add 数据库中会新增商品记录数据.

使用 Doctrine 提供的命令行工具也可以简单的查询SQL, 查看刚才的数据插入效果:

$ bin/console doctrine:query:sql 'SELECT * FROM product'

查询数据

再添加一个 show 接口, 来展示对应ID的商品名称:

    /**
     * @Route("/product/show/{id}", name="url_product_show")
     *
     * @param int $id
     * @return Response
     */
    public function show($id)
    {
        //根据商品ID查询商品信息到实体对象
        $product = $this->getDoctrine()->getRepository(Product::class)->find($id);

        //监测查询结果
        if (!$product instanceof Product) {
            throw $this->createNotFoundException(
                'No product found for id: ' . $id
            );
        }

        return new Response('The product name: ' . $product->getName());
    }

通过访问 http://localhost:8000/product/show/1 来查看之前添加商品的名称.

修改信息

添加一个 update 接口, 修改商品ID为1的名称为: New name {id}

    /**
     * @Route("/product/update/{id}", name="url_product_update")
     *
     * @param int $id
     * @return Response
     */
    public function update($id)
    {
        $entityManager = $this->getDoctrine()->getManager(); //实体管理器

        //根据商品ID查询商品信息到实体对象
        $product = $entityManager->getRepository(Product::class)->find($id);

        //监测查询结果
        if (!$product instanceof Product) {
            throw $this->createNotFoundException('No product found for id: ' . $id);
        }

        //修改名称
        $product->setName('New name ' . $id);

        //保存到数据库
        $entityManager->persist($product);
        $entityManager->flush();

        return new Response('Product name update to: ' . $product->getName());
    }

通过访问 http://localhost:8000/product/update/1 来修改之前添加商品的名称.

删除信息

添加一个 delete 接口, 实现删除商品操作

    /**
     * @Route("/product/delete/{id}", name="url_product_delete")
     *
     * @param int $id
     * @return Response
     */
    public function delete($id)
    {
        $entityManager = $this->getDoctrine()->getManager(); //实体管理器

        //根据商品ID查询商品信息到实体对象
        $product = $entityManager->getRepository(Product::class)->find($id);

        //监测查询结果
        if (!$product instanceof Product) {
            throw $this->createNotFoundException('No product found for id: ' . $id);
        }

        //删除
        $entityManager->remove($product);
        $entityManager->flush();

        return new Response('Product was deleted: ' . $product->getName());
    }

通过访问 http://localhost:8000/product/delete/1 来删除之前添加商品编号为1的信息.

复杂的查询

在这之前的数据查询都是非常简单的. 正式在项目中遇到的查询都是比较复杂的. 多条件关联的. 这个时候可以在 Repository 中进行扩展.

先实现一个查询: "查询价格大于指定价格的商品信息, 商品按价格升序排列. ", 我们可以定义一个方法: getAllGreaterThanPrice($price)ProductRepository 中.

// src/Repository/ProductRepository.php
// ...
    /**
     * @param $price
     * @return Product[]
     */
    public function getAllGreaterThanPrice($price): array
    {
        $qb = $this->createQueryBuilder('p')
            ->andWhere('p.price > :price')
            ->setParameter('price', $price)
            ->orderBy('p.price', 'ASC')
            ->getQuery();

        return $qb->execute();
    }

定义好后, 在Controller中就可以方便的调用.

$minPrice = 1000;

$products = $this->getDoctrine()
    ->getRepository(Product::class)
    ->getAllGreaterThanPrice($minPrice);

关于 DQL 和 SQL

DQL 和 SQL 语法比较相似. 具体可以参考: Doctrine Query Language DQL 在复杂的查询中使用.

我们用DQL语句再次重写上面的查询方法:

    /**
     * @param $price
     * @return Product[]
     */
    public function getAllGreaterThanPrice($price): array
    {

//        $qb = $this->createQueryBuilder('p')
//            ->andWhere('p.price > :price')
//            ->setParameter('price', $price)
//            ->orderBy('p.price', 'ASC')
//            ->getQuery();
//
//        return $qb->execute();

        $entityManager = $this->getEntityManager();
        $query = $entityManager->createQuery(
            'SELECT P FROM App\Entity\Product p WHERE p.price > :price ORDER BY p.price ASC'
        )->setParameter('price', $price);

        return $query->execute();
    }

用 SQL 来实现查询, SQL 查询返回的是数组, 非实体对象数组.

    /**
     * @param $price
     * @return array
     */
    public function getAllGreaterThanPrice($price): array
    {
        $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]);

        return $stmt->fetchAll();
    }

数据库的基本操作到此就有个大概的概念, 具体的API需要查阅 Doctrine 的文档, 非常的丰富.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,451评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,172评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,782评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,709评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,733评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,578评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,320评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,241评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,686评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,878评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,992评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,715评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,336评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,912评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,040评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,173评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,947评论 2 355

推荐阅读更多精彩内容

  • 一、数据库概述 什么是数据库数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户...
    圣贤与无赖阅读 3,857评论 0 4
  • 1.MySQL数据库 2.SQL语句 第一节课 ###1(MySQL数据库)数据库概念.avi 5...
    码了个农啵阅读 1,213评论 1 16
  • 特别说明: 1、本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识...
    安易学车阅读 1,814评论 0 40
  • 数据库编程概述、pymysql基本操作方法总结、参数化列表防止SQL注入总结 2.6 Python数据库编程 学习...
    Cestine阅读 1,530评论 0 2
  • 书籍:《好好学习》 《拆掉思维里的墙》,作者古典说过一句话,大意如此: 读书可能是改变你命运最好的机会,但你有没有...
    懒惰的妮子阅读 312评论 0 1