如何在Yesod路由中接收UserId列表?解决作用域报错问题
在Yesod路由中接收UserId列表的正确姿势
这个问题我之前踩过坑!你遇到的报错是因为Yesod找不到UserIds这个类型——没错,你不需要自定义这个类型,直接用[UserId]就可以了,具体操作如下:
1. 修正路由规则
把你原来的路由:
/api/users/display/*UserIds DisplayR GET
改成:
/api/users/display/*[UserId] DisplayR GET
这里的*[UserId]告诉Yesod:这个位置要匹配多个路径片段,并把它们解析成UserId类型的列表。比如访问/api/users/display/123/456/789,就会把[UserId 123, UserId 456, UserId 789]作为参数传给DisplayR的处理函数。
2. 编写对应的Handler函数
你的Handler需要接收[UserId]类型的参数,比如:
getDisplayR :: [UserId] -> Handler Html getDisplayR userIds = do -- 这里写你的业务逻辑,比如根据ID列表查询用户 let userIdsStr = show userIds defaultLayout [whamlet| <h1>接收的用户ID列表 <p>#{userIdsStr} |]
只要你的UserId类型已经实例化了PathPiece类型类(比如是newtype UserId = UserId Int,Yesod会自动为Int派生PathPiece),那么列表的解析会自动完成——Yesod会逐个解析每个路径片段为UserId,然后组合成列表。
3. 备选方案:用查询参数传递列表
如果你的ID列表很长,用路径片段可能会碰到URL长度限制,这时候可以用查询参数的方式:
- 路由改成:
/api/users/display DisplayR GET - Handler里通过查询参数获取列表:
访问的时候用getDisplayR :: Handler Html getDisplayR = do -- 获取名为"ids"的查询参数列表 idsStr <- lookupGetParams "ids" -- 把字符串转换成UserId(这里需要处理转换失败的情况) case traverse (parsePathPiece @UserId) idsStr of Left err -> sendResponseStatus status400 [shamlet|<p>无效的ID格式:#{err}|] Right userIds -> do -- 处理业务逻辑 defaultLayout [whamlet|<p>用户ID列表:#{show userIds}|]/api/users/display?ids=123&ids=456&ids=789这样的URL即可。
内容的提问来源于stack exchange,提问作者Qwertie




