Back to Homepage

URL Change and Track Clicks Management

4 min read

Tags:

URL Change and Track Clicks Management

When it comes to Laravel, a leading PHP framework, implementing 301 redirects and tracking clicks is easier than ever. Laravel provides robust features and well-structured libraries to make this process efficient and straightforward. This article will explore how to change URLs, redirect old URLs to new ones, and track clicks using Laravel.

What is a 301 Redirect?

A 301 redirect is the most efficient and search engine-friendly method for webpage redirection. It's the best way to ensure that users and search engines are directed to the correct page.

Implementing 301 Redirects in Laravel

Run the following command to create a new migration file:

Note: Replace article with your own table name

php artisan make:migration create_article_url_changes_table

Now, open the generated migration file. It will be located under database/migrations/. You'll see two methods in the migration file: up() and down(). The up() method is used to create the table, and the down() method should reverse the actions of up().

Replace the content of the up() method and add the down() method as follows

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateArticleUrlChangesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
     Schema::create('article_url_changes', function (Blueprint $table) {
           $table->id();
           $table->unsignedBigInteger('article_id');
           $table->string('old_slug');
           $table->string('new_slug');
           $table->unsignedBigInteger('redirect_count')->default(0);
           $table->timestamps();
           $table->foreign('article_id')
              ->references('id')
              ->on('articles') // Replace with your own table name
              ->onDelete('cascade');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
   public function down()
   {
    Schema::dropIfExists('article_url_changes');
   }
}

After you've added this code, run the migration:

php artisan migrate

Add this below code to your existing code to

namespace App\Http\Controllers;

use App\Models\Article;
use App\Models\ArticleURLChange;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class ArticleController extends Controller
{
    /**
     * Handle changes in the article slug.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function handleSlugChange(Request $request): Response
    {
        $newSlug = $request->input('slug');
        $articleId = $request->input('article_id');

        // Validate the input data
        if (!$this->validateSlugChange($newSlug, $articleId)) {
            return response('Invalid data provided', 400);
        }

        // Retrieve the original model from the database
        $originalArticle = Article::find($articleId);
        $oldSlug = $originalArticle->slug;

        // Check and handle the slug change
        if (!$this->shouldUpdateSlug($oldSlug, $newSlug)) {
            return response('Slug has not changed', 200);
        }

        $this->updateSlug($articleId, $oldSlug, $newSlug);

        return response('Slug updated successfully', 200);
    }

    /**
     * Validate the slug and article ID.
     *
     * @param  string  $newSlug
     * @param  int  $articleId
     * @return bool
     */
    private function validateSlugChange(string $newSlug, int $articleId): bool
    {
        return !empty($newSlug) && !empty($articleId);
    }

    /**
     * Determine if the slug should be updated.
     *
     * @param  string  $oldSlug
     * @param  string  $newSlug
     * @return bool
     */
    private function shouldUpdateSlug(string $oldSlug, string $newSlug): bool
    {
        return $oldSlug !== $newSlug;
    }

    /**
     * Update the slug in the database.
     *
     * @param  int  $articleId
     * @param  string  $oldSlug
     * @param  string  $newSlug
     * @return void
     */
    private function updateSlug(int $articleId, string $oldSlug, string $newSlug): void
    {
        // Check if there's already a redirect from the new slug to the old slug
        $existingRedirect = ArticleURLChange::where('old_slug', $newSlug)
            ->where('new_slug', $oldSlug)
            ->first();

        // Delete the old redirect if we are reverting back to an old slug
        if ($existingRedirect) {
            $existingRedirect->delete();
        }

        // Create a new redirect entry
        ArticleURLChange::create([
            'article_id' => $articleId,
            'old_slug' => $oldSlug,
            'new_slug' => $newSlug,
        ]);
    }
}

In the below example, I used a method named handleSlugChange to encapsulate the logic. This method accepts a route object, which will only contain the incoming HTTP when main Article Route doesn't find any result. You can call implement is as per your choice. I Didn't want to implement it as a middleware to avoid making it run everytime.

Route::get('/{article:slug}', \App\Http\Controller\ArticleDetail::class)->name('blog.articles.detail')
        ->missing(function ($request) {
            $urlChange = ArticleURLChange::where('old_slug', $request->route('article'))->first();
            if ($urlChange) {
                $urlChange->increment('redirect_count');
                return redirect('/' . $urlChange->new_slug, 301);
            }
            abort(404);
  });
Follow @LaravelSage on X → Follow @LaravelSage on Facebook →
Aniket Singh

Aniket Singh

View All Articles

Full-stack developer with a knack for Merging creativity with technical expertise for standout solutions.

Related Articles

Top Laravel Packages for Building Powerful Applications

Top Laravel Packages for Building Powerful Applications

Are you ready to take your Laravel skills to the next level and build extraordinary applications? Look no further! In this blog post, we will unveil a treasure trove of top packages that will revolutionize your development process.

MarkdownX:  Markdown Editor by DevDojo

MarkdownX: Markdown Editor by DevDojo

It's a lightweight markup language used by developers, writers, and content creators for formatting text for various purposes, such as documentation, blog posts.

Subscribe for 20+ new Laravel tutorials every week

You can unsubscribe at any time. You'll also get -20% off my courses!

© 2024

 

Laravel Sage

   |    Privacy Policy