Laravel 8.x Vue Js Tutorial With Twitter Application

Hello artisan, in this tutorial, i will show you how we can create a simple twitter application using laravel 8 and vue js. In this tutorial i will also show you how to create follow-unfollow system in laravel using vue js. 

I am using Axios to send a http request. We simply build an application in which, the user can post the tweet and appears in his timeline. Also, one user can follow or unfollow each other. 

 If currently signed in user follow any other registered user then he can also see the following user’s tweet in his timeline. The very basic app, but the very powerful web app to understand laravel and vue.js fundamental concepts.

In this laravel vue tutorial we will create simple Twitter app with follow unfollow system. A user can follow another user and after logged in he can post a tweet.

I am putting this Laravel and vue example project on github so you can check it out there. Git repository for this project

 

laravel-vue-js-tutorialPreview : 

follow-unfollow-laravel-6-vue-js

Preview after hitting follow button : 

laravel-vue-tutorial-from-scratch

Preview of timelineComponent : 

laravel-6-vue-js-follow-unfollow-tutorial-preview

Step 1: Install Laravel.

Type the following command in the terminal.

composer create-project --prefer-dist laravel/laravel TwitterApp

 

now type bellow command to go to this directory

cd twitterApp

 

Step 2: Install npm

Install the front-end dependencies using the following command.

npm install

 

Create an authentication using the following command.

composer require laravel/ui --dev

php artisan ui vue --auth

 

Now when user logged in then he can see the home.blade,php page. So we need to thing in this page. 

  • One is tweet form
  • Another is timeline to show tweet

 

resources/views/home.blade.php 

 

Now go to this URL: 

 

localhost:8000/home 

 

and you can see the changes.

Step 3: Create tweet form

Write the following code inside FormComponent.vue file.

resources/js/components/FormComponent.vue

 

Import this component inside app.js file.

resources/js/app.js

require('./bootstrap');

window.Vue = require('vue');

Vue.component('example-component', require('./components/ExampleComponent.vue').default);

//Twitter Component
Vue.component('form-component', require('./components/FormComponent.vue').default);

const app = new Vue({
    el: '#app',
});

 

Also, we need to add this component inside a home.blade.php file.

resources/views/home.blade.php 

 

Step 4: Create Post Model

Okay, now create a model and migration.​​

php artisan make:model Post -m

 

Write the following schema inside a create_posts_table.php file.

    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
            $table->string('body', 130);
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
 
        });
    }

 

Migrate the posts table.

php artisan migrate

 

Step 5: Create PostController

Also, we need to create a PostController. So create a controller by the following command.

php artisan make:controller PostController

 

Step 6: Define the relationships.

Inside User.php model, we need to define a function that is a relationship between Post model and User model.

// User.php

public function posts()
{
   return $this->hasMany(Post::class);
}

 

Also, the Post belongs to User. So we can define the inverse relationship inside Post.php model.

// Post.php

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

 

Step 7: Save Tweet in the database.

When we have used the command npm install, it has already install axios library. So we can use the axios to send a POST request to a Laravel backend web server and store the tweet in the database.

routes/web.php

Route::post('tweet/save', 'PostController@store');

 

Also, we need to define the $fillable property inside Post.php model to prevent the Mass Assignment Exception.

app/Post.php

protected $guarded = [];

 

The final thing is to define the store function inside PostController.php file.

app/Http/Controllers/PostController.php

namespace App\Http\Controllers;

use App\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function store(Request $request, Post $post)
    {   

        $newPost = $request->user()->posts()->create([

            'body' => $request->body

        ]);
   
        return response()->json($post->with('user')->find($newPost->id));
    }

}

 

Read also : User Roles and Permissions Tutorial in Laravel without Packages

Also, we need to use axios library to send a POST request, so write the code inside FormComponent.vue file.

resources/js/components/FormComponent.vue

 

Step 8: Create a vue event.

To display all the tweets on the frontend, we need to first show the tweets to the Timeline, and for that, we need to create an event. Remember, we are not refreshing the page to fetch all the tweets. When we add a new tweet, we need to display that tweet in the user’s timeline without refresh the page. 

 

We can also use Vuex for this, but right now, we are not diving into Stores and actions, let us keep it simple.

resources/js/app.js 

//Events
let Event = new Vue()
window.Event = Event;

 

Now make an Event in FormComponet.vue

resources/js/components/FormComponent.vue

 

So, when the new post is saved, we can emit an event that has the saved tweet with the user.

 

Step 9: Create a Timeline Component.

resources/js/components/TimelineComponent.vue

 

So, we are listening for that event, and when the event is listened by this component, we add the new data to the posts array and iterate the component to display the tweet and user as well. Now, register this component inside an app.js file.

resources/js/app.js

Vue.component('timeline-component', require('./components/TimelineComponent.vue').default);

 

Also, add this component inside a home.blade.php file.

 

Add a new tweet, and you can see the name and tweet.

 

Step 10: Show time in the timeline.

Add this below code inside post.php to get date. So, we can use the append attribute to add the time data and then fetch it in the response. Very simple.

app/Post.php

protected $appends = ['createdDate'];

public function getCreatedDateAttribute(){

 return $this->created_at->diffForHumans();

}

 

Now, we can access the createdDate property inside TimelineComponent.vue file.

resources/js/components/TimelineComponent.vue

 

Step 11: Create a user profile.

Now, we need to create one controller called UserController. Type the following command.

php artisan make:controller UserController

 

Now, add the following function inside UserController.php file.

app/Http/Controllers/UserController.php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function show(User $user)
    {
        return view('user', compact('user'));
    }

}

 

Here, I am using Route Model Binding, but we will use my name on the route. So, we can access it through user’s name key. So we need to define the routing key inside User.php file.

app/User.php

// User.php

public function getRouteKeyName()
{
   return 'name';
}

 

Create a view file called user.blade.php inside views folder.

resources/views/user.blade.php

 

Also, we need to define the route inside a web.php file.

routes/web.php

Route::get('users/{user}', 'UserController@show')->name('user.show');

 

Let us say; I have registered the user with a name: abc. We can access its profile using this URL

localhost:8000/users/abc

 

Step 12: Display URL inside TimelineComponent.

Create an accessor for a profileLink inside User.php model file.

app/User.php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{

    protected $appends = ['profileLink'];

    public function getProfileLinkAttribute()
    {
        return route('user.show', $this);
    }

}

 

Now, we can display this URL inside TimelineComponent.vue file.

resources/js/components/TimelineComponent.vue

 

Step 13: Create Follow or Unfollow link.

 

Create a migration file for Followers table.Type the following command to generate model and migrations.

php artisan make:model Follower -m

 

Now, write the following schema inside create_followers_table.

Schema::create('followers', function (Blueprint $table) {
  $table->bigIncrements('id');
  $table->unsignedBigInteger('user_id');
  $table->unsignedBigInteger('follower_id');
  $table->nullableTimestamps();

  $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
  $table->foreign('follower_id')->references('id')->on('users')->onDelete('cascade');
});

Migrate the table.

php artisan migrate

 

Now, we need to set up the relationship with the User model.

app/User.php

public function following()
{
  return $this->belongsToMany(User::class, 'followers', 'user_id', 'follower_id');
} 

 

Next step is, we need to put some condition that is following.

  • The user can not follow himself.
  • If another user is not followed by him, then he can follow the user.
  • If the user is followed by another user, then he can unfollow him or her.

 

app/User.php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{

    public function isNot($user)
    {
        return $this->id !== $user->id;
    }

    public function isFollowing($user)
    {
        return (bool) $this->following->where('id', $user->id)->count();
    }

    public function canFollow($user)
    {
        if(!$this->isNot($user)) {
            return false;
        }
        return !$this->isFollowing($user);
    }

}

 

Okay, now we have written all the conditions regarding function, we can head over to the user.blade.php file and implement the follow or unfollow link.

resources/views/user.blade.php

 

Step 14:  Follow the User.

routes/web.php

Route::get('users/{user}/follow', 'UserController@follow')->name('user.follow');

 

Now, we can write the follow() function inside UserController.php file.

app/Http/Controllers/UserController.php

public function follow(Request $request, User $user)
{
    if($request->user()->canFollow($user)) {

        $request->user()->following()->attach($user);

    }

    return redirect()->back();
}

 

Also, we need to update the user.blade.php file.

resources/views/user.blade.php

 

Step 15:  Unfollow the User

We can unfollow the user, which is currently following. So we can write the following function inside User.php file.

app/User.php

public function canUnFollow($user)
{
    return $this->isFollowing($user);
}

 

Also, we need to define the unfollow route inside a web.php file.

routes/web.php

Route::get('users/{user}/unfollow', 'UserController@unfollow')->name('user.unfollow');

 

Now, write the unFollow() function inside UserController.php file.

app/Http/Controllers/UserController.php

public function unFollow(Request $request, User $user)
{
   if($request->user()->canUnFollow($user)) {
       $request->user()->following()->detach($user);
    }
       return redirect()->back();
}

 

Also, we need to update the user.blade.php file.

resources/views/user.blade.php

 

Now, finally, the follow and unfollow functionality is over. you can check it now

 

Step 16: Fetch tweets 

So, we can define the index() function inside PostController.php file.

app/Http/Controllers/PostController.php

namespace App\Http\Controllers;

use App\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function store(Request $request, Post $post)
    {   

        $newPost = $request->user()->posts()->create([

            'body' => $request->body

        ]);
   
        return response()->json($post->with('user')->find($newPost->id));
    }

    public function index(Request $request, Post $post)
    {
        $posts = $post->whereIn('user_id', $request->user()->following()
                        ->pluck('users.id')
                        ->push($request->user()->id))
                        ->with('user')
                        ->orderBy('created_at', 'desc')
                        ->take($request->get('limit', 10))
                        ->get();
          
        return response()->json($posts);
    }

}

 

Define the route for this index() function.

routes/web.php

Route::get('posts', 'PostController@index')->name('posts.index');

 

Okay, now finally, we need to send a network request using axios library. We need to define the axios get request inside our TimelineComponent.vue file.

resources/js/components/TimelineComponent.vue

 

Finally, our laravel vue tutorial is over. In this Laravel and vue examplewe have covered lots of things and concepts.I hope it can help you with your real-time projects.

 

#laravel-6 #vue-js #follow-unfollow #laravel