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

Kyl*_*rst 5 encryption accessor laravel laravel-6

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

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);
    }
} 
Run Code Online (Sandbox Code Playgroud)

评论模型

protected $fillable = ['content','user_id','commentable_id', 'commentable_type'];
protected $encryptable = [
    'content'
];
Run Code Online (Sandbox Code Playgroud)

评论控制器

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);
}
Run Code Online (Sandbox Code Playgroud)

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

编辑评论资源

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,
        ];
    }
} 
Run Code Online (Sandbox Code Playgroud)

编辑 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,
        ];
    }
}
Run Code Online (Sandbox Code Playgroud)

错误:

传递给 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']]);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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

return new CommentResource($comment);
Run Code Online (Sandbox Code Playgroud)

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

我不确定为什么会这样,但我已经在这上面花了几个小时,所以我无法解决它为什么会崩溃。也许别人可以。

Edw*_*use 1

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

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;
  }

  ....
Run Code Online (Sandbox Code Playgroud)

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