在VPS上用Symfony2怎么实现CRUD操作?(第一部分)

文章导读
PHP Frameworks目录热门话题关于 Symfony Symfony 是一个开源的 PHP web 开发框架——它是一套工具和方法论的集合,帮助你构建优秀的应用程序。该框架的特点包括速度快、灵活性高、可扩展性强以及稳定性好。你可以用它来开发完整的 web 应用程序,也可以用于项目中较小的功能模块。
📋 目录
  1. Bundles
  2. 实体
  3. 读取数据
  4. 结论
A A
PHP Frameworks
How To Use Symfony2 To Perform CRUD Operations on a VPS (Part 1)

关于 Symfony

Symfony 是一个开源的 PHP web 开发框架——它是一套工具和方法论的集合,帮助你构建优秀的应用程序。该框架的特点包括速度快、灵活性高、可扩展性强以及稳定性好。你可以用它来开发完整的 web 应用程序,也可以用于项目中较小的功能模块。

在之前的教程中,我们已经了解了如何安装 Symfony2 Standard Distribution 并将其配置为在你的 VPS 上运行。在本教程及接下来的教程中,我们将创建一个小型 Symfony 应用程序,对我们的数据模型执行一些基本的 CRUD(create, read, update, delete)操作。本教程假设你已经按照上一篇教程的步骤操作,并且能够从其结束的地方继续。

我们将处理的数据是新闻页面。我们将创建一个 entity(作为新闻页面的数据模型),并学习如何读取和显示它。在下一篇文章中,我们将学习执行其他操作,即添加、更新和删除新闻页面。但首先,我们需要创建一个 bundle。

Bundles

Symfony 中的 bundle 是一个目录,你在其中存放应用程序特定功能所需的所有文件。这包括 PHP 文件、样式表、javascript 文件等。在我们的应用程序中,我们将只创建一个 bundle,负责所有与新闻页面相关的功能。如果我们还想有一个博客,可以为此创建一个特定的 bundle。

bundle 的优点在于它们也像插件一样工作(甚至 Symfony 的核心功能也是以 bundle 形式组织的)。这意味着你可以自己创建新的 bundle 来包含特定功能的全部代码,或者注册由他人创建的外部 bundle。所以在开始处理数据之前,让我们使用命令行生成一个空的 bundle,因为 Symfony Standard Distribution 提供了这个便捷的功能。这意味着你无需手动创建所有文件夹并将 bundle 注册到 Symfony 中——这一切都会自动完成。

因此,要自动生成一个 bundle,请导航到应用程序的主文件夹,在我们的例子中是 Symfony:

cd /var/www/Symfony

运行以下命令生成名为 NewsBundle 的新 bundle:

php app/console generate:bundle --namespace=Foo/NewsBundle --format=yml

按照屏幕上的提示操作并接受默认选项。此命令将生成一个名为NewsBundle的 bundle,属于供应商Foo。你可以选择任何供应商命名(基本上代表你自己),但必须确保 bundle 名称以Bundle结尾。此外,该命令指定 bundle 的配置文件格式为 YAML 文件。

在后台,会为你的 bundle 创建文件夹结构(位于 src/Foo/NewsBundle),并将 bundle 注册到应用程序的其他部分。

实体

如果您按照前一个教程中的所有步骤操作,您的数据库连接应该已经配置好了。如果没有,您可以编辑 parameters.yml 文件:

nano /var/www/Symfony/app/config/parameters.yml

在那里,您可以指定数据库信息。如果您已经创建了数据库,可以跳过下一步。但是,您可以使用以下命令让 Symfony 自动创建与此文件中信息匹配的数据库:

php app/console doctrine:database:create

现在,为了处理我们的数据模型(新闻页面),我们需要创建一个称为 Entity 的东西。这基本上是一个 PHP class,它定义了我们新闻页面的所有信息。Symfony 有一个方便的命令行工具来实现这一点,我们将使用它,还有另一个不错的工具来创建与此数据模型匹配的实际数据库表。

因此,从命令行运行以下命令来生成名为 News 的 entity:

php app/console doctrine:generate:entity

按照屏幕上的指示操作。首先,您需要指定名称,或者说是简写名称。对我们来说是 FooNewsBundle:News(entity 名称是冒号后面的那个,但您还需要指定它所属的 bundle)。接下来,对于配置管理,选择 yml

然后,您将添加 class 属性(这些将匹配表列)以用于我们的数据模型。让我们添加 title(string, 255)、body(text)和 created_date(datetime)。接下来,不需要 repository,所以选择 no,然后确认生成。Entity 现在已创建。

如果您好奇想看看它的样子,可以查看新创建的 entity class 文件:

nano /var/www/Symfony/src/Foo/NewsBundle/Entity/News.php

接下来,让 Symfony 根据这个新创建的 entity 生成存储我们新闻页面的数据库表。运行以下命令:

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

此命令将从 entity 中获取信息并据此生成表。您应该会看到一个简单的确认消息:“Database schema updated successfully! "1" queries were executed.” 现在,如果您查看数据库,应该会看到一个名为 News 的表,包含 4 个列(id、title、body 和 created_date),这些都与 News entity class 中的属性匹配。

读取数据

由于我们的数据库是空的,让我们使用 phpmyadmin 或命令行插入 2 行测试数据,这样我们就可以使用新的 Symfony 应用程序来读取它们。稍后,我们将看到如何使用应用程序添加新内容,但现在,你可以在 mysql 终端中运行以下命令来添加 2 行数据:

use symfony;
INSERT INTO News (title,body,created_date)
    VALUES ('News title 1', 'Some body text', NOW());
INSERT INTO News (title,body,created_date)
    VALUES ('News title 2', 'Another body text', NOW());

现在我们有一些虚拟内容,让我们创建一个路由,将用户对特定新闻页面的请求映射到 Symfony Controller。

应用程序中的主要路由文件位于 app/config 文件夹中,但你也可以在 bundle 文件夹结构中的 routing.yml 文件中为你的 bundle 定义特定的路由规则:

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

让我们删除已经存在的规则,并添加另一个规则:

foo_news_show:
    pattern:  /news/{id}
    defaults: { _controller: FooNewsBundle:Default:show }

这个规则的名称是 foo_news_show,当浏览器请求 www.example.com/Symfony/web/app_dev.php/news/{id} 时,它将被触发,其中 {id} 是请求的新闻页面的动态传递 ID 的通配符。在 defaults 下,我们指定要调用的 Controller 和方法。在这种情况下,它将是位于 DefaultController.php 文件中的 DefaultController 以及其中的 showAction 方法(我们现在必须创建它)。

我们在这里指定 DefaultController,因为它的文件已经存在,是我们在创建 bundle 时由 Symfony 自动生成的。所以我们就使用它吧。我们现在要做的是创建使用 News entity class 和 Doctrine 数据库库来请求新闻页面,然后将其传递给 Twig 模板文件的方法。所以让我们编辑 DefaultController.php 文件:

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

在这个文件中,你已经看到了定义的 indexAction() 方法。在它下面,让我们声明 showAction() 方法:

public function showAction($id) {
      $news = $this->getDoctrine()
            ->getRepository('FooNewsBundle:News')
            ->find($id);
      if (!$news) {
        throw $this->createNotFoundException('未找到 ID 为 ' . $id . ' 的新闻');
      }
    
      $build['news_item'] = $news;
      return $this->render('FooNewsBundle:Default:news_show.html.twig', $build);
    }

这个函数使用 Doctrine 检索传递的 ID 对应的 news entity(如果未找到新闻则抛出异常),并将 news 对象传递给我们要创建的 news_show.html.twig 模板文件。代码非常直观。所以让我们这样做。

视图位于 bundle 的 Resources/views 文件夹下,在另一个以使用它们的 Controller 命名的文件夹中——在我们的情况下是 Default。所以在那里创建一个名为 news_show.html.twig 的新文件:

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

并粘贴以下模板代码:

{{ news_item.Title }}
{{ news_item.Body }}

<h1>{{ news_item.Title }}</h1>
{{ news_item.Body }}

这是一个带有 Twig 模板语言的 html 文件。我们在这里不详细介绍 Symfony 中的 Twig,有兴趣可以在这里阅读更多。现在如果你将浏览器指向 www.example.com/Symfony/web/app_dev.php/news/1,你应该会看到 ID 为 1 的新闻。

现在让我们通过创建另一个路由规则和 Controller 方法来创建所有新闻页面的列表。打开你之前编辑的同一个 routing.yml 文件:

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

并添加以下内容:

foo_news_home:
    pattern:  /news/
    defaults: { _controller: FooNewsBundle:Default:index }

这个路由将触发 DefaultControllerindexAction() 方法,所以让我们去编辑它(如果你记得,它已经在 Controller 文件中,所以我们只需要修改它):

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

删除默认指定的参数($name)和方法中的代码。相反,粘贴以下内容:

$news = $this->getDoctrine()
            ->getRepository('FooNewsBundle:News')
            ->findAll();
      if (!$news) {
        throw $this->createNotFoundException('未找到新闻');
      }
    
      $build['news'] = $news;
      return $this->render('FooNewsBundle:Default:news_show_all.html.twig', $build);

类似于我们之前创建的方法,这个方法将找到表中的所有新闻并将它们传递给 news_show_all.html.twig 模板文件。所以让我们在之前创建的文件同一文件夹中创建这个文件:

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

并遍历 $news 对象数组来显示所有新闻标题:

{% for new in news %}

<h3>{{ new.Title }}</h3>

{% endfor %}

现在如果你访问 www.example.com/Symfony/web/app_dev.php/news/,你应该会看到我们手动添加到表中的 2 个新闻标题。让我们也使用 Symfony 路由系统为这些标题添加链接,指向我们之前创建的各自页面。所以将以下内容替换:

<h3>{{ new.Title }}</h3>

为这个:

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

这是 Twig 模板中生成链接的便捷方式。你基本上指定使用哪个路由,以及路由期望的通配符的值——在这种情况下是 news 对象中的 ID。现在如果你刷新页面,标题就会变成指向各自页面的链接。

结论

在本教程中,我们了解了 Symfony bundle 是什么以及如何创建它们。我们还启动了一个小型应用程序,该应用程序需要与数据库中的新闻页面进行交互。为此,我们定义了一个与表结构匹配的 Entity class,并使用 Doctrine 来访问信息并填充 entity 对象。此外,我们还使用了 Symfony 路由系统,将浏览器请求连接到 PHP Controller 方法,这些方法随后请求数据并在 Twig 模板中将其呈现回浏览器。

在下一个也是最后一个教程中,我们将探讨创建、更新和删除新闻页面。

感谢与 Community 一起学习。请查看我们提供的计算、存储、网络和管理数据库产品。

了解更多我们的产品