如何在外部PHP文件中访问Drupal的用户对象?
嘿,我明白你遇到的麻烦了——把自定义的upload.php作为CKEditor的文件浏览器,却没办法获取登录用户的UID,还得调整Apache重写规则才能访问它。这本质上是因为你的upload.php没融入Drupal的运行环境,咱们一步步来解决:
为什么$user->uid没有值?
Drupal的用户会话、权限这些核心功能,都是通过它的引导流程初始化的。你的upload.php是一个独立的文件,没有加载Drupal的核心引导文件,所以它完全不知道当前有没有用户登录,自然拿不到$user->uid的值。
另外,你提到要把/userfiles加入Apache重写例外,这是因为Drupal默认的.htaccess规则会把所有非真实文件/目录的请求转发到index.php(也就是Drupal的入口)。如果/userfiles没被例外,访问upload.php时就会被转去index.php?q=/userfiles/upload.php,自然无法正常加载你的文件。
解决方案一:让upload.php加载Drupal环境
如果你想保留现有的upload.php文件,只需要在文件最顶部加入Drupal的引导代码,就能让它获取到Drupal的用户会话:
// 注意:这里的路径要根据你的Drupal根目录位置调整 // 假设你的upload.php在 /userfiles/ 下,Drupal根目录在上级目录 include_once '../includes/bootstrap.inc'; // 初始化Drupal到完整引导阶段,这样就能获取用户信息 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); // 现在就能正常判断用户是否登录了 if ($user->uid == 0) { // 未登录用户直接返回403禁止访问 header("HTTP/1.1 403 Forbidden"); exit; } // 下面写你原来的上传逻辑代码...
关于Apache重写规则的调整
其实你不需要把整个/userfiles目录加入例外——只要你的upload.php是真实存在的文件,Drupal默认的.htaccess规则里的RewriteCond %{REQUEST_FILENAME} !-f会自动跳过它(这条规则的意思是:如果请求的是真实存在的文件,就不转发到index.php)。如果你之前必须加例外才能访问,可能是你的.htaccess被修改过,或者upload.php的路径有问题,检查一下规则里有没有额外限制/userfiles的条目。
解决方案二:改用Drupal自定义菜单回调(推荐)
更符合Drupal最佳实践的方式是,不要用独立的upload.php,而是在自定义模块里创建一个专属的回调路径,这样完全在Drupal环境里运行,不用处理外部文件的引导问题:
- 创建一个自定义模块(比如叫
ckeditor_upload),在模块文件里添加菜单路由:
function ckeditor_upload_menu() { $items['admin/ckeditor/upload'] = array( 'title' => 'CKEditor 文件上传', 'page callback' => 'ckeditor_upload_handler', 'access arguments' => array('upload files'), // 可以换成你需要的权限 'type' => MENU_CALLBACK, ); return $items; }
- 编写上传处理的回调函数:
function ckeditor_upload_handler() { global $user; // 直接判断用户是否登录(或者检查更细的权限) if ($user->uid == 0) { drupal_access_denied(); return; } // 这里写入你的上传逻辑,和原来的upload.php代码一致 }
- 在CKEditor的配置里,把文件浏览器的路径设置为
/admin/ckeditor/upload即可。
这种方式的好处是:天然继承Drupal的权限体系,不用手动处理用户会话,也不需要调整Apache重写规则,后续维护起来更方便。
内容的提问来源于stack exchange,提问作者Markus

