1.安装 composer
切换到项目要安装的目录 composer -v
composer create-project symfony/framework-standard-edition project
指定版本
composer create-project symfony/framework-standard-edition project "3.4.2"
遇到错误 Failed opening required 'D:\www\symfony\project
\web/../vendor/autoload.php'
说明没有安装依赖 可以1.composer -vvv 2.compser update
2.入口文件
入口文件是 web/app.php 开发模式需要修改该里面$kernel = new AppKernel('dev',
true);app.dev.php为开发入口文件 需要域名加上这个文件名
3.路由
配置文件 在routing.yml
app:
resource: '@AppBundle/Controller/'
type: annotation
类型为annotation 为注释路由
/**
* @Route("/lucky/number") 括号里必须是双引号
*/
numberAction——被称为控制器,这是你控制页面的地方。此处唯一的原则是:一个控制器
必须返回一个Symfony的Response对象
(1)return new Response(
'Lucky number: '.$number.''
);
(2)返回json格式:
$data = array(
'lucky_number' => rand(0, 100),
);
// 自动调用json_encode并设置Content-Type头
return new JsonResponse($data);
(3)动态URL匹配:/lucky/number/{count}
/**
* @Route("/lucky/number/{count}")
*/
public function numberAction($count){}
可以访问http://www.symfony.com/lucky/number/5
要确保占位符的名字一致 {count}和 $count
支持多个占位符(比如/blog/{category}/{page})
要确保占位符的名字一致
@Route("/blog/{page}", name="blog_list", requirements={"page": "\d+"})
url 格式为/blog/{page} 匹配blog控制器下的listAction方法 并且占位符必须为数字的情况下 才匹配此方法 如果想要url为/blog 也能访问 需要给一个默认值 public function listAction($page = 1)
(4)根据理由生成url
public function numberAction($count)
{
$url = $this->generateUrl(
'lucky_number',
array('count' => '2')
);
return new Response("
}//lucky/number/2
生成绝对路径的url
$url = $this->generateUrl(
'lucky_number',
array('count' => '2'),
UrlGeneratorInterface::ABSOLUTE_URL//加上这个参数
);
要加上 use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
//http://www.symfony.com/lucky/number/2
生成带有Query字符串的URL
$url = $this->get('router')->generate(
'lucky_number',
array('count' => '2','name'=>'shiyan')
);
///lucky/number/2?name=shiyan
4.渲染模板(利用容器)
引用Twig(或其他Symfony工具)最简单的方式,就是继承Symfony的Controller基类:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class LuckyController extends Controller{}
使用templating服务
$html = $this->container->get('templating')->render(
'lucky/number.html.twig',
array('luckyNumberList' => $numbersList)
);
return new Response($html);
通过继承Controller基类,你可以使用很多快捷方法
return$this->render('lucky/number.html.twig',array('luckyNumberList'=>$numbersList));
注意渲染的时候要加上文件夹名称 lucky/number.html.twig
创建模板 创建一个新的app/Resources/views/lucky目录,再将number.html.twig置于其中
{% extends "base.html.twig" %}
{% block body %}
{% endblock %}
5.控制器
重定向 默认情况下,redirectToRoute()方法执行302(临时)重定向。如果要执行301(永久)重定向,请修改第2个参数:
return $this->redirectToRoute('homepage', array(), 301);
从定向到外部网站,使用redirect()并传入外部URL:
public function indexAction()
{
return $this->redirect('http://symfony.com/doc');
}
(2)管理Session
use Symfony\Component\HttpFoundation\Request;
public function indexAction(Request $request)
{
$session = $request->getSession();
// store an attribute for reuse during a later user request
$session->set('foo', 'bar');
// get the attribute set by another controller in another request
$foobar = $session->get('foobar');
// use a default value if the attribute doesn't exist
$filters = $session->get('filters', array());
}
JSON
控制器基类定义了json()方法,来创建一个JsonResponse 并自动编码给定的内容:
public function indexAction()
{
return $this->json(array('username' => 'jane.doe'));
}
模板引擎 TWIG
(1)引入其他模版
{# app/Resources/views/article/article_details.html.twig #}
{{ article.body }}
{# app/Resources/views/article/list.html.twig #}
{% extends 'layout.html.twig' %}
{% block body %}
{% for article in articles %}
{{ include('article/article_details.html.twig', { 'article': article }) }}
{% endfor %}
{% endblock %}
使用了 {{ include() }} 标签
{'article':article} 语法是标准Twig哈希映射(hash maps)的写法(即是一个键值对数组)。如果你需要传递多个元素,可以写成 {'foo': foo, 'bar': bar}。
(2) 链接到页面
class ArticleController extends Controller
{
/**
* @Route("/article/{slug}", name="article_show")
*/
public function showAction($slug)
{
// ...
}
}
{% for article in articles %}
{{ article.title }}
{% endfor %}
你可以通过Twig的 url 函数来生成绝对路径:
(3)链接到Assets
如果你需要assets资源的绝对URL,可以使用 absolute_url() Twig函数:
(4)输出转义
{{ description }}
{{ description|raw }}
数据库操作
配置数据库 app/config/parameters.yml
根目录下创建数据库 php bin/console doctrine:database:create
设置数据库的字符集
# app/config/config.yml
doctrine:
dbal:
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
创建实体Entity类
namespace AppBundle\Entity;
//引入映射
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="product")
* @package AppBundle\Entity
*/
class Product
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string", length=100)
*
*/
private $name;
使用此命令验证映射
php bin/console doctrine:schema:validate
生成简单的生成Getters和Setters
php bin/console doctrine:generate:entities AppBundle/Entity/Product
根据包含映射信息的类生成数据表
php bin/console doctrine:schema:update --force //--force强制生成
持久化对象到数据库
向bundle的 DefaultController 添加以下方法:
/**
* @Route("default/create")
*/
public function createAction()
{
$product = new Product();
//设置值
$product -> setName('lhz');
$product -> setPrice('88.2');
$product -> setDescription('你哈');
//取出 doctrine 服务的快捷方法
$em = $this->getDoctrine()->getManager();
// 告诉Doctrine你希望(最终)存储Product对象(还没有语句执行)
//persist($product) 调用,告诉Doctrine去 "管理" $product 对象。它 没有 引发对数据库的请求。
$em->persist($product);
// 真正执行语句(如,INSERT 查询)
$em->flush();
return new Response('保存数据到product表,生成id '.$product->getId());
}
访问路由 结果//保存数据到product表,生成id 1
从数据库中获取对象 返回的都是对象
$repository = $this->getDoctrine()->getRepository('AppBundle:Product');
// query for a single product by its primary key (usually "id")
// 通过主键(通常是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);
// find *all* products / 查出 *全部* 产品
$products = $repository->findAll();
// 查询一件产品,要匹配给定的名称和价格
$product = $repository->findOneBy(
array('name' => 'Keyboard', 'price' => 19.99)
);
// query for multiple products matching the given name, ordered by price
// 查询多件产品,要匹配给定的名称和价格
$products = $repository->findBy(
array('name' => 'Keyboard'),
array('price' => 'ASC')
);
实例:php
/**
*@Route("default/getonedata/{productId}")
*/
public function getOneData($productId)
{
$repository = $this->getDoctrine()->getRepository('AppBundle:Product');
//得到的都是对象
$product = $repository->findAll();
$data = array(
'product'=>$product
);
return $this->render('default/product.html.twig', $data);
}
html:
{% extends "base.html.twig" %}
{% block body %}
{% for item in product %}
{% endfor %}
{% endblock %}
结果:lucky numberlhz1
lucky numberlhz2
对象更新
/**
* @Route("default/update/{productId}")
*/
public function updateAction($productId)
{
$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('AppBundle:Product')->find($productId);
if (!$product) {
throw $this->createNotFoundException(
'No product found for id '.$productId
);
}
更新一个对象包括三步:
从Doctrine中取出对象;
修改对象;
调用entity manager的 flush() 方法
删除对象 ¶
删除一个对象十分类似,但需要从entity manager调用 remove() 方法:
/**
* @Route("default/delete/{productId}")
*/
public function deleteAction($productId)
{
$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('AppBundle:Product')->find($productId);
if (!$product) {
throw $this->createNotFoundException(
'No product found for id '.$productId
);
}
$em->remove($product);
$em->flush();
使用DQL进行对象查询
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'SELECT p
FROM AppBundle:Product p'
);
$product = $query->getResult();
$array = array(
'product'=>$product
);
return $this->render('default/product.html.twig', $array);
假设你要查询价格高于 19.99 的产品,并且按价格从低到高排列。你可以使用DQL,Doctrine中类似原生SQL的语法,来构造一个用于此场景的查询:
1 2 3 4 5 6 7 8 9 |
$em=$this->getDoctrine()->getManager();$query=$em->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也会非常自然。它们之间最大的不同就是你需要就“select PHP对象”来进行思考,而不是数据表的行。正因为如此,你要 从 AppBundle:Product 这个 entity (可选的一个AppBundle\Entity\Product 类的快捷写法)来select,然后给entity一个 p 的别名。
TIP
注意 setParameter() 方法。当使用Doctrine时,通过“占位符”来设置任意的外部值(上面例子的 :price),是一个好办法,因为它可以防止SQL注入攻击。
getResult() 方法返回一个结果数组。要得到一个结果,可以使用getSingleResult()(这个方法在没有结果时会抛出一个异常)或者 getOneOrNullResult() :
1 |
$product=$query->setMaxResults(1)->getOneOrNullResult(); |
DQL语法强大到令人难以置信,允许轻松地在entity之间进行join(稍后会覆盖relations)和group等。参考 Doctrine Query Language 文档以了解更多。
使用Doctrine's Query Builder进行对象查询 ¶
不去写DQL的大字符串,你可以使用一个非常有用的QueryBuilder对象,来构建那个字符串。当你的查询取决于动态条件时,这很有用,因为随着你的连接字符串不断增加,DQL代码会越来越难以阅读:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$repository=$this->getDoctrine()->getRepository('AppBundle:Product'); // createQueryBuilder() automatically selects FROM AppBundle:Product// and aliases it to "p"// createQueryBuilder() 自动从 AppBundle:Product 进行 select 并赋予 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 builder将返回一个标准的Query对象,可用于取得请求的结果集。