Home > Net >  Eloquent model hasOne returning a non related model
Eloquent model hasOne returning a non related model

Time:11-28

Background info

In my project I'm using the Illuminate\Database package.

I've setup two classes: User and Customtag. I'm trying to make relationship between the two.

I have two tables: vip_users and vip_customtags. Both have a column called 'steamid' which is VARCHAR(255).

Right now, there are multiple users, but for this case: I have an user with steamid 76561198048535340.

And there is a customtag with steamid 76561198048535341

Problem

foreach (User::all() as $u)
{
    echo "User: " . $u->vip_id . "<br>";
    print_r($u->customtag);
}

This code prints user 1, 2, 3, 4, 5... etc. But when the user with steamid 76561198048535340 comes around, it returns the customtag with steamid 76561198048535341

User: 1
User: 2
VipSystem\Models\Customtag Object
(
...
    [attributes:protected] => Array
        (
            [steamid] => 76561198048535341
        )

    [original:protected] => Array
        (
            [steamid] => 76561198048535341

        )
...
)
User: 3
User: 4
User: 5

The other way around, with requesting all customtags works fine. e.g.:

foreach (Customtag::all() as $tag)
{
    echo "Tag: " . $tag->id . "<br>";
    print_r($tag->user);
}

Prints:

Tag: 1
Tag: 2
Tag: 3
Tag: 4
Tag: 5

Classes

User

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;

class User extends Model
{
    public $timestamps = false;
    public $primaryKey = "steamid";

    public function customtag(): HasOne
    {
        return $this->hasOne(Customtag::class, "steamid", "steamid");
    }
}

Customtag

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Customtag extends Model
{

    public $timestamps = false;
    public $primaryKey = "id";

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, "steamid", "steamid");
    }
}

CodePudding user response:

/**
 * @return Customtag
 *
 * @throws ModelNotFoundException
 */
public function customtag()
{
    return Customtag::where('steamid', '=', '' . $this->steamid)->get()->firstOrFail();
}

Forcing the steamid into a string seems to do the trick for me. The SQL was being executed with an integer.

CodePudding user response:

By default, Laravel classes expect the primary key to be an incrementing integer. You need to tell the class that the primary key is actually a string.

Add the following to your User class:

protected $keyType = 'string';
public $incrementing = false;
  • Related