Jesse Luke Orange
Jesse Luke Orange

Reputation: 1999

User to Profile link Laravel 5.6

I am very new to Laravel and would like some clarity.

I am trying to Link two tables: Users => Profiles

Users looks like this:

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('username');
    $table->string('displayName');
    $table->string('email')->unique();
    $table->string('role')->nullable();
    $table->string('department')->nullable();
    $table->string('location')->nullable();
    $table->string('directDialIn')->nullable();
    $table->string('mobileNumber')->nullable();
    $table->string('managedByUsername')->nullable();
    $table->string('managedByDisplayName')->nullable();
    $table->timestamps();
});

Profiles looks like this:

Schema::create('profiles', function (Blueprint $table) {
    $table->increments('id');
    $table->string('user_username')->index();
    $table->mediumText('skills');
    $table->mediumText('background');
    $table->mediumText('socialProfiles');
    $table->string('displayPicture')->default('../../assets/images/user_pic.jpg');
    $table->string('mangedByUsername');
    $table->boolean('changesPending')->default(0);
    $table->timestamps();
}); 

The relevant models

class User extends Authenticatable
{
    use Notifiable;

    /**
     * Primary key to use
     */
    protected $primaryKey = 'username';

    /**
     * Tell Eloquent to not auto increment
     */
    public $incrementing = false;

    /**
     * Table to use
     */
    protected $table = 'users';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'username', 'displayName', 'email', 
        'role', 'department', 'location', 
        'directDialIn', 'mobileNumber', 'managedByUsername',
        'managedByDisplayName'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * Get the profile associated with this user
     */
    public function profile()
    {
        return $this->hasOne(Profile::class, 'user_username');
    }
}

class Profile extends Model
{
    /**
    * Get the user that has this Profile
    */
    public function user()
    {
        return $this->belongsTo(User::class, 'user_username');
    }
}

According to the documentation:

Eloquent determines the foreign key of the relationship based on the model name. In this case, the Phone model is automatically assumed to have a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method:

So I have explicitly defined the keys to be used.

In my routes I have:

Route::get('/profile/{user}', 'ProfileController@index');

I am quite used to just joining two tables with an SQL JOIN but in this case, how do I get both the User model data and the Profile Model data?

So it'd be like: User: Dave then Dave's profile.

Also, if Dave hasn't filled in his profile could I display just his user data?

In ProfilesController I have this:

public function index(Request $request)
{
    // Get this user's username from the session
    $username = $request->session()->get('User_name');

    /**
     * Get the Profile and associated User by pulling from the database via user_username
     * Will return a profile with an attached user
     */
    $profile = Profile::with('user')->where('user_username', $username)->first();

    return view('pages.profile.show', compact('profile'));
}

However, when I dump out the result for Profile the associated User is null.

I find this strange as I can use Artisan tinker as follows:

$profile = App\Profile::find(7);

and then...

$profile->user

Which yeilds the user relating to a Profile with an ID of 7.

A dd($profile); yeilds the following:

enter image description here

Profiles table

enter image description here

Users table

enter image description here

As you can see, there is data is both tables and user_username is the same as username but for some reason when using with:: the link between the two just isn't seen.

Upvotes: 1

Views: 1191

Answers (1)

Sohel0415
Sohel0415

Reputation: 9863

Use with() method

$profile_with_user = Profile::with('user')->where('user_username', $username)->first();

Or

$user_with_profile = User::with('profile')->where('username', $username)->first();

Upvotes: 1

Related Questions