Summer Sale! All accounts are 50% off this week.

mecjos's avatar

How to Eager Load a single Record of HasMany in condition?

Hi everyone. I need to fetch first record of hasMany relation in eager load query condition as follows:

$operations = Operation::with(['operationLang' => function ($query) {
            $query->where('lang_id', 1)->first();
        }])->where('user_id', 0)->get();
        return New OperationCollection($operations);

in above code, I have operation table and it's translations table.. I need to get operations with languages but not all of them only selected one or according to laravel localization. As far as my research on net, I shoundn't write first or get in query condition of eager loading but I don't know how I can do this. Thank you ..

0 likes
18 replies
Nakov's avatar
Nakov
Best Answer
Level 73

Here is what I might do, in the Operation model I will add a new relationship:

public function currentLang()
{
    return $this->hasOne(OperationLang::class)->ofMany(
            [ 'id' => 'max'],
            function($q) {
                $q->where('lang', app()->getLocale());
            }
        );
}

and then:

$operations = Operation::with('currentLang')->where('user_id', 0)->get();

it will eager load just that one. Of course make the modification in the function above to use the correct model and also the column name for which you keep the locale if that's what you have or the id.

Let me know if something like this would work?

P.S. Use latest of the 8th version of Laravel at least for the ofMany to work.

mecjos's avatar

@Nakov no didn't work.. I couldn't understand why but I get call to undefined relationship error. I made it simple as follows but same error..

return $this->hasOne(OperationLang::class)->ofMany('operation_id', 1);

when i put another relationship into that function in order to see whether function is problematic or not but it works,

Nakov's avatar

@mecjos is that how I showed it? The way you are passing the params to ofMany is completely wrong..

this is the syntax that you should use with your data..

return $this->hasOne(OperationLang::class)->ofMany(
            [ 'id' => 'max'],
            function($q) {
                $q->where('operation_id', 1);
            }
        );

and why it does not work is probably because OperationLang with Operation is not one to many relationship?

mecjos's avatar

@Nakov

operationsTableColumns = ['id', 'user_id', 'desc', 'is_active']
operationLangsTableColumns = ['operation_id', 'lang_id', 'name', 'abbr']

App\Modesl\Operation.php

public function translation()
    {
        return $this->hasOne(OperationLang::class)->ofMany(
            [ 'operation_id' => 'max'],
            function($q) {
                $q->where('operation_id', 1);
            }
        );
    }

here are my table columns and operation model... I can't see querying the language in that function. same error.

Nakov's avatar

@mecjos and do you have a relationship to query all the operationlanguages as well?

public function operationLangs()
{
	return $this->hasMany(OperationLang::class, 'operation_id');
}

?

mecjos's avatar

@Nakov Yes, are they related eachother.. it's another function..

mecjos's avatar

@Nakov yes I read it at the same time.. it's interesting, I make same thing as in docs but doesn't work. when I remove "ofMany" part of query it works..

Nakov's avatar

@mecjos based on this:

operationLangsTableColumns = ['operation_id', 'lang_id', 'name', 'abbr']

it looks like this is a many to many table, not one to many, so that's why the ofMany won't work I believe.

mecjos's avatar

@Nakov No I don't think so.. there isn't categorization of table according to their columns. Your relationship definitions determines the table is for what. operation model can has many operation translations.. I think table naming made you confused.. actually it's translations table there is another languages table..

Snapey's avatar

I get call to undefined relationship error

then that sounds like an error with the name you are using when you eager load, not the relationship method

mecjos's avatar

@Snapey no, it's the interesting one, when I change the relation in same relation name, it works. it's about ofMany part of relationship.

mecjos's avatar

@Snapey

this doesn't work.. normally it should work according to doc..

 public function translation()
    {
        return $this->hasOne(OperationLang::class)->ofMany('lang_id', 'max');
    }

this works.. I get only one trasnlation with this.

public function translation()
    {
        return $this->hasOne(OperationLang::class);
    }
mecjos's avatar

@nakov @snapey I think I found the reason... one of many relationship has added to laravel since version 8.42 and my version is 8.12.. is it possible to make this minor update?

Snapey's avatar

you can run composer update laravel/framework

mecjos's avatar

@Snapey oh I run only composer update.. now I get " Fatal error: Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= 8.0.2". You are running 7.4.11. in /home/vagrant/code/vendor/composer/platform_check.php on line " it updated homestead also I think.. it would be a surprise update without any problem already :)

Snapey's avatar

@mecjos perhaps you have a package that now wants php 8

if you have composer.json in version control, roll it back, delete composer.lock and delete the vendor folder, then run composer install to get back to where you were

Please or to participate in this conversation.