davy_yg's avatar
Level 27

json_encode

I wonder why after json_encode an array the value changes?

For example:

the value of dd($data['product']);

    LengthAwarePaginator {#2707 ▼
    #total: 8
    #lastPage: 1
    #items: Collection {#2676 ▼
      #items: array:8 [▼
        0 => ProductCatalog {#2485 ▼
        +translatedAttributes: array:14 [▶]
        #guarded: []
        #searchableColumns: array:14 [▶]
        #appends: array:1 [▶]
        #connection: "mysql"
        #table: "product_catalogs"
        #primaryKey: "id"
        #keyType: "int"
        +incrementing: true
        #with: []
        #withCount: []
        #perPage: 15
        +exists: true
        +wasRecentlyCreated: false
        #attributes: array:48 [▼
        "id" => 1565
        "product_category_id" => 202
         "master_data_nutrition_id" => null
        "master_data_format_id" => 41
        "is_archive" => 0
        "created_at" => "2019-10-11 09:45:01"
        "updated_at" => "2019-10-11 09:45:01"
        "weight" => null
        "refund" => 0
        "max_refund" => null
        "deleted_at" => null
        "brand_id" => 20
        "kode_product" => "9367011290038"
        "kode_product_supplier" => "9367011290038"
        "key_nutrition_specific_id" => null
        "benefit_specific_id" => null
        "how_to_consume" => null
      "is_saleable" => 0
      "is_stock_managed" => 0
      "is_batch_managed" => 0
      "kematangan" => "[]"
      "flag_product" => "0"
      "sold" => 0
      "rating" => 0.0
      "osa_score" => 0
      "slug" => "roasted-organic-pistachio-unsalted-sesa"
      "order_new" => null
      "freshness" => 1236
      "product_catalog_id" => 519
      "locale" => "en"
      "subtitle" => "xxx"
      "name" => "Roasted Organic Pistachio Unsalted Sesa"
      "warehouse" => null
      "description" => """
        Roasted Organic Pistachio Unsalted has undergone a unique dry roasting in our own factory with no salt addition. Pistachio has a savory taste like butter and de ▶
        
        Caution:

        Consumer with food or nut allergies, please read the ingredient statement carefully. Store in a cool and dry place.
        """
      "nutrition_fact" => null
      "word_of_coution" => null
      "certification" => "null"
      "packaging" => null
      "product_name_bpom" => null
      "ingredient" => null
      "key_ingredient" => null
      "key_nutrition_general" => null
      "benefit_general" => null
      "function_of_food" => null
      "tagline" => "<p>Healthy Bone<br>Neutral Taste<br>Mixture For Any Dish</p>"
      "rating_acessor" => "0,0"
      "qty_acessor" => 0
      "product_image_acessor" => "http://127.0.0.1:8000/img/cache/square-medium/default.png"
    ]

note: pay attention to name. It has a value in it.

Now, dd(json_encode($data['product']));

"{"current_page":1,"data":[{"id":1565,"product_category_id":202,"master_data_nutrition_id":null,"master_data_format_id":41,"is_archive":0,"created_at":"2019-10-11 09:45:01","updated_at":"2019-10-11 09:45:01","weight":null,"refund":0,"max_refund":null,"deleted_at":null,"brand_id":20,"kode_product":"9367011290038","kode_product_supplier":"9367011290038","key_nutrition_specific_id":null,"benefit_specific_id":null,"how_to_consume":null,"is_saleable":0,"is_stock_managed":0,"is_batch_managed":0,"kematangan":"[]","flag_product":"0","sold":0,"rating":0,"osa_score":0,"slug":"roasted-organic-pistachio-unsalted-sesa","order_new":null,"freshness":1236,"product_catalog_id":519,"locale":"en","subtitle":"xxx","name":null,"warehouse":null,"description":null,"nutrition_fact":null,"word_of_coution":null

Now, name equals null. This is strange. Any clue why?

0 likes
18 replies
JohnBraun's avatar

The LengthAwarePaginator class implements the Jsonable interface, as you can see here.

This means that it has a method toJson as you can see below. This in turn makes use of the toArray() method which returns the result as you posted after the json_encode() transformation.

class  LengthAwarePaginator
{
    // other methods...

    /**
     * Get the instance as an array.
     *
     * @return array
     */
    public function toArray()
    {
        return [
            'current_page' => $this->currentPage(),
            'data' => $this->items->toArray(),
            'first_page_url' => $this->url(1),
            'from' => $this->firstItem(),
            'last_page' => $this->lastPage(),
            'last_page_url' => $this->url($this->lastPage()),
            'next_page_url' => $this->nextPageUrl(),
            'path' => $this->path(),
            'per_page' => $this->perPage(),
            'prev_page_url' => $this->previousPageUrl(),
            'to' => $this->lastItem(),
            'total' => $this->total(),
        ];
    }

    /**
     * Convert the object into something JSON serializable.
     *
     * @return array
     */
    public function jsonSerialize()
    {
        return $this->toArray();
    }

    /**
     * Convert the object to its JSON representation.
     *
     * @param  int  $options
     * @return string
     */
    public function toJson($options = 0)
    {
        return json_encode($this->jsonSerialize(), $options);
    }
}
davy_yg's avatar
Level 27

Yes, but name next to subtitle shouldn't be replaced by null?

JohnBraun's avatar

How I would debug this, is by checking what the value of $this->items->toArray() is in the toArray() method of the paginator class (by using the dd() function before the return statement. What does this give you?

davy_yg's avatar
Level 27

It's something like this:

array:12 [▼
 "current_page" => 1
 "data" => array:4 [▼
   0 => array:54 [▼
  "id" => 519
  "product_category_id" => 202
  "master_data_nutrition_id" => null
  "master_data_format_id" => 41
  "is_archive" => 0
  "created_at" => "2019-10-11 09:45:01"
  "updated_at" => "2019-12-11 18:11:14"
  "weight" => null
  "refund" => 0
  "max_refund" => null
  "deleted_at" => null
  "brand_id" => 20
  "kode_product" => "9367011290038"
  "kode_product_supplier" => "9367011290038"
  "key_nutrition_specific_id" => null
  "benefit_specific_id" => null
  "how_to_consume" => null
  "is_saleable" => 0
  "is_stock_managed" => 0
  "is_batch_managed" => 0
  "kematangan" => "[]"
  "flag_product" => "0"
  "sold" => 0
  "rating" => 0.0
  "osa_score" => 0
  "slug" => "roasted-organic-pistachio-unsalted-sesa"
  "order_new" => null
  "freshness" => 1236
  "rating_acessor" => "0,0"
  "qty_acessor" => 0
  "product_image_acessor" => "http://127.0.0.1:8000/img/cache/square-medium//storage/media/1978/5dc29b229828a_34_Roasted-Organic-Pistachio-Unsalted-SESA-250-g.jpg"
  "kematangan_acessor" => []
  "name" => "Kacang Pistacio Organik Panggang Sesa"
  "warehouse" => null
  "description" => """
    Kacang Pistacio organik panggang yang diproses dengan pemanggangan kering di pabrik kami sendiri tanpa tambahan garam laut. Kacang Pistacio memiliki rasa gurih  ▶
    


    Perhatian:


    Konsumen yang memiliki alergi terhadap makanan atau kacang, harap membaca komposisi bahan dengan hati-hati. Simpan di tempat sejuk dan kering.
    """
  "nutrition_fact" => null
  "word_of_coution" => null
  "certification" => "null"
  "packaging" => null
  "product_name_bpom" => null
  "ingredient" => null
  "key_ingredient" => null
  "key_nutrition_general" => null
  "benefit_general" => null
  "function_of_food" => null
  "tagline" => "<p>Kesehatan Tulang<br>Rasa Netral<br>Campuran Hidangan</p>"
  "price" => array:2 [▶]
  "default_media" => null
  "product_review" => []
  "product_catalog_translation" => array:2 [▶]
  "benefit_specific" => null
  "data_format" => array:6 [▶]
  "translations" => array:2 [▶]
  "media" => array:2 [▶]
]
1 => array:54 [▶]
2 => array:54 [▶]
3 => array:54 [▶]
 ]
"first_page_url" => "http://127.0.0.1:8000/filter/pistachios?page=1"
"from" => 1
"last_page" => 1
"last_page_url" => "http://127.0.0.1:8000/filter/pistachios?page=1"
"next_page_url" => null
  "path" => "http://127.0.0.1:8000/filter/pistachios"   
  "per_page" => "24"
  "prev_page_url" => null
  "to" => 4
  "total" => 4
]

name has a value.

JohnBraun's avatar

Allright, so far so good. What if you dump the return value in the toJson() method?

dd(json_encode($this->jsonSerialize(), $options));
YeZawHein's avatar

Php documentation said "All string data must be UTF-8 encoded." You can use utf8_encode .

function utf8ize($data) {
    if (is_array($data)) {
        foreach ($data as $k => $v) {
            $data[$k] = utf8ize($v);
        }
    } else if (is_string ($data)) {
        return utf8_encode($data);
    }
    return $data;
}

dd(json_encode(utf8ize($data));)
davy_yg's avatar
Level 27

"{"current_page":1,"data": [{"id":1153,"product_category_id":null,"master_data_nutrition_id":null,"master_data_format_id":null,"is_archive":0,"created_at":"2019-12-18 14:47:23","updated_at":"2019-12-24 14:23:17","weight":null,"refund":0,"max_refund":null,"deleted_at":null,"brand_id":20,"kode_product":null,"kode_product_supplier":null,"key_nutrition_specific_id":null,"benefit_specific_id":17,"how_to_consume":null,"is_saleable":0,"is_stock_managed":0,"is_batch_managed":0,"kematangan":"[]","flag_product":"0","sold":0,"rating":0,"osa_score":0,"slug":"kacang-pistachios-250-g","order_new":null,"freshness":1378,"rating_acessor":"0,0","qty_acessor":0,"product_image_acessor":"http://127.0.0.1:8000/img/cache/square-medium//storage/media/2461/5df9e143297e7_pistachios.jpg","kematangan_acessor":[],"name":"Kacang Pistachios Mentah","warehouse":null,

name is there. What happened?

JohnBraun's avatar

In that case, you could use $data['product']->toJson() instead of encoding the object yourself. I think it goes wrong when you try to json_encode the paginator object, which first needs to transform itself to an array.

davy_yg's avatar
Level 27

I tried again:

        dd($data['product']->toJson());

and the name turns to null again. While in dd($data['product']) it never null.

with this one also sometimes it works and sometimes it does not.

d($data['product']->jsonSerialize());

It works at first, then eventually it does not. name still null.

and what kind of code @yezawhein is that?

Call to undefined function App\Http\Controllers\utf8ize()

I get that error message if I tried it.

JohnBraun's avatar

That's weird. I don't see what we're missing here now...

davy_yg's avatar
Level 27

The same thing also to:

     dd($data['product']->toArray());

name shows null eventually. it only has value if I do this: dd(data['product']);

JohnBraun's avatar

Did you override the toArray() method on the model? Do you have a custom getter (getNameAttribute()) ?

davy_yg's avatar
Level 27

What do you mean?

To cek the value I usually comment out the rest:

// dd($data['product']->jsonSerialize());
    // dd(json_encode(utf8ize($data['product'])));
    dd($data['product']->toArray());
    // dd(json_encode($data['product']->jsonSerialize()));
    // dd(json_encode($data['product']));
davy_yg's avatar
Level 27

The model is taken from:

ProductCatalogRepository.php

 public function __construct(ProductCatalog $model)
    {
    $this->model = $model;
    }

It eventually turns into $data['product'] , it's a long process. I just need to make sure when I json encode the value does not change since it gives error it does.

What is custom getter (getNameAttribute()) ?

There are several names in the relation table:

 []
    #relations: array:8 [▼
      "price" => Collection {#2484 ▶}
      "defaultMedia" => null
      "productReview" => Collection {#2442 ▶}
      "productCatalogTranslation" => Collection {#2544 ▶}
      "benefitSpecific" => null
      "dataFormat" => MasterDataFormat {#2704 ▼
        +translatedAttributes: array:1 [▶]
        #guarded: []
        #searchableColumns: array:1 [▶]
        #connection: "mysql"
        #table: "master_data_formats"
        #primaryKey: "id"
        #keyType: "int"
        +incrementing: true
        #with: []
        #withCount: []
        #perPage: 15
        +exists: true
        +wasRecentlyCreated: false
        #attributes: array:4 [▶]
        #original: array:4 [▶]
        #changes: []
        #casts: []
        #dates: []
        #dateFormat: null
        #appends: []
        #dispatchesEvents: []
        #observables: []
        #relations: array:1 [▼
          "translations" => Collection {#2711 ▼
            #items: array:2 [▼
              0 => MasterDataFormatTranslation {#2736 ▼
                #fillable: array:1 [▶]
                #connection: "mysql"
                #table: "master_data_format_translations"
                #primaryKey: "id"
                #keyType: "int"
                +incrementing: true
                #with: []
                #withCount: []
                #perPage: 15
                +exists: true
                +wasRecentlyCreated: false
                #attributes: array:6 [▼
                  "id" => 81
                  "master_data_format_id" => 41
                  "locale" => "en"
                  "name" => "Roasted"
                  "created_at" => "2019-09-24 17:39:38"
                  "updated_at" => "2019-09-24 17:39:38"
                ]
                #original: array:6 [▶]

I am afraid if I use ->toJson(), it cannot tells which name it is? My product catalog name is being replace to data format name I am afraid in the GalleryList.vue which will gives error.

How to handle this?

martinbean's avatar

@davy_yg json_encode-ing a LengthAwarePaginator instance will call toArray on each item in the paginator’s collection. So if you have an array of models, it will call `toArr on each of those model instances.

You need to find out why toArray is messing with your attributes. You’ve probably got a mutator or something defined.

davy_yg's avatar
davy_yg
OP
Best Answer
Level 27

I think it finally works. I just have to narrow down my select to the fields I need:

 $products = $products
                ->join('product_catalog_translations as t', 'product_catalogs.id', '=', 't.product_catalog_id')
                ->orderBy('freshness')
                ->orderBy('t.subtitle')->select('product_catalogs.*');

Please or to participate in this conversation.