昨天我们已经创建好了新闻的首页。今天我们来实现添加新闻并且显示新闻的功能,并且学会使用 Composer 添加第三方 Bundle 来加速开发。
2020-04-12 补充:已经发布对应的 Symfony 5 精简版教程,建议对比观看。
创建业务数据模型
新闻数据算是我们业务模型里必不可少的模型之一。根据我们之前对需求的分析,我们可以很容易想到,新闻模型News
需要的属性:
- 标题属性
- 文本属性
接下来,我们要在 AppBundle 里创建它,但是这些数据还需要一个持久层来保存数据,例如之前配置的 Mysql。目前流行的开发方式,无论是 Java 还是 ROR,都会使用 ORM 将数据库字段和类属性关联起来。
Symfony 框架本身并不包含 ORM 工具(严格意义上来说,Symfony 框架,即 FrameworkBundle,不包含 ORM,安全组件,模板引擎,日志工具,邮件组件等一系列工具),只不过 Symfony installer 将一些推荐的,Web 开发常用的工具,都默认安装了。如果你已经知道如何用 Mysql 来存储/获取数据,也不一定非要用 ORM。这里我们为了快速开发,也为了省一些精力,就使用默认提供的 Doctrine2 ORM,它会给我们的开发带来许多便利。
决定了使用 Doctrine2,我们除了定义好 News
类,还需要写配置文件,让 Doctrine2 ORM 将 News
类同数据库某个表关联起来。听起来要做的工作不少,不过且慢,DoctrineBundle 里自带的代码生成工具能让我们的开发再快一点点:
php app/console doctrine:generate:entity
此时会有欢迎提示出现,并且让你输入一个模型的“短名字”,为什么说是要输入短名字?News
并不是全名,全名应该是包含命名空间的,比如我们的 News
全名应该是 AppBundle\Entity\News
,Entity 是什么?Entity 只是一个习惯性叫法。在 Doctrine2 的世界里,只要是 ORM 过的模型,都叫 Entity(除此之外还有用 MongoDB 作为存储方案的 ODM,ODM 过的模型习惯称之为 Document)。
后面我们就按照他们的提示,分别输入:
The Entity shortcut name: AppBundle:News
Configuration format (yml, xml, php, or annotation) [annotation]: #这里直接回车确认就好
New field name (press <return> to stop adding fields): title
Field type [string]: #直接回车
Field length [255]: 70 #这里我们很明确只需要70的长度
New field name (press <return> to stop adding fields): body
Field type [string]: text
New field name (press <return> to stop adding fields): #直接回车停止添加字段
Do you want to generate an empty repository class [no]? yes 是否创建新闻仓库类,这里我们先yes,之后解释
Do you confirm generation [yes]? #回车完成代码生成
刷新 src/AppBundle
目录,多了一个 Entity 目录,此目录包含了两个文件:News.php
和 NewsRepository.php
。
打开 News.php
我们可以看到,News
类已经生成好了,并且还有用注解格式写的 ORM 配置。我的建议是可以用生成代码工具尽量用,一是快,二是不容易写错字。
此时,我们就可以用 DoctrineBundle
的数据库操作工具来生成数据的数据库和表了:
php app/console doctrine:database:create
php app/console doctrine:schema:create
数据库创建好之后,我们应该创建“新建新闻”页和“新闻详情”页、以及更新我们之前写的“新闻首页”。不过且慢,DoctrineBundle 不仅仅能生成 Entity,它还能根据 Entity 直接生成相关的 Controller!这里我们先把之前的 NewsController
类文件删掉。然后使用下面命令:
php app/console doctrine:generate:crud
如同之前的命令,我们只用回答它的问题就行了:
The Entity shortcut name: AppBundle:News
Do you want to generate the "write" actions [no]? yes
Configuration format (yml, xml, php, or annotation) [annotation]:
Routes prefix [/news]:
Do you confirm generation [yes]?
我们会发现,被删除的 NewsController
又被重新生成,并且多了好多代码。先不管每个控制器方法里写了啥,我们先检查路由配置。我们会发现,一切都很好,除了首页的路由名字从以前的 news_index
变成了 news
,此时我们可以将 news
改回 news_index
,也可以考虑将之前的 news_index
定为 news
。我们这里选择后者,毕竟已经为我们定义了一套规则,并且也不赖,何必再去折腾别的命名方式?还好代码也不多,目前我们只用把首页模板 default/index.html.twig
里的 news_index
改成 news
就行了。
doctrine:genearte:crud
做的事情就比较多了,它不仅生成了控制器,所有的模板文件也都生成了,并且还生成了表单类。我们先不管表单类,先访问新闻首页 /news/
试试,没有意外的话,你们可以看到一个从新建、显示、编辑、删除都完全可用的新闻功能。
需要注意的是:从 Symfony 2.6 开始,模板文件推荐是放在 app/Resources
下的,但是 doctrine:generate:crud
命令还是将模板文件放在了 AppBundle
的 Resources
目录。不仅如此,也不推荐使用 @Template
注解来猜模板路径(官方说法:主要因为性能问题),所以这里我们得把生成的 src/AppBundle/Resources
目录移到 app
目录,并且去掉控制器类里的所有 @Template
注解,而直接使用 $this->render
方法。
有一些我们暂时用不着的方法,可以先去掉。比如删除相关的方法 deleteAction
以及 createDeleteForm
,以及相关的调用全部去掉。模板里面有用到 delete_form
的地方,也都删掉。为了节省代码,我们把 newAction/createAction,以及 editAction/updateAction 合并为一个方法,这也是 Symfony 官方所推荐的最佳实践:
/**
* @Route("/new", methods={"POST", "GET"}, name="news_new")
*/
public function newAction(Request $request)
{
$entity = new News();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) { // 注意如果不是POST请求,isValid方法会返回false
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('news_show', ['id' => $entity->getId()]));
}
return $this->render('news/new.html.twig', [
'entity' => $entity,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}/edit", methods={"GET", "PUT"}, name="news_edit")
*/
public function editAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('AppBundle:News')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find News entity.');
}
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('news_edit', ['id' => $id]));
}
return $this->render('news/edit.html.twig', [
'entity' => $entity,
'edit_form' => $editForm->createView(),
]);
}
注意合并之后,之前的两个路由 news_create
和 news_update
已经没有了,所以 NewsController
里相关的代码,都需要更新。
2016年06月13日更新:感谢网友提醒,从 2.8 版本开始,doctrine:generate:crud
已经按照最佳实践将模板生成到了 app/Resources
目录,而且不再使用 @Template
注解,以及合并了 newAction/createAction 和 editAction/updateAction 方法。
另外细心的同学会发现注解 @Method
也被我删除了,因为 @Route
其实是包含 @Method
的功能的。这里看个人爱好。
如果你已经清理干净了 @Method
和 @Template
注解,那么以下的代码就可以删除了:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
反过来也说明一个需要小心的点:如果你要使用某个注解功能,是需要 use
到当前代码文件的。
使用 KnpPaginatorBundle 实现翻页功能
现在有一个小问题,列表总是需要翻页的。此时大家如果心里在琢磨“翻页算法”,那说明你的开发方式还不够 Symfony,或者说还不够敏捷。像翻页这种常见的需求,现成的库一定是很多而且已经非常成熟,一个人花时间做设计和开发,让成千上万的其他人节省时间,正是开源软件伟大之处之一,除非是自己个人爱好,省时间的事情是一定要做的,毕竟工程师的主要职责是实现而不是钻研。目前支持 Doctrine2 的翻页库也有二三,而且大都已经 Bundle 化了。这里我推荐一款用得比较多的:KnpPaginatorBundle
安装第三方 Bundle 需要使用 Composer。安装 Composer 不在本篇范围内,大家可以上网搜搜,也可以看看我这篇 博客。这里我只用提醒大家一点:因为某种众所周知的原因,Composer 的速度不是很快,大家可以试试镜像。
准备好 Composer 以后,执行以下命令(假设已经把 composer.phar
改名为 composer
)
composer require "knplabs/knp-paginator-bundle"
昨天说过,之后将 Bundle 的“代表类”注册到 AppKernel
里,才能使用 Bundle 所提供的配置文件以及“服务”,什么是服务,稍后会说。
我们先完成 KnpPaginatorBundle 的注册:
// app/AppKernel.php
public function registerBundles()
{
return array(
// ...
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
// ...
);
}
然后新闻首页的代码做一点更新:
/**
* @Route("/", name="news")
*/
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$qb = $em->getRepository('AppBundle:News')->createQueryBuilder('n');
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate($qb, $request->query->getInt('page', 1));
return $this->render('news/index.html.twig', [
'pagination' => $pagination,
]);
}
其中 $this->get('knp_paginator')
得到的就是一个服务。目前不用深究服务是什么,只用知道服务也是一个对象,此对像会依赖一些其他的对象。如果手工初始化,需要写很多代码(依赖的对像的初始化,依赖的对象的依赖对象的初始化……),而 Symfony 的 Service Container 组件,可以通过配置文件来描述这种对象之间的依赖关系,进一步在实际使用的时候,只需用 $this->get
方法通过一个设置好的唯一名字去获取组件就行了($this->get()
其实是 $this->container->get()
的快捷方式)。依赖注入和服务容器是 Symfony 框架中运用得很多的概念之一,目前有个感觉就行,以后还会提到。
相应的模板文件app/Resources/views/news/index.html.twig
也做一点调整:
<tbody>
{% for entity in pagination %}
<tr>
...
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="4">
{{ knp_pagination_render(pagination) }}
</td>
</tr>
</tfoot>
分页我们就实现了。
这里我给大家介绍一下 createQueryBuilder
方法。首先大家应该知道的是,从数据库里获取数据,需要向数据库发起数据请求,一般来说是一段字符串,比如大家最熟悉不过的 SELECT * FROM xxx
这样的 SQL 语句,这个请求就叫“Query”,而“Query Builder”就是指创建 Query 的东西。其实有了 QueryBuilder 这个东西,在拼装 SQL 语句的时候,会方便许多,也不容易出错。大家可以对比一下以下代码:
$sql = "SELECT * FROM user WHERE is_active = 1";
if ($isAdmin) {
$sql .= " AND user_group = 'admin'"; // AND前面的空格很容易忘
}
if ($sortByUsername) {
$sql .= " ORDER BY username"; // 顺序还不能错,order必须在where之后判断
}
// 如果使用QueryBuilder
$qb = $doctrine->createQueryBuilder('u')->where('u.isActive = 1');
if ($sortByUsername) {
$qb->orderBy('u.username');
}
if ($isAdmin) {
$qb->addWhere('u.userGroup = 'admin'');
}
需要各位读者注意的是,如果记录条数不满每页记录数,分页控件是不会出现的(KnpPaginator 默认是 10 条,您也可以自己设置每页记录数,至于怎么调,留给大家当作业吧)
Symfony 框架实战教程——第三天:用 KnpPaginatorBundle 实现翻页 by Chris Yue is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

写作累,服务器还越来越贵
求分担,祝愿好人一生平安
天使打赏人
50 Comments
freechoice
9月 17, 2019 在 12:00 下午Symony 4.3里使用Knp-paginator-bundle,
Service “knp_paginator” not found: even though it exists in the app’s container, the container inside “App\Controller\ContentController” is a smaller service locator that only knows about the “doctrine”, “form.factory”, “http_kernel”, “parameter_bag”, “request_stack”, “router”, “security.authorization_checker”, “security.csrf.token_manager”, “security.token_storage”, “serializer”, “session”, “templating” and “twig” services. Try using dependency injection instead.不知道是不是换了使用方式,直接使用Pager了
Chris Yue
9月 19, 2019 在 9:58 上午很有可能是。错误信息其实有很详细的解释,可以获得以下信息:
1. knp_paginator 的服务还是存在容器里的
2. 但是 controller 里的容器并不是之前版本那个整个框架用的容器,而是一个更小的容器
3. 这个小容器里并没有 knp_paginator
另外它说了建议:
直接通过依赖注入的方式,把 knp_paginator 注入到 controller 里(具体怎么注入我这里就不说了,又是一篇文章的量,但应该很好搜索)。
另外多说一句,其实通过注入服务的方式是好于之前直接使用 container 的,目的是为了让控制器明确自己的依赖。
leo
7月 5, 2017 在 10:18 上午楼主 为啥 添加新闻不好使了呢 ,没走 create但是直接走到index了
Chris Yue
7月 6, 2017 在 9:13 上午你确认是表单是走的 POST 方法吗?
YIPU
1月 3, 2017 在 1:45 下午AppKernel::init() method is deprecated since version 2.3 and will be removed in 3.0. Move your logic to the constructor method instead.这个怎么解决啊,谢谢
Chris Yue
1月 4, 2017 在 12:43 下午如果我没记错的话,
AppKernel::init()
方法应该是在比较早之前的版本里在 web/app.php 里执行的一段代码。你的 Symfony 应该升级过,但 web/app.php 还没有更新,目前 Symfony3 以上已经不在 web/app.php 里执行AppKernel::init()
方法了。好博客 坚持,可以挂点广告 我帮你点。。。
8月 16, 2016 在 2:43 下午好博客 坚持,可以挂点广告 我帮你点。。。
Chris Yue
8月 17, 2016 在 10:44 上午噗~谢啦兄弟
匿名
6月 13, 2016 在 10:38 上午在Symfony 2.8.7版本中,
doctrine:generate:crud
命令已经将模板文件放在了app/Resources
下的目录。也不再使用@Template
注解来猜模板路径,而直接使用$this->render
方法。而且 newAction/createAction,以及 editAction/updateAction 也已经合并为一个方法,这也是 Symfony 官方所推荐的最佳实践
Chris Yue
6月 13, 2016 在 2:06 下午感谢提醒
东东包
3月 23, 2016 在 3:35 下午使用knppaginatorbundle可以实现ajax分页吗?
Chris Yue
3月 24, 2016 在 9:11 上午可以啊,knppaginatorbundle可以只提供数据
万仕红
2月 2, 2016 在 10:54 上午用 sonata-project/admin-bundle 做的后台,上线2个月左右,出现了一个性能问题,把调试工具打开发现在查询列表的时候 有2条SQL语句执行特别慢
以上两条SQL随着项目的增大,执行时间越来越长。目前150W左右数据执行时间需要 18058.10 ms
我猜想是 knplabs/knp-paginator-bundle 在分页和查询总数的时候 总数带上了关键字 “DISTINCT”
我把这两条语句的关键字 DISTINCT 去掉以后,直接拿到数据库执行只需要 5ms 。所以我去查找 symfony2、sonata-project/admin-bundle、knplabs/knp-paginator-bundle 对于这个关键字的处理或者配置,但是持续查找了快一个礼拜都没有结果。
在此希望博主如果有时间的话,能够帮我分析分析。
感激不尽
Chris Yue
2月 3, 2016 在 1:24 下午我刚才去KnpPaginator的项目站看了一下,有一个配置是控制count时是否用DISTINCT的:
但这个选项也只能控制count那一句,select那一句是控制不了的。
之所以有这个选项,我想应该是作者为了和Doctrine2的做法一致吧,
select distinct
是Doctrine2加上的这个问题以前我也有注意过,但一直不明白为什么Doctrine2非要多写一句
select distinct
,如果你知道原因也麻烦跟我说下,谢谢,我非常好奇……xiaoyu
11月 27, 2015 在 2:57 下午KnpPaginatorBundle 页面怎么加载样式呢!
Chris Yue
11月 30, 2015 在 12:33 上午在
config.yml
里:例子里的twig文件是默认值,你可以参考此文件自己写一个模板,然后再配置成自己的twig文件路径
蚊子
10月 18, 2015 在 4:27 下午还有就是$paginator实例是怎么来的,我写$pagination = $paginator->paginate 的时候没有代码提示,我要new pagination吗?
Chris Yue
10月 25, 2015 在 10:30 上午代码提示是IDE提供的辅助功能,但因IDE的不同,代码提示的能力也不一样。如果只是IDE没有出现提示,不一定代码有问题,以实际可运行为主。
蚊子
10月 18, 2015 在 4:01 下午请教一下作者,看了你的教程受益匪浅,只是有个问题不清楚,还没去写代码调试。
$paginator = $this->get(‘knp_paginator’); 里的这个knp_paginator,没看到你在哪里声明这个id呀 ,这样可以这个id的服务吗?
Chris Yue
10月 25, 2015 在 10:27 上午knp_paginator服务是KnpPaginatorBundle里面定义的。Bundle是可以定义服务的
wimi
9月 22, 2015 在 9:22 上午Case mismatch between loaded and declared class names: AppBundle\Entity\news vs AppBundle\Entity\News
这是怎么回事?
Chris Yue
9月 24, 2015 在 9:04 下午抱歉你的评论自己跑到垃圾评论里了。
你检查一下你的Entity\News的文件名是大写开头的News.php么?这个文件应该是Windows下的吧我还从来没遇到过
freechoice
9月 19, 2015 在 10:43 上午翻页是可以用了,如果更换了其他的Subscriber,比如KnppaginatorBundle首页上的那个分类文件的翻页,还写了个Service,这时候如果还想从数据库取记录出来,就不知道怎么换回来了,还请大哥指教啊
Chris Yue
9月 21, 2015 在 1:47 下午额……你说啥……
你是想不用分页控件直接从数据库里取数据?
freechoice
9月 21, 2015 在 9:30 下午不是不想用分页控件从数据库当中取数据,而是同时从数据库和其他数据源取数据,默认情况下是用Doctrine的QueryBuilder取数据么,在KnpPaginationBundle的官方的Subscriber.md当中有介绍使用其他的数据源,比如说读取某个文件夹当中的文件列表进行分页(官网就是这个例子),我自己也写了一个从其他地方取数据的Subscriber,工作的挺好,至少摆脱了数据库的束缚了,摆脱了这个束缚,新的问题来了,当我想用数据库的时候,我没办法切换到数据库中的记录分页,我知道Knppaginationbundle有多个Subscriber,但我不知道怎么切换他们。 http:/www.aiduv.com,使用的就是其他的数据源,不是数据库,但我想用数据库的记录分页的时候,傻眼了
freechoice
9月 21, 2015 在 11:57 下午官网的文档在这里:https://github.com/KnpLabs/KnpPaginatorBundle/blob/master/Resources/doc/custom_pagination_subscribers.md
我提交的问题在这里:https://github.com/KnpLabs/KnpBundles/issues/465
Chris Yue
9月 24, 2015 在 8:57 下午OK我知道你说的什么意思了。我大概瞄了一下KnpPaginatorBundle的代码,最简单粗暴的方式就是不要使用symfony的service tag功能,你自己根据使用情况手动调用
event_dispatcher
服务的addSubscriber
方法,比如直接在某些不需要Doctrine的Controller使用自己的Subscriber,在某些需要Doctrine的Controller用默认的Subscriber。只不过Subscriber不是那么用的,要正儿八经写我建议还是通过target来判断——人家例子其实写得很详细了——如果target是一个需要你自己分页的对象,那就处理一下分页方式。如果不是,比如target是个Doctrine QueryBuilder对象你就直接
return
就行了ko1079
9月 1, 2015 在 5:34 下午遇到一个特别诡异的问题,纠结了我一下午 楼主看看
FatalErrorException: Error: Call to undefined method Doctrine\ORM\Query::hasHint() in E:\www\symfony\Symfony\vendor\knplabs\knp-components\src\Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ORM\QuerySubscriber\UsesPaginator.php line 37
Chris Yue
9月 2, 2015 在 10:32 上午我从来没有遇到过这个问题,不过看起来像是doctrine版本的问题,你可以尝试运行`composer update`命令来更新所有第三方库,如果还不行的话,你可能得给doctrine降级安装
txsing
5月 22, 2015 在 11:02 上午博主,我的代码跟你的一模一样,设置了每页1条新闻,可是结果是 第一页上依然显示所有的新闻,尽管下面的导航条显示了有4页,这是什么情况的
Chris Yue
5月 25, 2015 在 4:34 下午你这属于疑难杂症了……我还真没看出来哪儿不对的,等会儿……不应该是
$paginator->paginate($qb, $pageNumber, $pageSize)
吗,你试试leo
5月 14, 2015 在 3:26 下午完全是新手,这一天可真不容易啊
一上午反复折腾到现在,在@Template 换 $this->render这里折腾了好久,中途想放弃换其他教程的,但又不甘心浪费的前两天学习的时间.
如果博主的文章能更详细点就好了。
感谢!
Chris Yue
5月 15, 2015 在 1:10 下午没问题。你在替换@Template的过程中遇到什么问题了?有什么细节容易忽略的,能说一下吗?我补充一下
leo
5月 15, 2015 在 3:56 下午原来@Template是写在public function 上面的注释中的,替换的话需要使用$this->render() 需要把函数中return的数组代入并把注释中的@Template()删除掉,开始我不知道在这卡了好久,除了这里这一篇我还挺顺利的。
blooe
4月 30, 2015 在 2:55 上午你好,查了半天还是不太理解createQueryBuilder(‘n’)的意思,可以解释下吗?
Chris Yue
4月 30, 2015 在 6:45 下午为了让其他更多人能看到,我还是写在文章里面吧,你可以在本页搜索一下”createQueryBuilder”定位
blooe
4月 29, 2015 在 5:56 下午应该给读者提醒一下,新手容易被误导。一开始因为我的总条数没达到它默认的每页新闻条数,一直没显示页码,搞得我以为哪里出错了,后来设置了paginate第三个参数,才出现了页码
Chris Yue
4月 30, 2015 在 6:41 下午同感,立马加上
Alex Zheng
4月 16, 2015 在 4:30 下午问你,你这里创建了数据库,按照symfony在app/config/parameters.yml.dist这个文件中的配置,应该在mysql中看到一个名字叫symfony的数据库才对。
但是在我这里没有看到,不知道是什么原因。
还请指教
Chris Yue
4月 24, 2015 在 9:10 上午真正的配置文件不是
parameter.yml.dist
而是parameter.yml
不好意思你的评论被当成垃圾评论了现在我才看到……蔡司基
4月 2, 2015 在 6:52 下午flush后我怎获取影响条数?
Chris Yue
4月 2, 2015 在 7:45 下午问一遍就行了……你多余的评论我先删了啊。
如果你是非要获取数据库返回的影响条数,你可以通过nativeQuery来执行Mysql的——如果我没记错的话——
ROW_COUNT()
语句来返回影响条数。但这样并不好,因为ROW_COUNT()不一定其他数据库会提供一样的函数,万一换库了你就悲剧了,另外也因为多执行了一条SQL语句。
还有一个方法就是不用Doctrine ORM而只用Doctrine DBAL去执行update语句,文档中的$conn就是
$this->getDoctrine()->getManger()->getConnection()
ccna30
3月 31, 2015 在 9:05 下午我在用pagination的时候出现一个常见问题,就是想把数据表里面的图片路径,比如1.jpg 填入模板的<img标签:如
这样当然可以出现图片,但是其中的public/1.jpg用{{ article.face }}替换之后,输出还是src=”/web/{{ article.face }}”,感觉是嵌套的{{不起作用。
如果想在控制其中将article.face传过来,可是却不知道如何从$pagination对象取出face,感觉是传过来是整个的查询result,能否取出特定字段你?
pagination的文档上也没有相关内容。
ccna30
3月 31, 2015 在 9:23 下午当然
<img src=”/lq/web/public/{{ article.face }}”..
将路径写死就能解决这个问题,这样就不能用asset了。
Chris Yue
3月 31, 2015 在 10:50 下午{{ }}
不能嵌套用的亲……跟<?php ?>
里不能再套一个<?php ?>
一个意思……这样写就行了吧
ccna30
3月 27, 2015 在 12:13 下午安装了KnpPaginatorBundle之后,也修改了模板,但是结果是白屏。
ccna30
3月 27, 2015 在 12:14 下午模板代码为
ccna30
3月 27, 2015 在 12:23 下午访问http://localhost/news/web/app_dev.php/news/,就是白屏,无任何错误信息,查看源代码为空。。
ccna30
3月 27, 2015 在 1:56 下午这节我弄了三天了,还是白屏,于是我修改控制器最后一句为:
return new Response(“OK”);
得到了OK的输出,说明是模板渲染没成功。
Chris Yue
3月 27, 2015 在 9:40 下午你还真是够拼的。我看了一下你的代码,首先你得把注释里的
@Template
那行给去了,然后确认模板文件的位置是在项目根目录下app/Resources/views/news/index.html.twig