Search code examples
phparrayslaravelcollectionslaravel-8

Reset value on map / transform function failed - Laravel


When i tried to change the value of id to encrypted Id is using map function and transform function, it get zero value no string value or alpha numeric getting replaced .

but it is mandatory to encrypt all id's for API

Please Help me .

Function

 function getLatestArticle($profileId)
 {
   $data = Article::wherehas('articleTrans',function($query){
    $query->where('status', ApiConstants::PUBLISHED_STATUS);
   })->with(['articleTrans'=>function($q){
        $q->select('id','article_id','language_id','title','short_description','description','main_image');
        $q->where('status', ApiConstants::PUBLISHED_STATUS);
   }])->latest()->paginate(ApiConstants::D_PAGE_C);

   $data->getCollection()->transform(function ($value) {
    $value->id = encrypt($value->id);
    return $value;
   });
    return $data;
  }

Collection

  "latest_data": [
        {
            "id": 0,
            "profile_id": 3,
            "name": "Test",
            "trending": 0,
            "new_arrived": 0,
            "featured": 0,
            "reading_time": null,
            "has_series": 0,
            "status": 0,
            "created_by": 1,
            "updated_by": 1,
            "deleted_at": null,
            "created_at": "2022-03-24T10:27:16.000000Z",
            "updated_at": "2022-03-31T11:41:14.000000Z",
            "created_from": 1,
            "article_trans": {
                "id": 8,
                "article_id": 12,
                "language_id": 1,
                "title": "Test",
                "short_description": "Test",
                "description": "<p><strong>TestTestTestTestTestTestTest&nbsp;</strong></p>\r\n\r\n<p><strong>TestTestTestTestTestTestTestTestTestTestTestTestTest</strong></p>",
                "main_image": "1648117636_AXwwVY6JSmNTxmXIiRqGlXiePTl70chCkmMDlehp.jpeg",
                "image_url": "http://127.0.0.1:8000/storage/admin/article/image/1648117636_AXwwVY6JSmNTxmXIiRqGlXiePTl70chCkmMDlehp.jpeg"
            }
        }

Solution

  • Its not good solution to temporarily modify entity objects only for change API response format.

    Better solution is using DTO/Transformer classes. Good example of transformers implementation is https://fractal.thephpleague.com/transformers/

    In this way you can split presentation and model.

    Using any packages is optional, you can write simple transformer classes like this:

    // app/Transformers/ArticleTransformer.php
    final class ArticleTransformer
    {
        public static function transform(Article $article): array
        {
            return [
                'id' => encrypt($article->id),
                // any fields
            ];
    
            /*
               // or if you need change only one property
               return array_replace(
                  $article->toArray(), // or $article->jsonSerialize()
                  [
                      'id' => encrypt($article->id),
                  ],
               ); 
            */
        }
    
        public static function transformCollection(Collection $articles): Collection
        {
            return $collection->map(fn (Article $article): array => self::transform($article));
        }
    }
    

    Then use this transformer:

    return [
      'latest_data' => ArticleTransformer::transformCollection($latestArticles),
    ];
    

    Not very good, but should work:

    Override jsonSerialize/toArray method of model, in returning modify your id.