Laravel Tinker Creating Data

We’ll go into the command line to create a new entry in posts:

php artisan tinker

Now add a new record:

$post = App\Models\Post::create(['title'=>'PHP post from tinker','content'=>'PHP content tinker','user_id'=>1]);

It will show you the results of the post including new ID.

To see again type:

$post

This means you can set the variable with all the information before you create a database entry

$post = new App\Models\Post

See the result

$post

Add rest of information:

$post->title = "New title for object"
$post->content = "New content for object"
$post->user_id = 2

See the result

$post

To save this post to the database just do like this:

$post->save()

Eloquent Polymorphic Relation Many to Many

Many to many relationships for polymorphic relations they share a single list of unique records, those unique records are shared amongst the other tables. If we have a post in the Videos table they are going to be sharing tags.

We are going to have a few tables in order to do this:

php artisan make:model Video -m
php artisan make:model Tag -m
php artisan make:model Taggable -m

Open up the video and tag migration to add this:

            $table->string('name');

Open up taggable to add the linking parts. You can remove the increment id and timestamps:

            $table->integer('tag_id');
            $table->integer('taggable_id');
            $table->string('taggable_type');

Now migrate this

php artisan migrate

Now we need to set the relationship starting in the Post model. Write this:

    public function tags() {
        return $this->morphToMany('App\Models\Tag', 'taggable');
    }

Add this exact piece of code to the Video model as well.

On your Tag model we need to define the Post and Video method:

    public function posts() {
        return $this->morphedByMany('App\Models\Post','taggable');
    }
    public function videos() {
        return $this->morphedByMany('App\Models\Video','taggable');
    }

Create two videos and two tags (try javascript and php). Then connect these in your taggables table.

In taggables table you need to choose a tag from the tags table. Then taggable ID refers to the ID from either videos or posts table. Write the taggable_type like this: App\Models\Video. This will put a tag on a post record and a video record.

Let’s pull out a post’s tag:

Route::get('/post/tag', function(){
    $post = Post::find(1);
    foreach($post->tags as $tag){
        echo $tag;
    }
});

Now let’s do the inverse and find the post from the tag. Look inside your taggable table to see you are referencing the correct model (post or video) or else you’ll get back nothing.

use App\Models\Tag;

Route::get('/tag/post', function(){
    $tag = Tag::find(2);
    foreach($tag->posts as $post){
        echo $post->title;
    }
});

Eloquent Polymorphic Relation

Polymorphic relations allow a model to belong to more than one other model in a single association. A really simple example is a users table and a posts table and they both could be related to one other table called photos. So in the photos table we’ll have some columns that would specify the model in which they belong to and the ID of that record. For example, we have one photo record that belongs to the post model with an ID of 1, and this belongs to the user model with an ID of 2.

We are going to have a photos table which will need a new Photo role which we’ll build a migration at the same time:

php artisan make:model Photo -m

Open up the migration and add these to the up function:

            $table->string('path');
            $table->integer('imageable_id');
            $table->string('imageable_type');

Now migrate this

php artisan migrate

Create a few photos in your database. This one is a little more complicated than usual. imageable_id is the ID of the post OR user. imageable_type lets us know which model to reference in this format (App\Models\User).

Now we need to set the relationship starting in the Photo model. Write this:

    public function imageable() {
        return $this->morphTo();
    }

Now we need to set the other tables. Let’s set Post model to pull photos:

    public function photos() {
        return $this->morphMany('App\Models\Photo','imageable');
    }

Add this exact piece of code to the User model as well.

Let’s pull out a user’s photo:

Route::get('/user/photos', function(){
    $user = User::find(1);
    foreach($user->photos as $photo){
        echo $photo;
    }
});

Let’s pull out a post’s photo:

Route::get('/post/photos', function(){
    $post = Post::find(1);
    foreach($post->photos as $photo){
        echo $photo;
    }
});

Eloquent Has Many Through Relationship

The “has-many-through” relationship provides a shortcut for accessing distant relations via an intermediate relation.

We are going to have a country table which will need a new Country role which we’ll migration at the same time:

php artisan make:model Country -m

Since we need a new foreign key (country_id) on the users table, we’ll create a new migration for this:

php artisan make:migration add_country_id_column_to_users --table=users

Open up the migration and add the first to up function and second to down function:

$table->integer('country_id');
$table->dropColumn('country_id');

Now open your country table migration to add a name column:

$table->string('name');

Now migrate this

php artisan migrate

Create a few countries. Attach your user to one of these new countries by editing and inputting the ID.

Now we need to define this Many Through relationship in the model. Open up Country model and add:

    public function posts(){
        return $this->hasManyThrough('App\Models\Post','App\Models\User');
    }
The first argument passed to the hasManyThrough function is the name of the final model we wish to access, while the second argument is the name of the intermediate model which has the foreign ID of this model (country_id).

Now let’s see this lookup in action. Add this to routes:

Route::get('/user/country', function(){
    $country = Country::find(4);
    foreach($country->posts as $post){
        echo $post->title;
    }
});
We find by country ID which then finds the user that owns the post to get the post title.

Eloquent Querying Intermediate Table / Pivot

Add this to the User model.. the new addition is withPivot which allows us to pull data from the intermediate table. We always need to specify this.

    public function roles(){
        return $this->belongsToMany('App\Models\Role')->withPivot('created_at');
    }

Now in routes add this:

Route::get('/user/pivot', function(){
    $user = User::find(1);
    foreach($user->roles as $role){
        echo $role->pivot->created_at;
    }
});

Eloquent Many to Many Relationship

We are going to make roles for our users which will require a new model called Role with a migration

php artisan make:model Role -m

Next you need to make a table for both roles and users. In Laravel you need to use singular case and go in alphabetical order.

php artisan make:migration create_users_roles_table --create=role_user

In your roles migration add the new fields:

$table->string('name');

In your user role migration add these fields:

$table->integer('user_id');
$table->integer('role_id');

Now migrate this

php artisan migrate

Create two roles: administrator, subscriber. Create a second user if doesn’t exist. In role_user attach the user to role based on ID of each. You can do 1,1 and 2,2.

Now we need to define the relationship in the model. Open up User model and add:

    public function roles(){
        return $this->belongsToMany('App\Models\Role');
        //To customize tables name and columns follow the format below
        //(Table name, user foreign key name, role foreign key name)
        //return $this->belongsToMany('App\Models\Role', 'user_roles', 'user_id', 'role_id');
    }

Now let’s see roles in action. Add this to routes:

Route::get('/user/{id}/role', function($id){
    $user = User::find($id);
    foreach($user->roles as $role){
        echo $role->name.'<br>';
    }
});

Another way to find roles:

Route::get('/user/{id}/role', function($id){
    $user = User::find($id)->roles()->orderBy('id', 'desc')->get();
    return $user;
});

Eloquent One to Many Relationship

Update your Post model by adding this:

    public function posts(){
        return $this->hasMany('App\Models\Post');
    }

We can now display the user’s post titles in our routes:

use App\Models\User;

/*
|--------------------------------------------------------------------------
| ELOQUENT Relationships
|--------------------------------------------------------------------------
*/

Route::get('/posts', function(){
    $user = User::find(1);
    foreach($user->posts as $post){
        echo $post->title.'<br>';
    }
});

View in your browser.