繁体   English   中英

Angular JS和Symfony2

[英]Angular JS and Symfony2

我目前正在使用Symfony2进行一个项目,并就此寻求一些建议。

我正在考虑以两种不同的方式使用混合应用程序a)登录页面应使用带CRF令牌的传统形式,并让symfonty2处理它。 b)所有内页(可能是模块)我希望它们是非AJAX,但其中的其他活动应该像单页一样。

例如,我有一个员工模块 当用户点击它完全从服务器(所有模板和表单等)加载时,现在员工模块下的每个活动(如添加/更新删除/视图等)都将通过AJAX加载,并且响应将以JSON(即AngularJS)返回。

我目前正在考虑使用FOSUserBundle在初始请求时返回html然后根据请求类型接受:application / json它将返回JSON(还记得add / updat delete / view部分吗?)。

我的问题是使用Angular Partials(html)文件或Symfony2 Twig更好吗? 或者使用Angular JS会更好,但是让那些部分由Symfony2 twig渲染? (我在想这里的Forms,想要从客户端和服务器端验证)

有没有人经历过类似的问题,如果是,那么使用AngularJS和Symfony2或任何其他框架开发HYBRID应用程序的方法是什么? 任何相关的想法表示赞赏。

我和你的情况一样。 AngularJS + Symfony2项目,REST API,使用FOSUserBundle登录等。

......各方面都有利有弊,所以没有正确的方法,我只想说出我的所作所为。

我选择AngularJS本机模板,没有CSRF验证,使用Twig构建的基本模板,服务器端验证,使用FOSJSRoutingBundle以及一些帮助程序(BuiltResponse和BaseController)。

为什么原生模板?

通过逐字使用,我们解决了变量问题,但是我们的模板中会有更复杂的逻辑。

我们的应用程序也将具有不太可扩展性。 我们所有的表单模板都在Symfony应用程序中执行请求,AngularJS的最佳专业人员之一是从存储服务(如S3)或CDN(如Cloudfront)加载我们的控制器,模板等。 由于没有服务器端处理,我们的模板加载速度会快得多。 即使有缓存,Twig显然也比较慢。

根据我自己的经验,Twig和AngularJS模板都非常复杂。 我开始将它们组合在一起,但管理起来很痛苦。

我做了什么?

我在前端创建了静态模板,使用相同的字段名称,这不是很好。 我们需要在每次手动更新表单时更新模板。 但这是我发现的最佳方式。 由于字段名称相同,我们在调整Angular控制器中的模型名称时不会遇到任何问题。

如果您要将软件创建为服务,则无论如何都需要执行此操作。 你不会在移动应用程序中加载应用程序中的表单模板吗?

为什么没有CSRF验证?

显然,我们不在REST API中使用CSRF验证。 但是,如果您想这样做,则需要在每次加载表单时发出请求以获取CSRF令牌。 这真的非常糟糕。 因此,我们创建了一个CRUD,我们还需要创建一个“csrf-CRUD”,更多4条路由。 这没有任何意义。

我做了什么?

我在表单中禁用了CSRF。

基本模板?!

是的。 基本模板只是在我们的应用程序中加载任何路由。 这是我正在做的事情:

在此输入图像描述

如果您使用的是html5 angularjs网址,这将有助于我们避免在用户直接访问某些应用程序URL时出错。 很简单。

服务器端验证,为什么?

如果我们在Angular中进行验证,我们需要在服务器端执行相同的操作,因此我们需要维护2个验证代码。 那很痛苦。 我们在表单中进行的每一项更改,都需要更改前面的验证,后面的验证以及Angular静态表单。 真的,真的很痛苦。

我做了什么?

我基本上使用Symfony约束进行了服务器端验证。 对于每个请求,应用程序验证表单并检查是否发现任何错误,如果是,则获取第一个并将其作为响应发送。

在AngularJS中,应用程序检查错误键内是否有任何错误。 因此,我们在所有应用程序中都使用了一个进程来执行任何表单请求。 就像那样:

在此输入图像描述

和路线?

还有另一个问题:路线。 直接放url是不可靠的方法。 如果我们更改了网址中的任何内容,那么该路由就会消失,用户也不会喜欢。

为了解决这个问题,我们可以使用FOSJsRoutingBundle 使用该库,我们可以将路径名称直接放在Angular控制器中,它将填充路径的确切URL。 它与Symfony完全集成,因此参数可以很好地工作。

而是直接使用url,我们可以这样做:

Routing.generate('panel_products_show', {id: $routeParams.product_id});

瞧! 我们得到路线网址。


这将解决您遇到的最大问题。 但还有更多。

问题1 - 表格输入

Symfony中的表单通常有一个前缀,如“publish_product”,因此每个字段都有一个名称,如[publish_product]name 啊,这对我来说是怎么回事。

在Angular中,publish_product不被视为数组。 您需要使用单引号来执行此操作,例如['publish_product']name 这真的很糟糕,我们需要更改每个键才能使用这种格式。 在AngularJS中,我这样做:

{{ formData('[publish_product]name') }}

绝对愚蠢。

最好的解决方案是简单地删除Symfony中的表单前缀,使用createNamedBuilder方法而不是createBuilder 我让第一个参数为null,是的,我们不再需要使用前缀了。 现在,我们使用:

{{ formData.name }}

好多了。

问题2 - 路线很难维护

每个请求都可以返回任何内容,我需要重复很多代码。 这真的很难维护,所以我只创建一些应用程序规则,构建响应,BaseController等。

createNamedBuilder

createNamedBuilder是一个createNamedBuilder的方法。 对于我们拥有的每种形式,我们都需要这样做:

在此输入图像描述

解决起来很简单。 我刚刚创建了一个BaseController,我正在扩展它的每个控制器。 我创建了一个简单的方法来完成它。

在此输入图像描述

对于每条路线,我们不需要重复3条线,更好。

回应

当我的应用程序开始增长时,我遇到了一个严重的问题:我的所有回答都不同。 这真的很难维持。 对于我正在做的每个请求,有时我使用“响应”,有时“数据”,错误消息在响应中丢失等。

所以,我决定创建一个buildResponse,我只需要设置一些参数,每个路由都得到相同的结果,甚至是GET路由。

在此输入图像描述

response键显示状态和消息。 它可能是错误或成功,并且消息是可选字段,可以是空白的。 例如,成功状态,显示消息“您创建了产品”。

data键显示我需要的任何信息。 例如,用户添加了产品,现在他需要链接才能看到它。 在数据中,我把帖子的url,我很容易从AngularJS控制器获取它。

notifications是我的业务逻辑的特定键。 每个操作都可以向用户返回通知。

你有什么钥匙并不重要。 最重要的是有一个标准化的响应,因为当你的应用程序增长时,它将非常有用。

这是我的控制器的路线:

在此输入图像描述

完全标准化。 Scrutinizer代码质量工具说我的所有路由都是重复的。 :d

有一个BaseController和一个builtResponse会帮助你这么多。 当我开始重构我的代码时,每条路线丢失了大约4-10行。


详细信息: getFormError返回表单的第一个错误。 这是我的方法:

public function getFormError(FormInterface $form)
{
    if ($form->getErrors()->current()) {
        return $form->getErrors()->current()->getMessage();
    }

    return 'errors.unknown';
}

...而buildResponse的参数是:1。状态。 我从BaseController中的常量中得到它。 它可以改变,所以我认为重要的是不要在每条路线中使用字符串值。 2.翻译信息。 (我使用preg_match来检查它是否有翻译格式,因为getFormError已经转换了错误)。 3.数据(数组)参数。 4.通知(数组)参数。

我还有其他问题

到目前为止,该项目只有一种受支持的语言。 当我开始使用多语言版本时,我将遇到另一个大问题:维护两个版本的翻译:后端消息和验证以及前端的文本。 这可能是个大问题。 当我得到最好的方法时,我会更新这个答案。

我花了几个月才得到这种方法。 如此多的代码重构和未来可能会更多。 所以我希望它可以帮助别人不需要这样做。

如果我有更好的方法来做到这一点,我会更新这个答案。

我不擅长写英文,所以这个答案可能会有许多语法错误。 对不起,我正在修理我所看到的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM