> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Customize searchable data

> Scout Extended transforms your model into Algolia records. You can override this to customize what data you want to index.

## Customize records

Scout Extended transforms your model into Algolia records with the `toSearchableArray` method. You can override this method to customize what data you want to index.

```php PHP icon=code theme={"system"}
class Article extends Model
{
    use Searchable;

    /**
     * Get the indexable data array for the model.
     *
     * @return array
     */
    public function toSearchableArray()
    {
        $array = $this->toArray();

        // Applies Scout Extended default transformations:
        $array = $this->transform($array);

        // Add an extra attribute:
        $array['added_month'] = substr($array['created_at'], 0, 7);

        return $array;
    }
}
```

<Info>
  To know more about the `transform` method check the section [Transformers](#transformers).
</Info>

## Relationships

Algolia doesn't perform any `JOIN` operations.
All searchable data must exist in each record.
This means that model relationships aren't indexed by default. If you want to index relationships within a record, you need to override the `toSearchableArray` method in your model and include the relationships you want to index.

### Add attributes from relations

For example, if you are indexing articles and each article has one author, all you need to do is add its full name or email.

```php PHP icon=code theme={"system"}
public function toSearchableArray()
{
    $array = $this->toArray();

    $array = $this->transform($array);

    $array['author_name'] = $this->author->name;
    $array['author_email'] = $this->author->email;

    return $array;
}
```

### Many-to-many

If you want to index the entire relationship you can do it by loading them before calling the `toArray` method.

The resulting object has categories,
converted to an array by Laravel:

```php PHP icon=code theme={"system"}
public function toSearchableArray()
{
    /**
     * Load the categories relation so that it's
     * available in the Laravel toArray() method
     */
    $this->categories;

    $array = $this->toArray();

    $array = $this->transform($array);

    return $array;
}
```

It could be that not all data from the relation.
To clean up the data, you can do something like this:

```php PHP icon=code theme={"system"}
public function toSearchableArray()
{
    $array = $this->toArray();

    $array = $this->transform($array);

    $array['categories'] = $this->categories->map(function ($data) {
        return $data['name'];
    })->toArray();

    return $array;
}
```

<Info>
  Algolia has [a size limit per record](https://support.algolia.com/hc/en-us/articles/4406981897617-Is-there-a-size-limit-for-my-index-records-/),
  so you should just index the data you need.
</Info>

## Update relations when parents or children change

After embedding information from a relation in your record,
you might want to keep them up to date when you change the relation.

Depending on the relationship type between your models,
you have two solutions:
using the `$touches` property,
and listening for the `saved` event.

### The `$touches` property

Laravel has a [built-in feature](https://laravel.com/docs/eloquent-relationships#touching-parent-timestamps) to let the parent relationship know that one of their children has changed.

In a typical `Article <=> Comment` example,
all you would need to do is add `article` to the `$touches` property.

```php PHP icon=code theme={"system"}
class Comment extends Model
{
    use Searchable;

    protected $touches = ['article'];

    public function article()
    {
        return $this->belongsTo(Article::class);
    }
}
```

<Note>
  This method only works with `belongsTo` and `belongsToMany` relationships.
</Note>

### The `saved` event

If you use any other relationship,
listen to the `saved` event and trigger the indexing.

```php PHP icon=code theme={"system"}
class Author extends Model
{
    public static function boot()
    {
        parent::boot();

        static::saved(function ($model) {
            $model->articles->filter(function ($item) {
                return $item->shouldBeSearchable();
            })->searchable();
        });
    }

    public function articles()
    {
        return $this->hasMany(Article::class);
    }
}
```

## Transformers

Some builder methods such as `where` and `whereBetween` require numeric values. For this reason, if `toSearchableArray` isn't defined, Scout Extended transforms, by default:

* Dates into `timestamps`
* Numeric strings into `integers` or `floats`.

You can overwrite this behavior by implementing the `toSearchableArray` method:

```php PHP icon=code theme={"system"}
public function toSearchableArray()
{
    $array = $this->toArray();

    // If you want, apply the default transformations
    $array = $this->transform($array);

    // Apply custom treatment

    return $array;
}
```

### Custom transformers

One of the primary benefits of creating a `Transformer` class is the ability to type-hint any dependencies your transformer may need in its constructor. **The declared dependencies are automatically resolved and injected into the transformer instance.**

To write a transformer:

<Steps>
  <Step title="Create a new class">
    The class implements `Algolia\ScoutExtended\Contracts\TransformerContract`.
    The `transform` method should transform the given `$value` as needed:

    ```php PHP icon=code theme={"system"}
    namespace App\Search\Transformers;

    use App\Contracts\TransformService;
    use Algolia\ScoutExtended\Contracts\TransformerContract;

    class CustomTransformer implements TransformerContract
    {
        /**
         * @var \App\Contracts\TransformService
         */
        protected $service;

        /**
         * Creates a new instance of the class.
         *
         * @param  \App\Contracts\TransformService $service
         *
         * @return void
         */
        public function __construct(TransformService $service)
        {
            $this->service = $service;
        }

        /**
         * Transforms the given array.
         *
         * @param  object $searchable
         * @param  array $array
         *
         * @return array
         */
        public function transform($searchable, array $array): array
        {
            $array = $this->service->transform($searchable->articleType, $array);

            return $array;
        }
    }
    ```
  </Step>

  <Step title="Apply a custom transform">
    Send the `$array` into the `transform` method and specify the transformers to apply.

    ```php PHP icon=code theme={"system"}
    public function toSearchableArray()
    {
        $array = $this->toArray();

        // Apply the custom transformations
        $array = $this->transform($array, [
            \App\Search\Transformers\CustomTransformer::class
        ]);

        return $array;
    }
    ```
  </Step>
</Steps>
