简体   繁体   中英

Relationships don't work

I have 2 models: User and Rank

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'username', 'email', 'password','registered_at','last_action','ip','about_user','reputation','rank','moderator_notes','verified','verify_code',
    ];
    public $timestamps=false;

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
    public function ranks() {
        return $this->hasOne(Rank::class,'id','rank');
    }
}

And

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Rank extends Model
{
    protected $table = "ranks";
    public $timestamps = false;

    public function user() {
        return $this->belongsTo('App\User');
    }
}

'rank' column in user table should be same as 'id' in ranks table. Now I want to get both user and his rank info. Tried in many ways, because found many ways in internet. One of them was like:

$user = User::where('id',$id)->where('username',$username)->first()->ranks();

But now I cant access any user info, get just ranks info... My view looks like this:

Username: {{$user->username}}<br/>
Email: {{$user->id==Auth::id()?$user->email:'nerodomas'}}<br/>
Rank: {{print_r(Auth::user()->ranks()->name)}}

username and email should be from users table, and rank (name) - from ranks table... However I only get errors. Cal anyone help me? :) thanks!

PS sorry for question title, couldn't create anything better..

There is some problem in your relationship and DB schema. Your ranks table should have user_id column instead of users table having rank column.

If you follow above schema then your relation should be as:

User.php

public function ranks()
{
    return $this->hasMany('App\Rank');
}

Rank.php

public function user()
{
    return $this->belongsTo('App\User');
}

Update

For Many To Many relationship your table should be as:

user table - |id|email|...

rank table - |id|name|

rank_user table - |id|user_id|rank_id|

The rank_user table is derived from the alphabetical order of the related model names.

Define relationship as:

User.php

public function ranks()
{
    return $this->belongsToMany('App\Rank');
}

Rank.php

public function users()
{
    return $this->belongsToMany('App\User');
}

Then you can query it as:

$user = User::where('id',$id)->where('username',$username)->with('ranks')->first();

And in your view you can use it as:

Username: {{$user->username}}<br/>
Email: {{$user->id==Auth::id()?$user->email:'nerodomas'}}<br/>
Rank: {{print_r(Auth::user()->ranks->first()->name)}}

Rank: {{print_r($user->ranks)}}

Docs

Update 2

To the response of comment below

Make sure you have entry in DB something like this:

If your logged in user id is 1 then:

user table

|id|name|
+-------+
|1 |Sam |

role table

|id|name         |
+----------------+
|1 |Administrator|
|2 |Moderator    |

role_user table

|id|user_id|role_id|
+------------------+
|1 |1      |1      |
|2 |1      |2      |

It looks like your have your relationships the wrong way round.

If multiple users can have the same rank the that means a rank can have many users (hasMany).

Your relationships should be

Rank Model

public function users()
{
    return $this->hasMany(User::class, 'rank', 'id');
}

User Model

public function userRank()
{
    return $this->belongsTo(Rank::class, 'rank', 'id');
}

Ideally, you would want to have the column on the users table called rank_id . This way you wouldn't have to define the local and foreign keys in the relationship and you would be able to call the relationship in the User model rank() .

With your user query id should be unique so you shouldn't need to query the username as well but I will use your original query as the example:

$user = User::where('id',$id)->where('username',$username)->first();

Then to get the rank relationship you can:

$rank = $user->userRank; //Rank model
$rank->name; //Rank name

Or even:

$rankName = $user->userRank->name;

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM