symfony2学习笔记(5)——数据库操作(增删改查)

一、配置数据库

二、创建和生成数据库表结构

三、从已有数据库生成Entity

四、保存数据到数据库

五、从数据库读取

六、更新记录

七、删除记录

八、工作笔记记录(可跳过):


Symfony和Doctrine进行了集成,Doctrine类库全部目标就是给你一个强大的工具,让你的工作更加容易。

Doctrine是完全解耦与Symfony的,所以并不一定要使用它。

一个简单例子:一个产品,我们首先来配置数据库,创建一个Product对象,添加到数据库并把它读回来。

首先,我们需要创建一个bundle:

$php app/console generate:bundle --namespace=Blog/StoreBundle

一、配置数据库

  在开始之前,首先需要配置数据库连接信息。根据惯例,这些信息通常会配置在app/config/parameters.yml 文件中。

#app/config/parameters.yml
# This file is auto-generated during the composer install
parameters:
    mailer_transport: smtp
    mailer_host: 127.0.0.1
    mailer_user: null
    mailer_password: null
    locale: zh_CN
    secret: 256d7de0d269e37752b49fec38f5fc5e
    debug_toolbar: true
    debug_redirects: false
    use_assetic_controller: true
    database_path: null
    assets_version: 0
    database_driver: pdo_mysql
    database_host: 127.0.0.1
    database_port: 3306
    database_name: symfony
    database_user: root
    database_password: 123

将配置信息定义到parameters.yml文件中也是一个常用的做法。定义在该文件中的配置信息将会被主配置文件在安装Doctrine时引用。

#app/config/doctrine.yml
            
# Doctrine Configuration
doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                driver:     "%database_driver%"
                host:       "%database_host%"
                port:       "%database_port%"
                user:       "%database_user%"
                password:   "%database_password%"
                charset:    UTF8
                dbname:     "%database_name%"
            
        # if using pdo_sqlite as your database driver, add the path in parameters.yml
        # e.g. database_path: "%kernel.root_dir%/data/data.db3"
        # path:     "%database_path%"
            
    orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        #auto_mapping: true
        entity_managers:
            default:
                connection: default
                mappings:
                    StoreBundle: ~

以上文件中dbal和orm中的default均可以复制后更改以实现多个数据库链接。

在config.yml中导入上面的两个yml配置文件:

#app/config/config.yml
            
imports:
    - { resource: parameters.yml }
    - { resource: doctrine.yml }
    - { resource: security.yml }

通过把数据库信息分离到一个特定的文件中,你可以很容易的为每个服务器保存不同的版本。现在Doctrine知道你的数据库配置了,你可以用它来创建一个数据库了。


二、创建和生成数据库表结构


(1)创建数据库

$php app/console doctrine:database:create —em=“default”

执行上面命令的时候可能会出现“[DoctrineDBALExceptionConnectionException]An exception occured in driver: SQLSTATE[HY000] [2002] No such file or directory ”的错误,将database_host由localhost改为127.0.0.1即可。


(2)通过entity生成数据库表结构

创建基础的Entity实体类:

  假设你创建一个应用程序,其中有些产品需要展示。即时不考虑Doctrine或者数据库,你也应该知道你需要一个Product对象来表现这些产品。在你的StoreBundle的Entity目录下创建一个实体类(Entity)。

// src/Blog/StoreBundle/Entity/Product.php
            
namespace Blog\StoreBundle\Entity;
            
class Product
{
    protected $name;
    protected $price;
    protected $description;
}

  这样的类经常被称为“Entity”,把表中的字段映射到该类。不过现在它还不能被保存到数据库中,因为现在它只不过还是个简单的PHP类。一旦你学习了Doctrine背后的概念,你可以让Doctrine来为你创建实体类。

       创建完整的Entity实体类:

php app/console doctrine:generate:entity --entity="StoreBundle:Product" --fields="name:string(255) price:float description:text" --with-repository
// src/Blog/StoreBundle/Entity/Product.php
            
<?php
            
namespace Blog\StoreBundle\Entity;
            
use DoctrineORMMapping as ORM;
            
/**
 * Product
 *
 * @ORMTable()
 * @ORMEntity(repositoryClass="BlogStoreBundleEntityProductRepository")
 */
class Product
{
    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;
            
    /**
     * @var string
     *
     * @ORMColumn(name="name", type="string", length=255)
     */
    private $name;
            
    /**
     * @var float
     *
     * @ORMColumn(name="price", type="float")
     */
    private $price;
            
    /**
     * @var string
     *
     * @ORMColumn(name="description", type="text")
     */
    private $description;
            
            
    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }
            
    /**
     * Set name
     *
     * @param string $name
     * @return Product
     */
    public function setName($name)
    {
        $this->name = $name;
            
        return $this;
    }
            
    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }
            
    /**
     * Set price
     *
     * @param float $price
     * @return Product
     */
    public function setPrice($price)
    {
        $this->price = $price;
            
        return $this;
    }
            
    /**
     * Get price
     *
     * @return float 
     */
    public function getPrice()
    {
        return $this->price;
    }
            
    /**
     * Set description
     *
     * @param string $description
     * @return Product
     */
    public function setDescription($description)
    {
        $this->description = $description;
            
        return $this;
    }
            
    /**
     * Get description
     *
     * @return string 
     */
    public function getDescription()
    {
        return $this->description;
    }
}

根据Entity生成数据库:

php app/console doctrine:schema:update --force --em="default"

看到如下提示即为成功:

Updating database schema...

Database schema updated successfully! "1" queries were executed


三、从已有数据库生成Entity

#生成Entity基础字段:
php app/console doctrine:mapping:import --force StoreBundle annotation
#根据数据库结构生成Product表的Entity
app/console doctrine:mapping:import --em="default" StoreBundle --filter=Product annotation 
#生成get/set方法:
php app/console doctrine:generate:entities BlogStoreBundle

注意:
(1)--em="default"中的default是指connection,对应第一步配置数据库信息(doctrine.yml)中的default

(2)--filter=Product 这里的P是大写的,它的规则跟生成的类名是一致的(采用驼峰型)

例如:

表名: article             --filter=Article
表名:test_article         --filter=TestArticle
表名:test_article_detail  --filter=TestArticleDetail

四、保存数据到数据库

// src/Blog/TestBundle/Controller/DefaultController.php
            
// ...
use Blog\StoreBundle\Entity\Product;
            
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
            
// ...
public function createAction()
{
    $product = new Product();
    $product->setName('A Foo Bar');
    $product->setPrice('19.99');
    $product->setDescription('Lorem ipsum dolor');
            
    $em = $this->getDoctrine()->getManager();
            
    $em->persist($product);
    $em->flush();
            
    return new Response('Created product id '.$product->getId());
}

配置路由:

#src/Blog/TestBundle/Resources/config/routing.yml
            
test_create:
    path:     /test/create
    defaults: { _controller: TestBundle:Default:create }


五、从数据库读取


public function showAction($id)
{
       $product = $this->getDoctrine()
                 ->getRepository('AcmeStoreBundle:Product')
                 ->find($id);
        if(!$product){
             throw $this->createNotFoundException('No product found for id ' .$id);
        }
       //do something,想把$product对象传递给一个template等。
}

配置路由:

#src/Blog/TestBundle/Resources/config/routing.yml
            
test_show:
    path:     /show/{id}
    defaults: { _controller: TestBundle:Default:show }


其他查询方式可参考:Symfony2 Doctrine 数据库查询方法总结


六、更新记录

public function updateAction($id)
{
    $em = $this->getDoctrine()->getEntityManager();
    $product = $em->getRepository('AcmeStoreBundle:Product')->find($id);
            
    if (!$product) {
        throw $this->createNotFoundException('No product found for id '.$id);
    }
            
    $product->setName('New product name!');
    $em->flush();
            
    return $this->redirect($this->generateUrl('homepage'));
}

更新记录仅需要三步:

1. 从Doctrine找到对象

2. 修改这个对象

3. 调用entity manager的flush函数

注意:

$em->persist($product)没有必要,这个方法仅仅是要告诉Doctrine去管理或者观看$product对象,当你从Doctrine中找到了$product对象,它已经被管理了。

Notice that calling $em->persist($product) isn't necessary. Recall that this method simply tells

Doctrine to manage or "watch" the $product object. In this case, since you fetched the $product object

from Doctrine, it's already managed.


七、删除记录

$em->remove($product);
$em->flush();


八、工作笔记记录(可跳过):

1. 增加记录:

     1.1 单表增加

use Acme\StoreBundle\Entity\Product;
             
public function createAction()
{
    $product = new Product();
    $product->setName('A Foo Bar');
    $product->setPrice('19.99');
    $product->setDescription('Lorem ipsum dolor');
    $em = $this->getDoctrine()->getManager();
    $em->persist($product);
    $em->flush();
    return new Response('Created product id '.$product->getId());
}

     1.2 多表增加

use Acme\StoreBundle\Entity\Category;
use Acme\StoreBundle\Entity\Product;
             
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
    public function createProductAction()
    {
        $category = new Category();
        $category->setName('Main Products');
        $product = new Product();
        $product->setName('Foo');
        $product->setPrice(19.99);
        // relate this product to the category
        $product->setCategory($category);
        $em = $this->getDoctrine()->getManager();
        $em->persist($category);
        $em->persist($product);
        $em->flush();
        return new Response(
        'Created product id: '.$product->getId()
        .' and category id: '.$category->getId()
        );
    }
}

     1.3 批量插入函数

/**
* 单词首字母大写(用于set函数)
*
* @author wyl
* @param string $str
* @return string
*/
function ucWords($str)
{
    $str = ucwords(str_replace('_', ' ', $str));
    $str = str_replace(' ', '', $str);
    return $str;
}
             
/**
* 批量写入数据
*
* @author wyl
* @param string $entity
* @param array $dataList
* @param array $per
*/
function batchInsertByEntity($entity, $dataList, $per = 1000)
{
    $count = count($dataList);
    for ($i = 0; $i < $count; $i ++) {
        $obj = new $entity();
        foreach ($dataList[$i] as $k => $v) {
        $obj->{"set" . $this->ucWords($k)}($v);
        }
        $this->em->persist($obj);
        if (($count % $per) === 0) {
        $this->em->flush();
        $this->em->clear();
        }
    }
    // 除不尽剩下的还是要保存的
    $this->em->flush();
    $this->em->clear();
}

(2)删除记录:

public function deleteAction($id)
{
    $em = $this->getDoctrine()->getManager();
    $product = $em->getRepository('AcmeStoreBundle:Product')->find($id);
             
    if (!$product) {
        throw $this->createNotFoundException(
        'No product found for id '.$id
        );
    }
             
    $em->remove($product);  //注意:此处是remove函数
    $em->flush();
    return $this->redirect($this->generateUrl('homepage'));
}

(3)查询记录:

参看这篇文章:Symfony2 Doctrine 数据库查询方法总结


by 雪洁 2015-03-10 02:49:44 7613 views
我来说几句

相关文章