🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 文章评论 博客已经部署,我们写了一些非常好的博客帖子,并通过Adminer发布。 人们正在阅读博客,他们非常热衷于我们的想法。 我们每天都收到很多赞美的电子邮件。 但是,当我们只有在电子邮件中,所以没有其他人可以阅读它的所有赞美? 如果人们可以直接在博客上评论,以便其他人可以阅读我们是多么真棒,这不会更好吗? # 创建新表 我们用工具创建一个新表格InnoDB类,名称为comments ![](https://box.kancloud.cn/f6e6c29ebe4b7a08f72c4aee616dba4b_705x289.png) ~~~ CREATE TABLE `comments` ( `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, `post_id` int(11) NOT NULL, `name` varchar(250) NOT NULL, `email` varchar(250) NOT NULL, `content` text NOT NULL, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`) ) ENGINE=InnoDB CHARSET=utf8; ~~~ 如果创建时出错,查看是否第一个posts表是不是InnoDB类型。 # 表单 首先,我们需要创建一个表单,这将允许用户对我们的页面发表评论。 Nette Framework对表单提供了极好的支持。 它们可以在控制器中配置并在模板中呈现。 Nette Framework有一个组件的概念。 组件是可重用的类或代码片段,可以附加到另一个组件。 即使控制器是一个组件。 每个组件都是使用组件中心创建的。 所以让我们在PostPresenter中加入以下代码。 ~~~ protected function createComponentCommentForm() { $form = new Form; // means Nette\Application\UI\Form $form->addText('name', 'Your name:') ->setRequired(); $form->addEmail('email', 'Email:'); $form->addTextArea('content', 'Comment:') ->setRequired(); $form->addSubmit('send', 'Publish comment'); return $form; } ~~~ 让我们解释一下。 第一行创建一个Form组件的新实例。 以下方法将HTML输入附加到表单定义中。 - > addText将呈现为<input type = text name = name>,带有<label>您的姓名:</ label>。 正如你可能已经猜到了, - > addTextArea附加一个<textarea>和 - > addSubmit添加一个<input type = submit>。 有更多的方法,但这是所有你必须知道,现在。 您可以在文档中了解更多。 一旦在控制器中定义了表单组件,我们可以在模板中显示它。因此,请将{control}放在帖子详细信息模板的末尾,在app / presenters / templates / Post / show.latte中。 因为组件的名称是commentForm(它是从方法createComponentCommentForm的名称派生的), ~~~ ... <h2>Post new comment</h2> {control commentForm} ... ~~~ 意思是你在show.latte里面加入以上代码就象以下一样 ![](https://box.kancloud.cn/d874390e5f56ff5ee52b1ad6c3dca663_526x305.png) 再刷新文章详细页面,就了现了表单! ![](https://box.kancloud.cn/9a75d043799ea6073f884cc0fea9b5c5_433x435.png) # 批论保存到数据库 现在可以尝试提交一些数据? 您可能已经注意到,表单没有执行任何操作。 它只是在那里,看起来很酷,什么也不做。 我们必须给它附加一个回调方法,这将保存提交的数据。 将以下行放在组件工厂中返回行之前的createComponentCommentForm中: ~~~ $form->onSuccess[] = [$this, 'commentFormSucceeded']; ~~~ ![](https://box.kancloud.cn/f693ee261db83604978db9e3d687cd92_533x325.png) 这意味着“表单成功提交后,调用当前控制器的方法commentFormSucceeded”。 但是这个方法还不存在,所以让我们来创建它。 ~~~ public function commentFormSucceeded($form, $values) { $postId = $this->getParameter('postId'); $this->database->table('comments')->insert([ 'post_id' => $postId, 'name' => $values->name, 'email' => $values->email, 'content' => $values->content, ]); $this->flashMessage('Thank you for your comment', 'success'); $this->redirect('this'); } ~~~ 以上代码一定要放在createComponentCommentForm()下面 ![](https://box.kancloud.cn/8a08cf712e1a184b40218913009c72a6_658x531.png) 新方法有一个参数,它是被提交的表单的实例,由createComponentCommentForm()创建。 我们收到在$values中提交的值。 然后我们将数据插入数据库。 当我们提交时 $this->flashMessage('Thank you for your comment', 'success'); 会产生信息提示,但是他都是在上部出现,如果我们想把这个信息提交按模板 出现,那我们应如下操作,先在 app/presenters/templates/@layout.latte 中加入以下代码 ~~~ <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">{$flash->message}</div> ~~~ ![](https://box.kancloud.cn/0b88c9d41948e4cb8a8f16ab3256c781_782x207.png) 我们再试一次就明白了。 # 显示评论 Nette \ Database有一个很酷的功能,名为Selection API。 你还记得我们创建的表是InnoDB吗? 管理员创建了所谓的外键,这将为我们节省大量的工作。 Nette \ Database使用外键来解析表之间的关系,并且知道关系,它可以自动为您创建查询。 你还记得,我们已经将$ post变量传递给PostPresenter :: renderShow()中的模板,现在我们要遍历所有的post_id等于$ post-> id的评论。 你可以通过调用$ post-> related('comments')。 就是这么简单。 看看结果代码。 ~~~ public function renderShow($postId) { ... $this->template->post = $post; $this->template->comments = $post->related('comments')->order('created_at'); } ~~~ ![](https://box.kancloud.cn/cd7e0da5f02fa79e9fb639bb802ddc7d_697x268.png) 然后在show.latte模板中加入以下代码 ![](https://box.kancloud.cn/68f13e0d3f57a9bbc12f43cb965bf696_910x450.png)! 注意特殊的n:tag-if属性。 你已经知道n:属性如何工作。 嗯,如果你用tag-添加属性,它将只包裹标签,而不是它们的内容。 如果他们提供了电子邮件,这允许您将评论者的名字变成链接。 这两行结果相同: ![](https://box.kancloud.cn/7b137ca9bf176afe40b8330451eaea42_623x56.png)