Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

richardh's avatar

Relations on column that is an array

Is there a way of joining on a column where it is and array on intergers. I want to try and do this

    public function students(){
        return $this->hasMany('App\Api\Models\User', '[group_ids]', 'id');
    }

'[group_ids]' is an array. how could I make the query work

0 likes
4 replies
lostdreamer_nl's avatar
Level 53

Found a way for you.......

Create a new class: app/HasManyJson.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Collection;

class HasManyJson extends HasMany
{
    public function addEagerConstraints(array $models)
    {
        $this->query->whereIn($this->foreignKey, $this->getKeys($models, $this->localKey));
    }
    
    protected function getKeys(array $models, $key = null)
    {
        $keys = [];
        collect($models)->each(function ($value) use ($key, &$keys) {
            $keys = array_merge($keys, json_decode($value->getAttribute($key), true));
        });
        return array_unique($keys);
    }
    
    
    public function matchMany(array $models, Collection $results, $relation)
    {
    
        $foreign = $this->getForeignKeyName();
    
        $dictionary = $results->mapToDictionary(function ($result) use ($foreign) {
            return [$result->{$foreign} => $result];
        })->all();
        
        foreach ($models as $model) {
            $ids = json_decode($model->getAttribute($this->localKey), true);
            $collection = collect();
            foreach($ids as $id) {
                if(isSet($dictionary[$id]))
                    $collection = $collection->merge($this->getRelationValue($dictionary, $id, 'many'));
            }
            $model->setRelation($relation, $collection);
        }
    
        return $models;
    }
}

Change your students method:


    public function students()
    {
        $foreignKey = 'group_ids';
        $instance = new User();
        $localKey = 'id';
        // dont forget to import the HasManyJson class as well in the top of this model)
        return new HasManyJson($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
    }

Always fun to see how open Laravel is..... :)

2 likes
matbeard's avatar

Hi

This is quite an old post but it's exactly what I'm looking to achieve.

Unfortunately, I'm getting an error on line 19: array_merge(): Expected parameter 2 to be an array, int given

I'm using Laravel 8 with SQL Server and the field containing the array of ids is cast to an array in the model. Any suggestions?

Thanks

P.S. I forgot to mention... I'm trying to eager load the relations -- maybe that's the problem?

MrPunyapal's avatar

@matbeard

hey swap the foreignKey and localKey while calling relationship,

after that remove json_decode from both place in matchMany() and getKeys()

this worked for me.

1 like

Please or to participate in this conversation.