拔出数据后如何触发口才的访问者

时间:2019-02-20 22:31:01

标签: php eloquent laravel-5.7

目标

我希望能够在发送JSON响应时混淆我的ID。

我尝试了

创建如下的accessor

public function getIdAttribute()
{
    return Crypt::encrypt($this->attributes['id']);
}

但是这破坏了我的关系,因为(我从中学到的)访问器在查询之前就已经运行了。

问题

是否有任何方法告诉Eloquent在结果被拉出后触发访问器?

3 个答案:

答案 0 :(得分:0)

您的访问器方法永远不要对属性执行任何操作。相反,使用该方法后(即获得ID的值),必须使用encrypyt。

答案 1 :(得分:0)

找到了使用Response macros来实现我的预期的另一种方法:

app / Providers / AppServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Crypt;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        JsonResponse::macro('secured', function () {
            $data = json_decode(json_encode(JsonResponse::getData()), $toArray = true);

            array_walk_recursive($data, function(&$value, $key) {
                if ($key === 'id') {
                    $value = Crypt::encrypt($value);
                }
            });

            return $data;
        });
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

然后,在您的任何控制器上:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Post;

class PostController extends Controller
{
    public function index(Request $request)
    {
        if ($request->wantsJson() || $request->ajax()) {
            return response()->json(Post::all())->secured();
        }
    }
}

警告

我的数据库架构假定每个主键都被命名为“ id”。如果您复制/粘贴此内容,请记住这一点!

答案 2 :(得分:0)

我在这里看到2个选项。

1。

考虑到您可能希望API使用者能够请求/更新/删除您需要标识的单个对象,您可以向表中添加uuid字段,而不是公开您的ID?

这样,您仍然可以为对象提供唯一的标识符,但是无法猜测。

2。

如果您不想添加额外的字段并且想对ID进行加密,为什么不使用资源响应对象呢?

这将使您可以在返回之前自定义响应。

请参阅:https://laravel.com/docs/5.7/eloquent-resources#resource-responses

因此在您的控制器中:

public function index(Request $request)
{
    $posts = Post::all();

    return new PostResourceCollection($posts);
}

具有ID加密的PostResource

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;
use Crypt;

class PostResource extends Resource
{
    public function toArray($request)
    {
        return [
            'id' => Crypt::encrypt($this->id]),
            'x' => $this->x,
            'y' => $this->y,
        ];
    }
}

PostResourceCollection,它仅在PostResource上调用集合

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class PostResourceCollection extends ResourceCollection
{
    public function toArray($request)
    {
        return PostResource::collection($this->collection);
    }
}