如何使用Symfony2在VPS上执行CRUD操作(第2部分)

来自菜鸟教程
跳转至:导航、​搜索

关于 Symfony

Symfony 是一个开源的 PHP Web 开发框架 - 一组工具和方法来帮助您构建出色的应用程序。 这个框架的一些特点是它的速度、灵活性、可扩展性和稳定性。 您可以将它用于完整的 Web 应用程序,也可以用于项目所需的较小功能。

上一篇教程 中,我们开始创建一个小应用程序来说明如何使用 Symfony2 框架执行 CRUD(创建、读取、更新、删除)操作。 为此,我们安装了 Symfony2 Standard Distribution 并开始处理我们数据库中的新闻文章 - 如果您按照所有步骤操作,您应该在 www.example.com/Symfony/web 上看到/app_dev.php/news/

我们将在本教程中做的是了解如何使用我们在上一个中开始使用的相同数据模块执行其余的 CRUD 操作 - 创建、更新和删除。 因此,假设您在开始本教程之前已经完成了上一教程。

创建数据

为了创建数据,让我们首先创建另一个路由到表单页面以添加我们的新闻文章。 因此,让我们编辑 NewsBundle 中的 routing.yml 文件:

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/config/routing.yml

并添加一条新路线:

foo_news_add:
    pattern:  /news/add/
    defaults: { _controller: FooNewsBundle:Default:add }

您现在可能注意到的是,您将与我们之前创建的路由 (foo_news_show) 中的模式发生冲突,因为它会查看单词 add 并认为它是 ID需要找到的新闻。 所以让我们编辑 foo_news_show 路由并创建一个要求 {id} 变量是一个整数。 所以像这样转换它:

foo_news_show:
    pattern:  /news/{id}
    defaults: { _controller: FooNewsBundle:Default:show }
    requirements:
        id:  \d+

好的,保存文件,现在让我们在 DefaultController 中创建我们的 addAction() 方法,作为该路由的回调。 所以让我们编辑 DefaultController.php 文件:

nano /var/www/Symfony/src/Foo/NewsBundle/Controller/DefaultController.php

首先要做的是确保类加载 News 实体类、用于表单处理的 Symfony Request 组件和 Response 组件。 因此,在命名空间声明下方的文件顶部,添加以下行:

use Foo\NewsBundle\Entity\News;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

现在,在 showAction() 方法下方,让我们添加新的 addAction() 方法:

public function addAction(Request $request) {

     $news = new News();
     $news->setCreatedDate(new \DateTime());
    
     $form = $this->createFormBuilder($news)
        ->add('title', 'text')
        ->add('body', 'text')
        ->add('save', 'submit')
        ->getForm();

     $form->handleRequest($request);    
     if ($form->isValid()) {
       $em = $this->getDoctrine()->getManager();
       $em->persist($news);
       $em->flush();
       return new Response('News added successfuly');
     }
    
     $build['form'] = $form->createView();
     return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
 }

那么这里会发生什么? 首先,我们实例化一个 News 对象并将其创建日期设置为当前时间。 然后我们使用 Symfony 表单构建器创建一个表单,它有两个字段(匹配我们的 News 实体中的属性)和一个提交按钮。 在函数结束时,我们创建表单并将其传递给 form 变量中的 news_add.html.twig 模板文件,以便显示。 让我们快速创建该文件,然后我们将回过头来解释表单处理部分。 因此,在您创建其余模板的地方创建新模板:

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/views/Default/news_add.html.twig

并在其中添加以下简单行:

{{ form(form) }}

通过将浏览器指向新路由来保存并测试页面,您应该会看到以下表单:

www.example.com/Symfony/web/app_dev.php/news/add

现在如果你提交它会发生什么? 如果您查看我们刚刚创建的 addAction() 方法,您会看到我们尚未讨论的这个块:

  $form->handleRequest($request);    
     if ($form->isValid()) {
       $em = $this->getDoctrine()->getManager();
       $em->persist($news);
       $em->flush();
       return new Response('News added successfully');
     }

这基本上检查是否已传递表单请求(还记得作为参数传递的 Request 对象吗?)并且它是否有效,然后自动更新我们刚刚创建的 $news 对象并使用学说管理器来将其持久化到数据库中。 然后它创建一个新的 Response 对象,并将成功消息打印在屏幕上。 如果没有表单请求进来,它将跳过这些步骤并以正常方式显示表单。 简单的。

更新数据

现在我们知道如何阅读新闻页面并添加新页面,更新它们将非常容易 - 它基本上结合了这两个动作。 像往常一样,让我们在 routing.yml 文件中添加一条新路由:

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/config/routing.yml

以及我们的编辑路线:

foo_news_edit:
    pattern:  /news/{id}/edit
    defaults: { _controller: FooNewsBundle:Default:edit }
    requirements:
        id:  \d+

如您所见,我们保持 {id} 为整数的要求,并且我们指向同一个控制器中称为 editAction() 的新方法 - 我们现在必须创建它。 所以让我们再次编辑类文件:

nano /var/www/Symfony/src/Foo/NewsBundle/Controller/DefaultController.php

并添加新方法:

public function editAction($id, Request $request) {

    $em = $this->getDoctrine()->getManager();
    $news = $em->getRepository('FooNewsBundle:News')->find($id);
    if (!$news) {
      throw $this->createNotFoundException(
              'No news found for id ' . $id
      );
    }
    
    $form = $this->createFormBuilder($news)
        ->add('title', 'text')
        ->add('body', 'text')
        ->add('save', 'submit')
        ->getForm();

    $form->handleRequest($request);
 
    if ($form->isValid()) {
        $em->flush();
        return new Response('News updated successfully');
    }
    
    $build['form'] = $form->createView();

    return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
 }

这里发生的事情又很简单。 此方法与 addAction() 的区别在于,我们不是实例化一个新的 News 实体,而是从数据库中检索一个现有实体。 生成的 $news 对象将再次成为表单构建的基础。 正如您所注意到的,在这个简单的示例中,我们可以使用相同的模板文件来呈现表单。 另一个小的区别是我们很早就得到了实体管理器,我们不必在表单处理中使用它的 persist() 方法,因为 $news 对象已经被管理了通过它。 因此使用 flush() 足以将其保存到数据库中。

您可以继续尝试在 www.example.com/Symfony/web/app_dev.php/news/1/edit 编辑 ID 为 1 的新闻页面,您会看到结果。

删除数据

我们将在本教程中看到的最后一件事是如何删除我们的新闻页面。 所以像往常一样,让我们设置一条路线,将我们带到删除确认页面。 所以再次编辑 routing.yml 文件:

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/config/routing.yml

并粘贴在以下路线中:

foo_news_delete:
    pattern:  /news/{id}/delete/
    defaults: { _controller: FooNewsBundle:Default:delete }
    requirements:
        id:  \d+

接下来,让我们在 DefaultController 中创建方法 deleteAction()。 编辑类文件:

nano /var/www/Symfony/src/Foo/NewsBundle/Controller/DefaultController.php

并添加新方法:

public function deleteAction($id, Request $request) {

    $em = $this->getDoctrine()->getManager();
    $news = $em->getRepository('FooNewsBundle:News')->find($id);
    if (!$news) {
      throw $this->createNotFoundException(
              'No news found for id ' . $id
      );
    }

    $form = $this->createFormBuilder($news)
            ->add('delete', 'submit')
            ->getForm();

    $form->handleRequest($request);

    if ($form->isValid()) {
      $em->remove($news);
      $em->flush();
      return new Response('News deleted successfully');
    }
    
    $build['form'] = $form->createView();
    return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
}

这个方法完成了 editAction() 的大部分工作,除了它不构建编辑表单,它只是输出一个提交按钮,用于删除检索到的 $news 对象。 然后在提交表单时,我们使用实体管理器的remove()方法从文章中删除新闻页面。 您会注意到我们再次使用相同的模板文件:news_add.html.twig

如果您现在导航到 www.example.com/Symfony/web/app_dev.php/news/1/delete,您将看到的只是一个删除按钮。 因此,让我们对我们的模板文件添加一个小修改,以便在出现删除按钮的情况下,还包含一些文本。 所以编辑模板文件:

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/views/Default/news_add.html.twig

在已经存在的内容之上,粘贴以下内容:

{% if form.delete is defined %}
      Are you sure you want to delete the news page: {{ form.vars.value.title }} ?
    {% endif %}

这将打印出包含问题中新闻页面标题的确认文本(取自传递给模板的表单变量)。 现在,如果您刷新页面,您将在那里看到它,您可以单击删除以删除 ID 为 1 的新闻。 然后,您应该会收到我们创建的 Response 对象传递的确认消息。

清理

我们现在已经实现了核心 CRUD 操作,因此是时候通过将其四舍五入来完成我们的小应用程序了。 这意味着在新闻列表页面上添加一些链接,可以让您快速执行操作。 我们已经在上一个教程中看到了如何在模板中创建链接,所以现在应该不成问题了。 编辑 news_show_all.html.twig 模板文件,让我们添加一些管理链接:

nano /var/www/Symfony/src/Foo/NewsBundle/Resources/views/Default/news_show_all.html.twig

在以下行下方:

<h3><a href="{{ path('foo_news_show', {'id':  new.Id  }) }}">{{ new.Title }}</a></h3>

粘贴这个:

<a href="{{ path('foo_news_edit', {'id':  new.Id  }) }}">Edit</a> | <a href="{{ path('foo_news_delete', {'id':  new.Id  }) }}">Delete</a><hr />

并在页面顶部粘贴以下内容:

<a href="{{ path('foo_news_add') }}">Add news</a>

现在转到 www.example.com/Symfony/web/app_dev.php/news/ 并查看它的运行情况。 在那里,您将拥有编辑和删除每个新闻页面的链接以及用于创建新新闻的顶部链接。

结论

在本教程和之前的教程中,我们已经了解了如何构建一个小型 Symfony2 应用程序,该应用程序在我们的数据模型(新闻页面)上执行 CRUD。 您的 DefaultController.php 类文件现在应该如下所示:

<?php

namespace Foo\NewsBundle\Controller;

use Foo\NewsBundle\Entity\News;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller {

  public function indexAction() {
    $news = $this->getDoctrine()
            ->getRepository('FooNewsBundle:News')
            ->findAll();
      if (!$news) {
        throw $this->createNotFoundException('No news found');
      }
    
      $build['news'] = $news;
      return $this->render('FooNewsBundle:Default:news_show_all.html.twig', $build);
  }

  public function showAction($id) {
      $news = $this->getDoctrine()
            ->getRepository('FooNewsBundle:News')
            ->find($id);
      if (!$news) {
        throw $this->createNotFoundException('No news found by id ' . $id);
      }
    
      $build['news_item'] = $news;
      return $this->render('FooNewsBundle:Default:news_show.html.twig', $build);
   }

   public function addAction(Request $request) {

     $news = new News();
     $news->setCreatedDate(new \DateTime());
    
     $form = $this->createFormBuilder($news)
        ->add('title', 'text')
        ->add('body', 'text')
        ->add('save', 'submit')
        ->getForm();

     $form->handleRequest($request);    
     if ($form->isValid()) {
       $em = $this->getDoctrine()->getManager();
       $em->persist($news);
       $em->flush();
       return new Response('News added successfuly');
     }
    
     $build['form'] = $form->createView();
     return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
  }

  public function editAction($id, Request $request) {

    $em = $this->getDoctrine()->getManager();
    $news = $em->getRepository('FooNewsBundle:News')->find($id);
    if (!$news) {
      throw $this->createNotFoundException(
              'No news found for id ' . $id
      );
    }
    
    $form = $this->createFormBuilder($news)
        ->add('title', 'text')
        ->add('body', 'text')
        ->add('save', 'submit')
        ->getForm();

    $form->handleRequest($request);
 
    if ($form->isValid()) {
        $em->flush();
        return new Response('News updated successfully');
    }
    
    $build['form'] = $form->createView();

    return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
  }

  public function deleteAction($id, Request $request) {

    $em = $this->getDoctrine()->getManager();
    $news = $em->getRepository('FooNewsBundle:News')->find($id);
    if (!$news) {
      throw $this->createNotFoundException(
              'No news found for id ' . $id
      );
    }

    $form = $this->createFormBuilder($news)
            ->add('delete', 'submit')
            ->getForm();

    $form->handleRequest($request);

    if ($form->isValid()) {
      $em->remove($news);
      $em->flush();
    }
    
    $build['form'] = $form->createView();
    return $this->render('FooNewsBundle:Default:news_add.html.twig', $build);
  }

}

尽管这非常简单,但 Symfony2 能够扩展到更复杂的数据,在多个表中结构化,并在管理数据时表现出色。 最后,使用带有 Symfony 的 Twig 模板系统可以让您创建非常强大且易于管理的网站。 祝你好运!

文章提交者:Danny