You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过AngularJS远程标记或取消标记Drupal 7节点?

解决Drupal 7 + Flags模块 + AngularJS的标记/取消标记问题

哈哈,这个问题我之前在做Drupal+Angular混合项目的时候踩过一模一样的坑!核心原因就是Flags模块本身没默认提供可供前端调用的REST接口——网站端能用是因为它走了Drupal的内部路由,而AngularJS属于前端独立调用,得自己给Flag操作搭后端API,再处理好Drupal的CSRF验证就行,给你一步步拆解:

第一步:给后端搭Flag操作的API端点

有两种方案,看你需求选:

方案1:用Services模块快速搞定(推荐)

  1. 先安装services和services_rest模块(注意选和Drupal 7匹配的版本)
  2. 进入admin/services新建一个REST服务,比如命名为flag_api
  3. 在服务的资源列表里添加flag资源,然后勾选flag和unflag这两个操作,记得设置好访问权限(比如只允许登录用户调用,别开成公共的)
  4. 保存后就有可用的端点了:
    • 标记节点: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令牌验证,不然请求会被拒绝:

  1. 先获取CSRF令牌:
    在你的Angular应用初始化的时候,先拿一下Drupal的会话令牌:

    angular.module('你的应用名').run(function($http, $rootScope) {
      // 调用Drupal的令牌接口
      $http.get('/services/session/token').then(function(res) {
        $rootScope.drupalCsrfToken = res.data;
      });
    });
    
  2. 标记节点的请求函数:

    // 传入节点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'
      });
    }
    
  3. 取消标记的请求函数:

    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:01:29