Laravel-mysql-one-to-many-relationship.

·

3 min read

To understand one to many relationship we need two example tables ,

let take two table named blog_posts and comments.

now we will make necessary columns for blog_posts table

 Schema::create('blog_posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->text('content')->nullable();
        $table->timestamps();
});

and comments table

Schema::create('comments', function (Blueprint $table) {
            $table->id();
            $table->text('content');
            $table->unsignedBigInteger('blog_post_id')->index() ; 
            $table->foreign('blog_post_id')->references('id')->on('blog_posts')->onUpdate('cascade')->onDelete('cascade') ; 
            $table->timestamps();
        });

now we will establish a connection or relationship between blog_post and comments table with foreign() method that will grab our column named 'blog_post_id' and assign the targeted values inside this grabbed field , refferences() method will target id value of 'blog_posts' table which is targeted using on() methos

from right to left , we can simply say that on('blog_posts') table take the value of column references('id') and set it to our foreign('blog_post_id') field in comments table.

foreign('current_table_column_name')->refferences('targeted_table_column_name')->on('targeted_table')->onUpdate('cascade')->onDelete('cascade')

onUpdate('cascade') and onDelete('cascade') will take action automatically if foreign_table row is updated or deleted .

Link up with blog_posts and comments is done , now we should set method in BlogPost Model to access comments table data.

To set type of relationship between BlogPost and Comment.

class BlogPost extends Model
{
    use HasFactory;

    public $timestamps = true ; 

    protected $fillable = [// enabling to assign values in these fields using $fillable 
        'title',
        'content'
    ]; 


/// defining our comments() method and saying that one BlogPost has many Comment
    public function comments(){
        return $this->hasMany(Comment::class) ; 
    }

}

class Comment extends Model
{
    use HasFactory;

    protected $fillable = [
        'content'
    ];



// in our comments table we defining relational column id named 
// blog_post_id now wen must name our method "blog_post()"
// if we define relational column id with "abdx_blog_table_id" then
// method named will must be "abdx_blog_table()" 

    // here is another example if post_id
    // public function then->post(){
    //     return $this->belongsTo(BlogPost::class) ; 
    // } 


    //blog_post_id
    public function blog_post(){
        return $this->belongsTo(BlogPost::class) ; 
    }
}

now we will run php artisan tinker command to run command shell in laravel

we will add a blog post using tinker example code is here

$bp = BlogPost::create([ . "title" => "title-1", . "content" => "content-1" . ]);

$bp = BlogPost::create([ . 'title' => 'title-2', . 'content' => 'content-2' . ])

$bp = BlogPost::find(5) //find by id

creating two posts and selecting post which id number is 5

run php artisan tinker

$bp = BlogPost::find(5) //finding post number 5

$comment = new Comment() //creating a instance for Comment model

$comment->content = 'comment-1' //adding data to comment instance

$bp->comments()->save($comment) // assigning comment instance to

//$bp which is Blog Post with id 5

now we will see that our comment table has a new filled row with value in content and blog_post_id another example

$bp = BlogPost::find(6)

$comment = new Comment()

$comment->content = 'content-2'

$bp->comments()->save($comment)

now we tried these commands

$bp = BlogPost::find(6)

$comment = new Comment()

$comment->blog_post()->save($bp)

then we will get a error message

"BadMethodCallException Call to undefined method Illuminate\Database\Eloquent\Relations\BelongsTo::save()."

now we run

$comment->blog_post()->associate($bp)->save()

to save comment with $bp

another way save $bp in comment table

$comment = new Comment()

$comment->content = "third comment"

$comment->blog_post_id = 5

$comment->save()

$comment = new Comment()

$comment->content = 'a'

$comment2 = new Comment()

$comment2->content = 'b'

$bp = BlogPost::find(5)

$bp->comments()->saveMany([$comment,$comment2])

Query one to many relationship

$post = BlogPost::with('comments')->get()

$post = BlogPost::all()

$bp = BlogPost::find(5)

$bp->comments

$comment = Comment::find(10)

$comment->blog_post

$comment

eager loading

eager loading with withCount , here withCount will create a new field named ''comments_count" with number of comment in each blog post.

$posts = BlogPost::withCount('comments')->get();

$posts = BlogPost::with('comments')->get();

this query will return all BlogPost with comments so query will efficient with eager loading

lazy loading

example for a lazy loading

$posts = BlogPost::all() ;