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

Elixir Phoenix未登录报function nil.id/0 is undefined错误排查

问题原因

报错触发逻辑非常明确:

  • 未登录用户访问页面时,控制器传递给模板的@current_user赋值为nil
  • 现有判断逻辑直接执行@current_user.id,等价于调用nil.id/0函数,而nil是Elixir内置原子类型,不存在id成员方法,因此抛出UndefinedFunctionError异常
  • 原判断逻辑没有做空值兜底,只要用户未登录就会触发报错,和帖子本身的权限归属判断无关
修复方案

1. 模板层快速修复

调整判断顺序,优先校验@current_user非空,再执行用户ID比对,利用Elixir&&运算符的短路特性,空值场景下不会执行后续的ID取值逻辑。修正后的模板代码如下:

<%= if @current_user && @current_user.id == @post.user_id do %>
  <span>
    <%= link "Edit", to: Routes.post_path(@conn, :edit, @post) %>
  </span>
  <span>
    <%= link "Delete", to: Routes.post_path(@conn, :delete, @post), method: :delete, data: [confirm: "Are you sure"] %>
  </span>
<% end %>

2. 工程化规范实现

不建议把权限判断逻辑直接散落在模板中,后续迭代很容易出现漏判,推荐把权限逻辑抽成可复用的辅助函数:

  • 在对应视图模块(通用权限逻辑可以放到全局Helper模块,帖子相关逻辑可以放到PostView)编写带模式匹配的判断函数:
defmodule MyAppWeb.PostView do
  use MyAppWeb, :view

  # 未登录用户直接返回无权限
  def can_modify_post?(nil, _post), do: false
  # 登录用户比对ID判断是否为帖子作者
  def can_modify_post?(user, post), do: user.id == post.user_id
end
  • 模板中直接调用该函数即可,代码更简洁,后续扩展(比如增加管理员可编辑的权限规则)时只需要修改辅助函数,不需要逐个调整模板:
<%= if can_modify_post?(@current_user, @post) do %>
  <span>
    <%= link "Edit", to: Routes.post_path(@conn, :edit, @post) %>
  </span>
  <span>
    <%= link "Delete", to: Routes.post_path(@conn, :delete, @post), method: :delete, data: [confirm: "Are you sure"] %>
  </span>
<% end %>

注意:模板层的按钮隐藏只是前端交互层面的体验优化,必须在控制器层的edit、update、delete动作中加同样的权限校验,避免用户直接构造请求绕过前端限制触发越权操作。

内容的提问来源于stack exchange,提问作者Aleksandr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:39:38