解密模型值的访问器不起作用

Posted

技术标签:

【中文标题】解密模型值的访问器不起作用【英文标题】:Accessor that decrypts model value isn't working 【发布时间】:2020-05-11 23:10:14 【问题描述】:

我有一个使用访问器和修改器来加密模型值的特性:

trait Encryptable

    public function getAttribute($key)
    
        $value = parent::getAttribute($key);

        if (in_array($key, $this->encryptable)) 
            $value = Crypt::decrypt($value);
            return $value;
         else 
            return $value;
        
    

    public function setAttribute($key, $value)
    
        if (in_array($key, $this->encryptable)) 
            $value = Crypt::encrypt($value);
        

        return parent::setAttribute($key, $value);
    
 

评论模型

protected $fillable = ['content','user_id','commentable_id', 'commentable_type'];
protected $encryptable = [
    'content'
];

评论控制器

public function storePostComment(Request $request, Post $Post)

    $this->validate($request, [
        'content' => 'required',
    ]);

    $comment = $post->comments()->create([
        'user_id' => auth()->user()->id,
        'content' => $request->content
    ]);
    
    
    dd($comment->content);
    //return new CommentResource($comment);

发生的情况是,当我通过 return new CommentResource($comment); 时,我得到了加密的 cmets 内容,但 dd($comment->content); 解密了 cmets 内容。如何解密整个评论对象,以便将其输出到资源中?

编辑评论资源

class CommentResource extends JsonResource

    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    
        return [
            'id' => $this->id,
            'content' => $this->content,
            'owner' => $this->owner,
        ];
    
 

编辑 2 以获得答案

这是我的尝试:

use App\Comment;

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class CommentResource extends JsonResource

    
    public function __construct(Comment $resource)
    
        $this->resource = $resource;
    
    
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    
        return [
            'id' => $this->id,
            'content' => $this->content,
            'owner' => $this->owner,
        ];
    

错误:

传递给 App\Http\Resources\CommentResource::__construct() 的参数 1 必须是 App\Http\Resources\Comment 的实例,给定 App\Comment 的实例,在 /Applications/MAMP/htdocs/my- 中调用app/app/Http/Controllers/Api/CommentController.php 第 31 行

编辑 3(最终编辑)

这是我想出来的:

我尝试了一堆不同的组合以及@Edwin Krause 的答案。我有另一个模型使用这种可加密特征并在一个工作正常的资源中输出。

为了给这个问题提供更多背景信息,我发现在测试中使用 assertJsonFragment 存在问题:

评论测试

/* @test **/
public function a_user_can_comment_on_a_post()

    $decryptedComment = ['content'=>'A new content']
    $response = $this->json('POST',  '/api/comment/' . $post->id, $decryptedComment);

        $response->assertStatus(201);

        $response->assertJsonStructure([
            'data' => [
                'owner',
                'content'
            ]
        ])
        ->assertJsonFragment(['content' => $decryptedContent['content']]);

assertJsonFragment 正在返回加密内容,因此失败,因为它正在针对解密的 cmets 内容进行测试。

我在控制器中使用dd(new CommentResource($comment)); 来检查内容是否正在解密,但不是。

我尝试在控制器方法中使用dd() 进行各种不同的故障排除,甚至在浏览器中进行测试。依然没有。我添加了@Edwin Krause 代码,但dd() 上仍然没有任何内容@

我终于很幸运,使用@Edwin Krause 摆脱了 dd() 并将我的控制器更改为:

工作代码与我的 CommentResource 中的 @Edwin Krause 答案相结合

$comment = Comment::create([
    'user_id' => auth()->user()->id,
    'content' => $request->content,
    'commentable_type' => 'App\Post',
    'commentable_id' => $post->id,
]);

return new CommentResource($comment);

测试变绿了。我试过dd(new CommentResource($comment));,内容仍然被加密。浏览器和assertJsonFragment 上的内容输出有效。我一定尝试了很多组合来尝试解决这个问题,我有点幸运。

我不确定为什么会这样,但我已经为此花费了数小时,所以我无法解决它为什么会崩溃。也许其他人可以。

【问题讨论】:

你能分享你的CommentResource代码吗? @apokryfos,刚刚在编辑中分享了它 在命名空间前添加use语句时出现同样的错误 不需要重写资源类的构造函数。只需使用$this->resource->content等访问模型的属性和方法即可。 【参考方案1】:

只是建议尝试覆盖 JsonResource 的构造函数并将 $resource 参数类型转换为您的模型类。 它适用于其他事情,不确定它是否能解决您的问题,需要测试

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;
use App\Comment;

class CommentResource extends JsonResource


  public function __construct(Comment $resource)
  
    $this->resource = $resource;
    $this->resource->content = $resource->content;
  

  ....

编辑: 我对构造函数进行了更多尝试,修改后的版本应该可以正常工作。我没有任何加密数据可以使用,但从逻辑上讲这应该可以。

【讨论】:

感谢您的帮助。这是我得到的:>传递给 App\Http\Resources\CommentResource::__construct() 的参数 1 必须是 App\Http\Resources\Comment 的实例,给定的 App\Comment 实例 不要忘记use App\Comment; 声明,如果这是您的模型所在的位置 你的 use 语句应该在命名空间下面 谢谢,这消除了错误,但不幸的是我的内容仍然没有解密。 嘿,我编辑了我的问题。我得到了答案,但我不确定发生了什么。我认为你在其中扮演了一个角色。如果您知道发生了什么并想编辑您的答案,我一定会将您的答案标记为正确。当您更改答案时,请提醒我。再次感谢您。

以上是关于解密模型值的访问器不起作用的主要内容,如果未能解决你的问题,请参考以下文章

模式中的引导日期选择器不起作用

CAD2014安全系统软件锁许可管理器不起作用或未正确安装

引导日期选择器不起作用

为啥 AVPlayer 边界时间观察器不起作用?

Jquery $('class', this) 选择器不起作用

Weka 分类器不起作用