Laravel Array & JSON Casting to Algolia

I am trying to send some data along to Algolia through the toSearchableArray. Any strings I have stored in my DB are sending along fine, but I hit a roadblock when trying to push nested JSON data along—the information is being sent as a string with characters escaped.

This is a sample of the nested object that I am storing in my table (MySQL with a JSON data type):

[
    {
        "id": 19, 
        "name": "Mathematics", 
        "short": "Math"
    }, 
    {
        "id": 23, 
        "name": "Science", 
        "short": "Science"
    }, 
    {
        "id": 14, 
        "name": "Health and Life Skills", 
        "short": "Health"
    }
]

My model looks like this:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Resource extends Model
{
    use Searchable;
    protected $primaryKey = 'objectID';

    public function toSearchableArray()
    {
        $data = $this->toArray();

        $data['grades'] = explode(';', $data['grades']);
        $data['units'] = explode(';', $data['units']);

        return $data;
    }
}

I get an output that looks like this:

array:22 [
  "objectID" => 1
  "name" => "Resource #1"
  "slug" => "resource-1"
  "write_up" => """
    This is an example write up.
    """
  "author" => "johnny"
  "type_name" => "Lesson Plan"
  "language" => "English"
  "grades" => array:3 [
    0 => "Kindergarten"
    1 => "Grade 1"
    2 => "Grade 4"
  ]
  "subjects" => "[{"id": 19, "name": "Mathematics", "short": "Math"}, {"id": 23, "name": "Science", "short": "Science"}, {"id": 14, "name": "Health and Life Skills", "short": "Health"}]"
  "units" => array:2 [
    0 => "Unit A"
    1 => "Unit B"
  ]
  "main_image" => "https://dummyimage.com/250x325/000000/fff.png&text=Just+a+Test"
  "loves" => 88
  "downloads" => 280
  "created_at" => "2018-01-01 13:26:47"
  "updated_at" => "2018-01-02 10:10:32"
]

As you can see, the ‘subjects’ attribute is being stored as a string. I know there is attribute casting in 5.5 (I am running 5.5), but I am not too clear on how I would implement the example they have for Array & JSON Casting in my work above. https://laravel.com/docs/5.5/eloquent-mutators#attribute-casting

Would anyone be willing to show me an example?

You can do it manually, just the way you explode grades and units

    public function toSearchableArray()
    {
        $data = $this->toArray();

        $data['grades'] = explode(';', $data['grades']);
        $data['units'] = explode(';', $data['units']);

        $data['subjects'] = json_decode($this->subjects, true);

        return $data;
    }

But I’d prefer relying on Laravel to do it automatically with Attribute Casting:
(note the new $casts attrubute)

class Resource extends Model
{
    use Searchable;
    protected $primaryKey = 'objectID';

    protected $casts = [
        'subjects' => 'array',
    ];

    public function toSearchableArray()
    {
        $data = $this->toArray();

        $data['grades'] = explode(';', $data['grades']);
        $data['units'] = explode(';', $data['units']);

        return $data;
    }
}

Please let me know if that worked for you.

1 Like

Dude, I could kiss you! This worked perfectly!

Thanks for providing two solutions as well. You’re a lifesaver!

1 Like