yii2和symfony_Symfony 2中的构建和处理表格

yii2和symfony

In this tutorial we will look at two examples of using forms in Symfony 2. In the the first, we will place form elements straight in the View file and then handle the form processing manually in the controller. In the second, we’ll use the Symfony form system to declare forms in an object oriented way and have Symfony process and persist the values.

在本教程中,我们将看两个在Symfony 2中使用表单的示例。在第一个示例中,我们将表单元素直接放置在View文件中,然后在控制器中手动处理表单处理。 在第二篇文章中,我们将使用Symfony表单系统以面向对象的方式声明表单,并进行Symfony处理并保留值。

We will be working on a simple installation of the Symfony framework. As you may know, it comes with a default bundle called AcmeDemoBundle and we will use that to illustrate working with forms. All the final code can be found in this repository I set up for this tutorial. Feel free to follow along or take a peek at the final code.

我们将致力于Symfony框架的简单安装。 如您所知,它带有一个名为AcmeDemoBundle的默认捆绑包,我们将使用它来说明如何使用表格。 所有最终代码都可以在我为本教程设置的存储库中找到。 随时关注或浏览最终代码。

非实体形式 (Non-entity forms)

The first example we will look at is how to process forms declared as regular HTML elements inside of a Symfony View file. There are 3 steps we will take to illustrate this:

我们将看到的第一个示例是如何处理在Symfony View文件中声明为常规HTML元素的表单。 我们将通过3个步骤来说明这一点:

  1. We will create a View file that contains our form HTML

    我们将创建一个包含表单HTML的View文件
  2. We will create a new Controller method in the WelcomeController class called form1Action that will handle our business logic (rendering the View, processing the form, etc).

    我们将在WelcomeController类中创建一个名为form1Action的新Controller方法,该方法将处理我们的业务逻辑(呈现View,处理表单等)。

  3. We will then create a simple route entry to map a URL path to this method so that we can see the form in the browser and be able to submit it.

    然后,我们将创建一个简单的路由条目,以将URL路径映射到此方法,以便我们可以在浏览器中看到该表单并能够提交该表单。

Let’s first create the View file that will show our form and the submitted value on top. In a file called form1.html.twig located in the src/Acme/DemoBundle/Resources/views/Welcome folder (the corresponding folder for the Welcome controller class Symfony comes with by default) I have the following:

首先创建一个View文件,该文件将在顶部显示我们的表单和提交的值。 在src/Acme/DemoBundle/Resources/views/Welcome文件夹中的一个名为form1.html.twig文件中(默认情况下, Welcome控制器类Symfony随附了相应的文件夹),我具有以下内容:

{% extends "AcmeDemoBundle::layout.html.twig" %}

{% block content %}

<h1>Form values</h1>

{% if name is defined %}
<p>Name: {{ name }} </p>
{% endif %}

<div>
    <form name="input" action="" method="post">

        Name:
        <input type="text" name="name"/>

        <input type="submit" name="submit" value="Submit">

    </form>
</div>

{% endblock %}

Above, I am extending the default layout in the DemoBundle just so I don’t see a very white page. And the rest is pretty basic as well: declaring a simple HTML form that posts to itself and showing the value of the only text field above the form (which will be passed from the Controller after processing in a variable called name).

上面,我只是在DemoBundle扩展了默认布局,所以我看不到非常白的页面。 其余的内容也很基本:声明一个简单HTML表单,该表单会自行发布并显示表单上方唯一文本字段的值(在处理完名为name的变量后,将从Controller传递该文本字段)。

Next, let’s declare the Controller method in charge of displaying this View and processing the form inside it. In the WelcomeController class file, I do two things:

接下来,让我们声明Controller方法负责显示此View并处理其中的表单。 在WelcomeController类文件中,我做两件事:

  1. I make use of the Symfony Request class that will help us easily access the submitted values:

    我利用了Symfony Request类,它将帮助我们轻松地访问提交的值:

    use Symfony\Component\HttpFoundation\Request;

    This goes above the class declaration.

    这超出了类声明。

  2. I have the following method:

    我有以下方法:

public function form1Action()
    {

        $post = Request::createFromGlobals();

        if ($post->request->has('submit')) {
            $name = $post->request->get('name');
        } else {
            $name = 'Not submitted yet';
        }

        return $this->render('AcmeDemoBundle:Welcome:form1.html.twig', array('name' => $name));

    }

In this method, I use the createFormGlobals() method found in the $request object to gather the PHP superglobals (including the $_POST values). Then I check if the submitted values include submit (which is basically our submit button), and if they do, I retrieve the value of the name element and pass it along to the View we just created. Simple.

在此方法中,我使用在$request对象中找到的createFormGlobals()方法来收集PHP超全局变量(包括$_POST值)。 然后,我检查提交的值是否包括submit (基本上是我们的Submit按钮),如果包含,则检索name元素的值并将其传递给我们刚刚创建的View。 简单。

Finally, let’s define a routing rule to match a URL path to this Controller method. In the routing.yml file located in the src/Acme/DemoBundle/Resources/config folder I added the following rule:

最后,让我们定义一个路由规则以使URL路径与此Controller方法匹配。 在src/Acme/DemoBundle/Resources/config文件夹中的routing.yml文件中,添加了以下规则:

_form1:
		pattern:  form1
		defaults: { _controller: AcmeDemoBundle:Welcome:form1 }

This will map the form1/ path to the new Controller method.

这会将form1/路径映射到新的Controller方法。

And that’s it, you can test it out. One thing to keep in mind is that this is not really a recommended way to handle forms when dealing with entities or any kind of content for your site. Symfony comes with some nice classes that will make doing that much easier. We will see how some of these work next.

就是这样,您可以对其进行测试。 要记住的一件事是,在处理实体或网站的任何内容时,这并不是处理表单的真正推荐方法。 Symfony附带了一些不错的类,它们使做起来更加容易。 接下来,我们将看看其中的一些工作。

Symfony实体和形式 (Symfony Entities and Forms)

Going forward, we will be looking at how to display and process a form for a Symfony entity called Article (that I’ve defined in the meantime and you can find in the repository). For a refresher on how entities work, check out our second part of the series on the Symfony framework.

展望未来,我们将研究如何显示和处理名为Article的Symfony实体的表单(在此期间我已经定义了,您可以在存储库中找到)。 要进一步了解实体的工作原理,请查看关于Symfony框架的系列文章的第二部分

I will illustrate a very simple example of how to display a form that will then save a new Article entity to the database, using the Symfony way. We’ll be working mainly with 5 files: the controller class file where we add two new methods for showing the form and for showing a simple confirmation page; the routing.yml file since we need to map the URLs; two View files to display the form and confirmation; and an ArticleType.php file in which we build the form.

我将展示一个非常简单的示例,说明如何显示一个表单,然后使用Symfony方式将新的Article实体保存到数据库中。 我们将主要处理5个文件:控制器类文件,在其中添加了两种新方法来显示表单和显示简单的确认页面; routing.yml文件,因为我们需要映射URL; 两个查看文件以显示表单和确认; 以及我们在其中构建表单的ArticleType.php文件。

We’ll start with the latter. Although you can build the form also directly inside the controller, using a separate type file makes it much more reusable so we’ll do that instead. Inside our src/Acme/DemoBundle/Form folder, I have a file called ArticleType, with the following contents:

我们将从后者开始。 尽管您也可以直接在控制器内部构建表单,但是使用单独的类型文件使它更具可重用性,因此我们将这样做。 在src/Acme/DemoBundle/Form文件夹中,我有一个名为ArticleType的文件,其内容如下:

<?php

namespace Acme\DemoBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ArticleType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('title', 'text', array('label' => 'Title'))
            ->add('body', 'textarea')
            ->add('save', 'submit');
    }

    public function getName()
    {
        return 'article';
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\DemoBundle\Entity\Article',
        ));
    }

}

Above, I extend the default Symfony form builder class to define my own form. The buildForm() method is responsible for actually building the form. Inside, I am adding to the $builder object’s various form elements that will suit our Article entity and that are named after the entity properties. For more information on the available form elements, you can consult the documentation.

上面,我扩展了默认的Symfony表单构建器类,以定义自己的表单。 buildForm()方法负责实际构建表单。 在内部,我要添加$builder对象的各种表单元素,这些元素将适合我们的Article实体,并以实体属性命名。 有关可用表单元素的更多信息,请查阅文档

The getName() method just returns the name of the form type itself whereas with the setDefaultOptions() method we specify the entity class we use this form for (as the value for the data_class key). And that’s it, we have our form definition, let’s build it inside our controller and display it on the page.

getName()方法仅返回表单类型本身的名称,而使用setDefaultOptions()方法,我们指定使用此表单的实体类(作为data_class键的值)。 就是这样,我们有了表单定义,让我们在控制器中构建它并将其显示在页面上。

Back in the WelcomeController class, I have included at the top two more class references (for the Article entity and the form type we just created):

回到WelcomeController类,在顶部还有两个类引用(用于我们刚刚创建的Article实体和表单类型):

use Acme\DemoBundle\Entity\Article;
use Acme\DemoBundle\Form\ArticleType;

Next, I added the following two methods:

接下来,我添加了以下两种方法:

public function form2Action(Request $request)
    {

        $article = new Article();

        $form = $this->createForm(new ArticleType(), $article);

        $form->handleRequest($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($article);
            $em->flush();

            $session = $this->getRequest()->getSession();
            $session->getFlashBag()->add('message', 'Article saved!');

            return $this->redirect($this->generateUrl('_form2saved'));
        }

        return $this->render('AcmeDemoBundle:Welcome:form2.html.twig', array('form' => $form->createView()));

    }

    public function form2savedAction()
    {

        return $this->render('AcmeDemoBundle:Welcome:form2saved.html.twig');

    }

The form2Action() method is responsible for showing and processing the form to create new Article enities. First, it instantiates a new empty object of that class. Then, it creates a new form for it using the form type we defined earlier. Next, it processes the form if one has been submitted, but if not, it renders the form2.html.twig View file and passes the rendered HTML form for it to display. Let’s create that file now and then we’ll come back and see what happens with the form processing.

form2Action()方法负责显示和处理表单以创建新的Article实体。 首先,它实例化该类的新的空对象。 然后,它使用我们之前定义的表单类型为其创建一个新表单。 接下来,如果提交了表单,它将处理该表单;如果未提交,它将呈现form2.html.twig View文件并传递呈现HTML表单以供显示。 让我们现在创建该文件,然后返回,看看表单处理会发生什么。

Right next to where we created form1.html.twig, I have form2.html.twig with the following contents:

在创建form1.html.twig ,我有form2.html.twig其中包含以下内容:

{% extends "AcmeDemoBundle::layout.html.twig" %}

{% block content %}

{{ form(form) }}

{% endblock %}

Couldn’t be simpler. It just renders the form that was passed to it. Let’s quickly also add the following route to our routing.yml file so we can see this in the browser:

再简单不过了。 它只是呈现传递给它的表单。 让我们快速还将以下路由添加到我们的routing.yml文件中,以便我们可以在浏览器中看到它:

_form2:
	    pattern:  form2
	    defaults: { _controller: AcmeDemoBundle:Welcome:form2 }

Now we can point our browser to the form2/ path and see a simple (but rather ugly) form. Now for the processing.

现在,我们可以将浏览器指向form2/路径,并查看一个简单(但相当难看)的表单。 现在进行处理。

As we saw earlier, the form2Action() method has a parameter passed to it: the $request object. So when we submit this form, it uses the handleRequest() method of the $form object we built to see if the form has been submitted (if its values exist in the $request superglobals). If it has been submitted, it runs a standard validation on it and saves the new object to the database (the one we originally instantiated has been automagically populated with the form values). Lastly, it saves a one request only flash message and redirects to another page, the path being built based on another route:

如前所述, form2Action()方法具有一个传递给它的参数: $request对象。 因此,当我们提交此表单时,它将使用我们构建的$form对象的handleRequest()方法来查看表单是否已提交(如果其值存在于$request超全局变量中)。 如果已提交,它将在其上进行标准验证,然后将新对象保存到数据库中(我们最初实例化的对象已经自动填充了表单值)。 最后,它保存一个仅请求的 Flash消息并重定向到另一页,该路径是根据另一条路线构建的:

_form2saved:
	    pattern:  form2saved
	    defaults: { _controller: AcmeDemoBundle:Welcome:form2saved }

The route triggers the form2savedAction() method we declared in the WelcomeController class and which renders the form2saved.html.twig View. And in this View, all I do for now is look if there is a message in the session flashBag and print it out:

该路由触发我们在WelcomeController类中声明的form2savedAction()方法,该方法将呈现form2saved.html.twig视图。 在此视图中,我现在要做的只是查看会话flashBag中是否有消息并打印出来:

{% extends "AcmeDemoBundle::layout.html.twig" %}
	
	{% block content %}
	
		{% for flashMessage in app.session.flashbag.get('message') %}
		    <p>{{ flashMessage }}</p>
		{% endfor %}
	
	{% endblock %}

And that’s it. Now you can refresh the form and submit it. You should be redirected to a simple page that shows the confirmation message. And if you check the database, a new Article record should have been saved.

就是这样。 现在,您可以刷新表单并提交。 您应该重定向到一个显示确认消息的简单页面。 并且,如果您检查数据库,则应该已经保存了新的Article记录。

结论 (Conclusion)

In this article we’ve looked at very simple usages of the Symfony 2 form system. First, we saw how to process a form submission using regular HTML form elements printed in the View. Then, we saw how to leverage the power of the Symfony form system to define forms in code in order to process and persist the values as an entity.

在本文中,我们研究了Symfony 2表单系统的非常简单的用法。 首先,我们了解了如何使用View中打印的常规HTML表单元素处理表单提交。 然后,我们看到了如何利用Symfony表单系统的功能在代码中定义表单,以便将值作为一个实体进行处理和持久化。

Each of these techniques have their use case. If you are performing CRUD operations on data or content, it’s best to use the second option. Symfony is very powerful when it comes to abstracting your data and this makes the form building very easy. If, however, you need some ‘on the fly’ processing of a form that does not save anything, you can build the form right into the View and then catch the submitted values in the controller.

这些技术都有其用例。 如果要对数据或内容执行CRUD操作,则最好使用第二个选项。 Symfony在抽象数据方面非常强大,这使表单的构建非常容易。 但是,如果您需要对表单进行“即时”处理而不保存任何内容,则可以将表单直接构建到View中,然后在控制器中捕获提交的值。

Questions? Comments? Would you like to know more? Let us know!

有什么问题吗 注释? 你想知道更多吗? 让我们知道!

翻译自: https://www.sitepoint.com/building-processing-forms-in-symfony-2/

yii2和symfony

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值