symfony3.4文档

控制器

一个简单的控制器示例

// src/AppBundle/Controller/LuckyController.php
namespace AppBundle\Controller;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class LuckyController
{
    /**
     * @Route("/lucky/number/{max}")
     */
    public function numberAction($max)
    {
        $number = random_int(0, $max);

        return new Response(
            '<html><body>Lucky number: '.$number.'</body></html>'
        );
    }
}


注释路由

 	/**
     * @Route("/lucky/number/{max}")
     */
   

浏览器访问路由地址:http:// localhost:8000/lucky/number/100

生成URL

$url = $this->generateUrl('blog_show', ['slug' => 'slug-value']);

重定向

如果要将用户重定向到另一个页面,请使用redirectToRoute() 和redirect()方法:

public function indexAction()
{
    // redirects to the "homepage" route
    return $this->redirectToRoute('homepage');

    // does a permanent - 301 redirect
    return $this->redirectToRoute('homepage', [], 301);

    // redirects to a route with parameters
    return $this->redirectToRoute('blog_show', ['slug' => 'my-page']);

    // redirects to a route and maintains the original query string parameters
    return $this->redirectToRoute('blog_show', $request->query->all());

    // redirects externally
    return $this->redirect('http://symfony.com/doc');
}

渲染模板

如果要提供HTML,则需要呈现一个模板。该render() 方法呈现一个模板,并将该内容放入Response 您的对象中:

// renders app/Resources/views/lucky/number.html.twig
return $this->render('lucky/number.html.twig', ['number' => $number]);

模板也可以存在于更深的子目录中。只是尝试避免创建不必要的深层结构:

// renders app/Resources/views/lottery/lucky/number.html.twig
return $this->render('lottery/lucky/number.html.twig', [
    'number' => $number,
]);

获取服务作为控制器参数

Symfony 3.3中引入了提示控制器参数以接收服务的功能。

如果您需要控制器中的服务,则只需键入一个带有其类(或接口)名称的参数即可。Symfony会自动为您提供所需的服务:

use Psr\Log\LoggerInterface;
// ...

/**
 * @Route("/lucky/number/{max}")
 */
public function numberAction($max, LoggerInterface $logger)
{
    $logger->info('We are logging!');
    // ...
}

直接访问服务

如果扩展基Controller类,则可以通过get() 方法访问任何Symfony服务。以下是您可能需要的几种常见服务:

$templating = $this->get('templating');

$router = $this->get('router');

$mailer = $this->get('mailer');

// you can also fetch parameters
$someParameter = $this->getParameter('some_parameter');

管理错误和404页面

如果找不到任何内容,则应该使用HTTP协议,并返回404响应。为此,您将抛出一种特殊类型的异常。如果要扩展Controller基AbstractController 类或基类,请执行以下操作:

public function indexAction()
{
    // retrieve the object from database
    $product = ...;
    if (!$product) {
        throw $this->createNotFoundException('The product does not exist');
    }

    return $this->render(...);
}

自定义错误页面

https://symfony.com/doc/3.4/controller/error_pages.html

会话:session的设置和获取

use Symfony\Component\HttpFoundation\Session\SessionInterface;

public function indexAction(SessionInterface $session)
{
    // stores an attribute for reuse during a later user request
    $session->set('foo', 'bar');

    // gets the attribute set by another controller in another request
    $foobar = $session->get('foobar');

    // uses a default value if the attribute doesn't exist
    $filters = $session->get('filters', []);
}

请求

use Symfony\Component\HttpFoundation\Request;

public function indexAction(Request $request)
{
    $request->isXmlHttpRequest(); // is it an Ajax request?

    $request->getPreferredLanguage(['en', 'fr']);

    // retrieves GET and POST variables respectively
    $request->query->get('page');
    $request->request->get('page');

    // retrieves SERVER variables
    $request->server->get('HTTP_HOST');

    // retrieves an instance of UploadedFile identified by foo
    $request->files->get('foo');

    // retrieves a COOKIE value
    $request->cookies->get('PHPSESSID');

    // retrieves an HTTP request header, with normalized, lowercase keys
    $request->headers->get('host');
    $request->headers->get('content-type');
}

Flash消息

您还可以在用户的​​会话中存储特殊消息,称为“即时消息”。按照设计,即时消息应仅使用一次:一旦您检索它们,它们就会自动从会话中消失。此功能使“刷新”消息特别适合存储用户通知。
例如,假设您正在处理 表单内容 提交:

处理完请求后,控制器在会话中设置一条Flash消息,然后进行重定向。
use Symfony\Component\HttpFoundation\Request;

public function updateAction(Request $request)
{
    // ...

    if ($form->isSubmitted() && $form->isValid()) {
        // do some sort of processing

        $this->addFlash(
            'notice',
            'Your changes were saved!'
        );
        // $this->addFlash() is equivalent to $request->getSession()->getFlashBag()->add()

        return $this->redirectToRoute(...);
    }

    return $this->render(...);
}

然后,在模板中(或者甚至更好的是,在您的基本布局模板中),使用app.flashes() 命令从会话中读取所有Flash消息:

3.3版的新功能:该app.flashes()枝条函数,Symfony的3.3推出。在此之前,您必须使用app.session.flashBag()。

{# app/Resources/views/base.html.twig #}

{# read and display just one flash message type #}
{% for message in app.flashes('notice') %}
    <div class="flash-notice">
        {{ message }}
    </div>
{% endfor %}

{# read and display several types of flash messages #}
{% for label, messages in app.flashes(['success', 'warning']) %}
    {% for message in messages %}
        <div class="flash-{{ label }}">
            {{ message }}
        </div>
    {% endfor %}
{% endfor %}

{# read and display all flash messages #}
{% for label, messages in app.flashes %}
    {% for message in messages %}
        <div class="flash-{{ label }}">
            {{ message }}
        </div>
    {% endfor %}
{% endfor %}

JSON助手

要从控制器返回JSON,请json()在基本控制器上使用helper方法。这将返回一个特殊的JsonResponse对象,该对象会自动对数据进行编码:

// ...
public function indexAction()
{
    // returns '{"username":"jane.doe"}' and sets the proper Content-Type header
    return $this->json(['username' => 'jane.doe']);

    // the shortcut defines three optional arguments
    // return $this->json($data, $status = 200, $headers = [], $context = []);
}

文件助手

可以使用file() 帮助程序从控制器内部提供文件:

public function fileAction()
{
    // send the file contents and force the browser to download it
    return $this->file('/path/to/some_file.pdf');
}

该file()助手提供一些参数来配置它的行为:

use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

public function fileAction()
{
    // load the file from the filesystem
    $file = new File('/path/to/some_file.pdf');

    return $this->file($file);

    // rename the downloaded file
    return $this->file($file, 'custom_name.pdf');

    // display the file contents in the browser instead of downloading it
    return $this->file('invoice_3241.pdf', 'my_invoice.pdf', ResponseHeaderBag::DISPOSITION_INLINE);
}

模板

layout布局:模板继承和布局

链接到页面

要链接到该页面,只需使用path()Twig功能并参考以下路线:

<a href="{{ path('welcome') }}">Home</a>

链接资源(js,css,image等静态资源)

<img src="{{ asset('images/logo.png') }}" alt="Symfony!"/>

<link href="{{ asset('css/blog.css') }}" rel="stylesheet"/>

如果您需要资源的绝对URL,请absolute_url()按以下方式使用Twig函数:

<img src="{{ absolute_url(asset('images/logo.png')) }}" alt="Symfony!"/>

链接css和js

通过app变量访问Twig中的用户,请求,会话等

应用场景: 可以用来实现在模板中判断用户是否登录的状态

表单

数据库 ORM

配置数据库

在真正开始之前,您需要配置数据库连接信息。按照约定,此信息通常在app/config/parameters.yml文件中配置 :

# app/config/parameters.yml
parameters:
    database_host:     localhost
    database_name:     test_project
    database_user:     root
    database_password: password

# ...

您还可以更改Doctrine的默认值,以便生成的SQL使用正确的字符集。

# app/config/config.yml
doctrine:
    dbal:
        charset: utf8mb4
        default_table_options:
            charset: utf8mb4
            collate: utf8mb4_unicode_ci

创建实体类

假设您正在构建一个需要显示产品的应用程序。甚至不用考虑Doctrine或数据库,您就已经知道需要一个Product对象来表示那些产品。在Entity您的AppBundle目录中创建此类:

// src/AppBundle/Entity/Product.php
namespace AppBundle\Entity;

/**
 * @IgnoreAnnotation("fn")
 */
class Product
{
    private $id;
    private $name;
    private $price;
    private $description;


}

添加映射信息

使用Doctrine,您可以以比将标量数据的行读取到数组中更有趣的方式使用数据库。取而代之的是,Doctrine允许您从数据库中提取整个对象,并将整个对象持久化到数据库中。为了使Doctrine能够做到这一点,您必须将数据库表映射到特定的PHP类,并且这些表上的列必须映射到其相应的PHP类上的特定属性。

以以多种不同的格式(包括YAML,XML)或Product通过DocBlock批注直接在类内部指定此元数据:

# src/AppBundle/Resources/config/doctrine/Product.orm.yml
AppBundle\Entity\Product:
    type: entity
    table: product
    id:
        id:
            type: integer
            generator: { strategy: AUTO }
    fields:
        name:
            type: string
            length: 100
        price:
            type: decimal
            scale: 2
        description:
            type: text

验证映射命令: 根据错误提示进行修改配置

php bin/console doctrine:schema:validate

实体类生成数据表

php bin/console doctrine:schema:update --force

将对象持久化到数据库中

既然您已将Product实体映射到其对应的product 表,就可以将Product对象持久保存到数据库了。从控制器内部,这非常容易。将以下方法添加到 DefaultController包的中:

// src/AppBundle/Controller/DefaultController.php

// ...
use AppBundle\Entity\Product;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Response;

public function createAction()
{
    // you can fetch the EntityManager via $this->getDoctrine()
    // or you can add an argument to your action: createAction(EntityManagerInterface $entityManager)
    $entityManager = $this->getDoctrine()->getManager();

    $product = new Product();
    $product->setName('Keyboard');
    $product->setPrice(19.99);
    $product->setDescription('Ergonomic and stylish!');

    // tells Doctrine you want to (eventually) save the Product (no queries yet)
    $entityManager->persist($product);

    // actually executes the queries (i.e. the INSERT query)
    $entityManager->flush();

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

// if you have multiple entity managers, use the registry to fetch them
public function editAction()
{
    $doctrine = $this->getDoctrine();
    $entityManager = $doctrine->getManager();
    $otherEntityManager = $doctrine->getManager('other_connection');
}


t h i s − > g e t D o c t r i n e ( ) − > g e t M a n a g e r ( ) 方 法 获 取 D o c t r i n e 的 实 体 管 理 器 对 象 , 这 是 D o c t r i n e 中 最 重 要 的 对 象 。 它 负 责 将 对 象 保 存 到 数 据 库 并 从 数 据 库 中 获 取 对 象 。 您 将 this->getDoctrine()->getManager()方法获取Doctrine的 实体管理器对象,这是Doctrine中最重要的对象。它负责将对象保存到数据库并从数据库中获取对象。 您将 this>getDoctrine()>getManager()DoctrineDoctrineproduct 像其他任何普通的PHP对象一样实例化并使用该对象。
该persist( p r o d u c t ) 调 用 告 诉 D o c t r i n e 对 product)调用告诉Doctrine对 product)Doctrineproduct对象进行“管理” 。这并不会导致查询到数据库中进行。
flush()调用该方法时,Doctrine会浏览它正在管理的所有对象,以查看是否需要将它们持久化到数据库中。在此示例中,$product对象的数据在数据库中不存在,因此实体管理器执行INSERT查询,并在product表中创建新行。

事务和并发

从数据库中获取对象

从数据库中取回对象更加容易。例如,假设您已经配置了一条路由,以Product根据其id值显示特定的路由:

public function showAction($productId)
{
    $product = $this->getDoctrine()
        ->getRepository(Product::class)
        ->find($productId);

    if (!$product) {
        throw $this->createNotFoundException(
            'No product found for id '.$productId
        );
    }

    // ... do something, like pass the $product object into a template
}

一旦有了存储库对象,就可以访问各种有用的方法:

$repository = $this->getDoctrine()->getRepository(Product::class);

// looks for a single product by its primary key (usually "id")
$product = $repository->find($productId);

// dynamic method names to find a single product based on a column value
$product = $repository->findOneById($productId);
$product = $repository->findOneByName('Keyboard');

// dynamic method names to find a group of products based on a column value
$products = $repository->findByPrice(19.99);

// finds *all* products
$products = $repository->findAll();

使用 findBy()和findOneBy() 方法 多条件获取对象
$repository = $this->getDoctrine()->getRepository(Product::class);

// looks for a single product matching the given name and price
//查找与给定名称和价格匹配的单个产品
$product = $repository->findOneBy([
    'name' => 'Keyboard',
    'price' => 19.99
]);

// looks for multiple products matching the given name, ordered by price
//按价格查找与给定名称匹配的多个产品
$products = $repository->findBy(
    ['name' => 'Keyboard'],
    ['price' => 'ASC']
);

更新对象

从Doctrine获取对象后,对其进行更新就很容易。假设您有一条将产品ID映射到控制器中的更新操作的路由:

use AppBundle\Entity\Product;
// ...

public function updateAction($productId)
{
    $entityManager = $this->getDoctrine()->getManager();
    $product = $entityManager->getRepository(Product::class)->find($productId);

    if (!$product) {
        throw $this->createNotFoundException(
            'No product found for id '.$productId
        );
    }

    $product->setName('New product name!');
    $entityManager->flush();

    return $this->redirectToRoute('homepage');
}

删除对象

删除对象非常相似,但是需要调用remove() 实体管理器的方法:

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

如您所料,该remove()方法通知Doctrine您要从数据库中删除给定的对象。DELETE但是,直到flush()调用该方法后,才实际执行实际查询。

查询对象

您已经了解了存储库对象如何使您无需任何工作即可运行基本查询:

$repository = $this->getDoctrine()->getRepository(Product::class);

$product = $repository->find($productId);
$product = $repository->findOneByName('Keyboard');

使用Doctrine,您还可以使用Doctrine查询语言(DQL)编写更复杂的查询。DQL与SQL相似,不同之处在于,您应该想象自己正在查询实体类的一个或多个对象(例如Product),而不是查询表中的行(例如product)。

在Doctrine中进行查询时,您有两个主要选择:编写纯DQL查询或使用Doctrine的查询生成器。

用DQL查询对象

假设您要查询价格超过的产品(价格19.99从最低到最贵)。您可以使用Doctl(Doctrine的类似SQL的本地语言)来为这种情况构造查询:

$query = $entityManager->createQuery(
    'SELECT p
    FROM AppBundle:Product p
    WHERE p.price > :price
    ORDER BY p.price ASC'
)->setParameter('price', 19.99);

$products = $query->getResult();

SQL和DQL的区别: 最大的区别是您需要考虑选择PHP对象而不是数据库中的行。
出于这个原因,你选择从该
AppBundle:Product 实体(为一个可选的快捷方式 AppBundle\Entity\Product类),然后别名它p。

setParameter() 方法使用Doctrine时,最好将任何外部值设置为“占位符”(:price在上面的示例中),因为它可以防止SQL注入攻击

getResult() 方法返回结果数组。要仅获得一个结果,可以使用getOneOrNullResult():

$product = $query->setMaxResults(1)->getOneOrNullResult();
更多 官方的 Doctrine Query Language文档

查询使用Doctrine的查询生成器对象

除了编写DQL字符串,您可以使用一个名为的有用对象 QueryBuilder为您构建该字符串。当实际查询取决于动态条件时,这很有用,因为随着您开始连接字符串,您的代码很快将变得难以用DQL读取:

$repository = $this->getDoctrine()
    ->getRepository(Product::class);

// createQueryBuilder() automatically selects FROM AppBundle:Product
// and aliases it to "p"
$query = $repository->createQueryBuilder('p')
    ->where('p.price > :price')
    ->setParameter('price', '19.99')
    ->orderBy('p.price', 'ASC')
    ->getQuery();

$products = $query->getResult();
// to get just one result:
// $product = $query->setMaxResults(1)->getOneOrNullResult();

该QueryBuilder对象包含构建查询所需的所有方法。通过调用该getQuery()方法,查询构建器将返回一个普通Query对象,该对象可用于获取查询结果。

有关Doctrine的查询生成器的更多信息,请查阅Doctrine的 查询生成器文档。

Doctrine的 查询生成器文档

如何创建自定义存储库类

该篇博客主要参考symfony3.4版本的官方文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值