Home > Software engineering >  How can I make a casted array searchable with Laravel Scout and TNTSearch?
How can I make a casted array searchable with Laravel Scout and TNTSearch?

Time:04-20

I'm currently working on a blog in Laravel 8.

The Article model is made like this:

protected $fillable = [
        'title',
        'subtitle',
        'body',
        'category',
        'view_count',
        'published_at',
        'tags'
    ];

protected $casts = [
        'published_at' => 'date:d-m-Y',
        'tags' => 'array'
    ];

I'd like to index my Article model, to make it searchable by title, subtitle, body and tags (which is the field that gives my problems).

For searching, I'm using Laravel Scout with TNTSearch. My toSearchableArray() function is the following:

public function toSearchableArray()
    {
        $array = [
            'id' => $this->id,
            'title' => $this->title,
            'subtitle' => $this->subtitle,
            'body' => $this->body,
            'tags' => $this->tags
        ];

        return $array;
    }

The problem is that when I launch php artisan scout:import "App\Models\Article" I receive this error:

mb_strtolower(): Argument #1 ($string) must be of type string, array given

  at C:\Users\Davide\working_area_davide\Freelance\sito_alvise_L8\vendor\teamtnt\tntsearch\src\Support\Tokenizer.php:10
      6▕     static protected $pattern = '/[^\p{L}\p{N}\p{Pc}\p{Pd}@] /u';
      7▕
      8▕     public function tokenize($text, $stopwords = [])
      9▕     {
  ➜  10▕         $text  = mb_strtolower($text);
     11▕         $split = preg_split($this->getPattern(), $text, -1, PREG_SPLIT_NO_EMPTY);
     12▕         return array_diff($split, $stopwords);
     13▕     }
     14▕ }

So I tried to transform $this->tags in a string, like this:

public function toSearchableArray()
    {
        $array = [
            'id' => $this->id,
            'title' => $this->title,
            'subtitle' => $this->subtitle,
            'body' => $this->body,
            'tags' => implode(',', $this->tags),
        ];

        return $array;
    }

but then I receive this error:

 implode(): Argument #1 ($pieces) must be of type array, string given

  at C:\Users\Davide\working_area_davide\Freelance\sito_alvise_L8\app\Models\Article.php:38
     34▕             'id' => $this->id,
     35▕             'title' => $this->title,
     36▕             'subtitle' => $this->subtitle,
     37▕             'body' => $this->body,
  ➜  38▕             'tags' => implode(',', $this->tags),
     39▕         ];
     40▕
     41▕         return $array;
     42▕     }

I searched the internet for a solution but didn't find anything.

Hope that someone can help! Thanks in advance!

CodePudding user response:

Would something like this work?

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

        if (is_array($tags)) {
            $tags = implode(',', $this->tags);
        }
        
        $array = [
            'id'       => $this->id,
            'title'    => $this->title,
            'subtitle' => $this->subtitle,
            'body'     => $this->body,
            'tags'     => $tags
        ];

        return $array;
    }

CodePudding user response:

I solved by undoing the array casting in protected $casts.

Honestly I don't know why, but that's that.

  • Related