我正在开发一个在前端使用大量 javascript 的 SF2 应用程序。
SF2 为我提供了一种构建良好 REST 应用程序的好方法,使用教义管理我的数据库,使用 twig 作为模板等等,但我想使用 Angularjs。
我知道 angularjs 和 SF2 是具有不同方法的 2 个不同框架,但我想知道完成这项工作的最佳方法是什么。
它甚至值得吗?
如果是,您认为更清洁、最有效的解决方案是什么?
也许使用 php 而不是 twig 模板来使用 angularjs 花括号?
我认为Symfony2
可以完美地与AngularJS
. 证明是我一方面使用 Symfony 制作 API,另一方面使用 AngularJS 制作 Web 应用程序。
此外,由于某些原因,我使用Twig
. {% verbatim %} {% endverbatim %}
每次我需要在我的视图中使用 Angular 时,我只需将 angular 的花括号嵌入到 twig语句中。
从 Twig 1.12 开始,原始标签被重命名为verbatim:
{% verbatim %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endverbatim %}
中间的所有内容都不会被 Twig 引擎解析,并且可以被 AngularJS 使用。
虽然我建议更改 AngularJS 分隔符。否则,在查看模板时可能很难区分 Twig 和 AngularJS 代码。
我面临同样的情况,在我的情况下,我决定拆分客户端和服务器项目,我使用 symfony2 作为服务器端,因为它的简单性和可用性以及其他给我带来的优势。另一方面,我用 AngularJS 创建了一个简单的 HTML 项目,这对我很有用,因为我想用相同的客户端文件创建一个 HTML5 移动应用程序。
那样的话,我认为这里问题的核心在于认证和授权过程。您必须在服务器端实施安全防火墙以在 REST 中工作(例如 WSSE: Symfony2: How to create a custom Authentication Provider)。
然后是客户端(AngularJS)中的相应实现,我发现的最有用的资源: Github:witoldsz/angular-http-auth。
如果你想对你的 sf2 项目进行更深入的实现,你可以使用 Assetic 的过滤器编译 AngularJS,并在页面加载中获得性能。
我使用以下代码来更改 AngularJS 分隔符
咖啡脚本:
# Change the angular delimiters for twig compatability
# and load module with ngResource
WAFapp2 = angular.module("WAFapp2", ['ngResource'], ($interpolateProvider) ->
$interpolateProvider.startSymbol "{[{"
$interpolateProvider.endSymbol "}]}"
) var WAFapp2;
或 Javascript:
var WAFapp2;
WAFapp2 = angular.module("WAFapp2", ['ngResource'], function($interpolateProvider) {
$interpolateProvider.startSymbol("{[{");
return $interpolateProvider.endSymbol("}]}");
});
然后在我的布局顶部:
<!DOCTYPE html>
<html lang="en" data-ng-app="WAFapp2">
<head>
然后稍后在我可以使用的 html 的 body 标记部分:
<ul>
{% for item in seq %}
<li>{[{ item }]}</li>
{% endfor %}
</ul>
我认为这可以让事情变得更干净,并且可以轻松混合树枝和角标签。这似乎对我很有效。
避免混淆的两个胡须的一个很好的解决方案是基于属性的指令,称为 ng-bind:<p ng-bind="yourText"></p>
与<p>{{yourText}}</p>
保持角度应用程序分开是更可取的。只需将 Symfony 用作数据检索/持久性的 api 和安全提供程序。
这将允许更大程度地分离视图和数据层。因此,您可以开始在前端工作,而无需考虑后端实现。您只需要模拟 api 调用。
我一直在尝试使用 Symfony 和 angularjs 构建单页应用程序。我使用 Symfony2 和 FOSRestBundle 来构建一个 Restful API 和 Angularjs 来构建前端。
AngularJs 本身不需要 Symfony2 框架来构建应用程序,只要它有一个 API 可以与之交谈。然而,我发现 Symfony2 在这些领域很有用:
模板中的翻译。API 有效负载中的数据在大多数情况下不需要翻译。使用 Symfony I18N 对模板的支持非常有意义。
加载选项列表。假设您有一个包含 200 多个选项的国家/地区列表。您可以构建一个 API 来填充 angularjs 中的动态下拉列表,但由于这些选项是静态的,您可以简单地在 twig 中构建该列表。
预加载数据/内容。如果您愿意,可以在托管页面中预加载模板或 JSON 数据
利用 Symfony 的身份验证功能。您也可以对应用程序的 API 使用相同的经过身份验证的会话。无需使用 Oauth。
Assetic 包对于 AngularJs 使用的 Javascript 文件的 urglyfy 和缩小非常有用
但是,我确实发现了以下挑战:
多个 Ajax 调用的 PHP 会话锁定。需要一种更好的方法来通过调用“session_write_close()”或使用数据库进行会话来释放 php 会话。Symfony 中调用“session_write_close”函数的最佳位置在哪里,以便我们可以尽快释放会话以进行更多 ajax 调用?
重新加载/同步加载的数据假设您在浏览器中显示了一个项目列表(如 ebay 项目),当列表在服务器端更新时,您希望在客户端的浏览器中更新该列表。您可能需要定期轮询列表或使用 Firebase 之类的东西。在大多数情况下,Firebase 是一种过度杀伤力,轮询对我来说并不好看,但实现这一目标的最佳方法是什么?
请添加您的评论。谢谢
我自己试图让 Symfony 和 AngularJS 一起工作时遇到了很多问题。但是,在处理它时,我学到了一些可能对您有所帮助的东西:
{{ variable }}
与树枝花括号分开,您有三种选择:一个)。在 AngularJS 表达式周围使用引号{{ '{{ variable }}' }}
乙)。包围你的 AngularJS 代码{% verbatim %} your code {% endverbatim %}
C)。使用 AngularJSinterpolateProvider
服务
angular.module('myApp', []).config(function($interpolateProvider){
$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
});
$http.get(Routing.generate('route_name', {'id':id}));
这可能不适用于您的提交,为什么?关于 $http.post,您应该知道的一件事是它不会将数据作为“表单数据”发送,而是作为“请求有效负载”发送,这是通过 HTTP POST 传输数据的正常方式。问题是这种“正常方式”并不等同于表单提交,这会导致使用 Symfony Request 对象解释数据时出现问题。
改用这个:
$http.put(url, $.param({foo: 'bar'}), {
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
当你想知道一个请求是否是控制器内的 AJAX 请求时,我们通常使用 isXMLHttpRequest() 方法。问题是 Angular 没有将其请求识别为 XMLHttpRequest 请求。用这个:
var app = angular.module('myModule', []);
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
}]);
创建表单时,您可以选择通过 AngularJS 显示表单并让 Symfony Form 处理请求。为此,您需要禁用 CSRF 保护:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => '...',
'csrf_protection' => false
));
}
现在你的 symfony 表单可以接收来自自定义 Angular 请求的数据了。
除了所有的事情,我仍然不确定一件事,是否使用 Symfony 或 AngularJS 显示您的表单。
希望这可以帮助。
理论上,你只会从 symfony 渲染你的索引页面,所以你根本不需要使用 twig。您只需要呈现第一页,然后角框架接管。Angularjs 有自己的模板语法和功能。我不认为有必要混合这两个,因为你可以完全分离两个框架。也许,让你的服务器响应 yourdomain.com 上的文件 index.html(你的角度应用程序),来自 symfony 的所有内容都来自 / api 前缀,或类似的东西。试想一下,您的 WebApi 项目是一台服务器,另一台是 angularjs 项目。在我看来,他们只会通过 api 调用进行交谈,根本不需要混合模板。
通过网络搜索,我遇到了不同的解决方案。例如,您可以如前所述更改角度符号。但是,我更喜欢通过简单地告诉 twig 输出角度符号来使其尽可能简单:
{{ '{{entity.property}}' }}
我遇到过同样的情况,我必须在 Symfony2 之上使用 AngularJS 开发单页应用程序。
如果你可以将两个应用程序分开,那就完美了!!!它将创建模型层和视图层的良好分离。如果不是这样,就像我的应用程序一样,您当然可以将 AngularJS 与 Symfony2 和 TWIG 完美结合使用。
我在 AngularJS 表达式周围使用了引号,例如 -
{{ '{{someAngularJsExpression}}' }}
只是需要一些时间来适应它,但是当你这样做时,你不会面临很多问题。Symfony 还允许您使用其他模板引擎,但我不希望这样做。
所以我的建议是要么有两个不同的 AngularJS 和 Symfony 应用程序。如果您没有资源这样做,您可以按照我的方式进行操作。别担心,你会习惯的。
今天每个人都想要带有 api 和 angular/vue 前端的 symfony 后端——这很好,但是这样我们就失去了前端的所有 symfony 能力。
我成功地将 Angular 与我的 symfony 应用程序一起使用。也许这不是高性能的东西,但它确实有效。
给你的一些提示:
1
阅读有关 $interpolateProvider 的信息
angular.module('myApp', [], function($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
这样你就可以改变 {{ }} 的角度来换取别的东西。我正在使用 {[{ 和 }]} ,所以它不会干扰树枝
2
这里第二好的事情是 https://symfony.com/doc/master/bundles/FOSJsRoutingBundle/index.html
这将 symfony 路由与 js 连接起来,因此您在 js 中的所有角度视图/或 ajax 调用都可以由 symfony 生成 - 这为您提供了巨大的可能性
{@ variable @}
在模板中使用。生成模板后,只需用简单的函数{@
替换{{
和@}
替换即可。这种方式很干净,比字符串连接等快得多。}}
str_replace
您可以简单地转义大括号,例如:
Hello {{ '{{' }} name {{ '}}' }}
它将被解析为下一个 HTML 代码:
Hello {{ name }}
您也可以尝试使用左右大括号 HTML 编码字符集,例如:
{ name }
但我不确定AngularJS lib是否会理解它:)。