如何通过AngularJS远程标记或取消标记Drupal 7节点?
解决Drupal 7 + Flags模块 + AngularJS的标记/取消标记问题
哈哈,这个问题我之前在做Drupal+Angular混合项目的时候踩过一模一样的坑!核心原因就是Flags模块本身没默认提供可供前端调用的REST接口——网站端能用是因为它走了Drupal的内部路由,而AngularJS属于前端独立调用,得自己给Flag操作搭后端API,再处理好Drupal的CSRF验证就行,给你一步步拆解:
第一步:给后端搭Flag操作的API端点
有两种方案,看你需求选:
方案1:用Services模块快速搞定(推荐)
- 先安装
services和services_rest模块(注意选和Drupal 7匹配的版本) - 进入
admin/services新建一个REST服务,比如命名为flag_api - 在服务的资源列表里添加
flag资源,然后勾选flag和unflag这两个操作,记得设置好访问权限(比如只允许登录用户调用,别开成公共的) - 保存后就有可用的端点了:
- 标记节点:
POST /flag_api/flag/你的标记名称/节点ID - 取消标记:
POST /flag_api/flag/你的标记名称/节点ID?unflag=1
- 标记节点:
方案2:自定义模块写回调(更灵活可控)
如果不想依赖Services模块,自己写个小模块就行(比如叫custom_flag_api):
function custom_flag_api_menu() { $items = array(); // 定义API路由:api/flag/标记名/节点ID $items['api/flag/%/%'] = array( 'page callback' => 'custom_flag_api_toggle_flag', 'page arguments' => array(2, 3), 'access arguments' => array('access content'), // 这里根据你的需求改权限,比如用flag的专属权限 'type' => MENU_CALLBACK, 'delivery callback' => 'drupal_json_output', // 直接返回JSON ); return $items; } function custom_flag_api_toggle_flag($flag_name, $nid) { // 获取标记对象和节点 $flag = flag_get_flag($flag_name); $node = node_load($nid); if (!$flag || !$node) { drupal_json_output(array('status' => 'error', 'msg' => '无效的标记或节点')); return; } $current_user = $GLOBALS['user']; $action = isset($_POST['action']) ? $_POST['action'] : 'flag'; // 执行标记/取消标记操作 if ($action === 'flag') { $flag->flag('flag', $nid, $current_user); } elseif ($action === 'unflag') { $flag->flag('unflag', $nid, $current_user); } drupal_json_output(array('status' => 'success', 'action' => $action)); }
第二步:AngularJS前端处理请求
重点要搞定Drupal的CSRF令牌验证,不然请求会被拒绝:
先获取CSRF令牌:
在你的Angular应用初始化的时候,先拿一下Drupal的会话令牌:angular.module('你的应用名').run(function($http, $rootScope) { // 调用Drupal的令牌接口 $http.get('/services/session/token').then(function(res) { $rootScope.drupalCsrfToken = res.data; }); });标记节点的请求函数:
// 传入节点ID和标记名称 function flagNode(nid, flagName) { return $http({ method: 'POST', url: '/api/flag/' + flagName + '/' + nid, // 对应你后端的路由 headers: { 'X-CSRF-Token': $rootScope.drupalCsrfToken, // 必须带这个头 'Content-Type': 'application/x-www-form-urlencoded' }, data: 'action=flag' }); }取消标记的请求函数:
function unflagNode(nid, flagName) { return $http({ method: 'POST', url: '/api/flag/' + flagName + '/' + nid, headers: { 'X-CSRF-Token': $rootScope.drupalCsrfToken, 'Content-Type': 'application/x-www-form-urlencoded' }, data: 'action=unflag' }); }
第三步:踩坑提醒
- 权限要配对:记得在Drupal的权限设置里,给用户开
flag 你的标记名称和unflag 你的标记名称的权限,不然API调用会返回403 - 跨域问题:如果Angular和Drupal不在同一个域名,得给Drupal开CORS,可以装
cors模块,或者在.htaccess里加CORS响应头 - 先测后端:先用Postman或者curl测一下后端API能不能正常工作,确认没问题再接前端
这样操作下来,应该就能解决你AngularJS端无法标记/取消标记的问题了,我之前用这个方案顺利搞定了项目需求~
内容的提问来源于stack exchange,提问作者ZombieShellback
相关产品推荐
相关产品推荐

