To create different post types (e.g., Blog and Article) in Laravel with separate tables and URL structures, follow these steps:
1. Create Migrations
Define separate tables for blogs and articles.
Blogs Migration:
php artisan make:migration create_blogs_table// database/migrations/YYYY_MM_DD_create_blogs_table.php
Schema::create('blogs', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->string('slug')->unique(); // For SEO-friendly URLs
    $table->text('content');
    $table->timestamps();
    $table->softDeletes();
});Articles Migration:
php artisan make:migration create_articles_table// database/migrations/YYYY_MM_DD_create_articles_table.php
Schema::create('articles', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->string('slug')->unique();
    $table->text('content');
    $table->timestamps();
    $table->softDeletes();
});Run migrations:
php artisan migrate2. Create Models
Generate models for Blog and Article.
Blog Model:
php artisan make:model Blog// app/Models/Blog.php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Blog extends Model {
    use SoftDeletes;
    protected $fillable = ['title', 'slug', 'content'];
    // Use 'slug' instead of 'id' in URLs
    public function getRouteKeyName() {
        return 'slug';
    }
}Article Model:
php artisan make:model Article// app/Models/Article.php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Article extends Model {
    use SoftDeletes;
    protected $fillable = ['title', 'slug', 'content'];
    public function getRouteKeyName() {
        return 'slug';
    }
}3. Define Routes
Set up distinct URL structures in routes/web.php:
// Blogs
Route::prefix('blogs')->group(function () {
    Route::get('/', [BlogController::class, 'index'])->name('blogs.index');
    Route::get('/create', [BlogController::class, 'create'])->name('blogs.create');
    Route::post('/', [BlogController::class, 'store'])->name('blogs.store');
    Route::get('/{blog}', [BlogController::class, 'show'])->name('blogs.show');
});
// Articles
Route::prefix('articles')->group(function () {
    Route::get('/', [ArticleController::class, 'index'])->name('articles.index');
    Route::get('/create', [ArticleController::class, 'create'])->name('articles.create');
    Route::post('/', [ArticleController::class, 'store'])->name('articles.store');
    Route::get('/{article}', [ArticleController::class, 'show'])->name('articles.show');
});4. Create Controllers
Generate controllers for each post type.
BlogController:
php artisan make:controller BlogController --resource// app/Http/Controllers/BlogController.php
use App\Models\Blog;
use Illuminate\Http\Request;
class BlogController extends Controller {
    public function index() {
        $blogs = Blog::latest()->get();
        return view('blogs.index', compact('blogs'));
    }
    public function show(Blog $blog) {
        return view('blogs.show', compact('blog'));
    }
    public function store(Request $request) {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'required|string',
        ]);
        // Generate a unique slug
        $slug = str()->slug($request->title);
        $count = Blog::where('slug', $slug)->count();
        if ($count > 0) {
            $slug = $slug . '-' . ($count + 1);
        }
        Blog::create([...$validated, 'slug' => $slug]);
        return redirect()->route('blogs.index');
    }
}ArticleController:
php artisan make:controller ArticleController --resource// app/Http/Controllers/ArticleController.php
use App\Models\Article;
use Illuminate\Http\Request;
class ArticleController extends Controller {
    public function index() {
        $articles = Article::latest()->get();
        return view('articles.index', compact('articles'));
    }
    public function show(Article $article) {
        return view('articles.show', compact('article'));
    }
    public function store(Request $request) {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'required|string',
        ]);
        $slug = str()->slug($request->title);
        $count = Article::where('slug', $slug)->count();
        if ($count > 0) {
            $slug = $slug . '-' . ($count + 1);
        }
        Article::create([...$validated, 'slug' => $slug]);
        return redirect()->route('articles.index');
    }
}5. Create Views
Organize views into separate directories for clarity.
Blogs Index (resources/views/blogs/index.blade.php):
@foreach ($blogs as $blog)
    <a href="{{ route('blogs.show', $blog) }}">{{ $blog->title }}</a>
@endforeachArticles Index (resources/views/articles/index.blade.php):
@foreach ($articles as $article)
    <a href="{{ route('articles.show', $article) }}">{{ $article->title }}</a>
@endforeachBlog Show Page (resources/views/blogs/show.blade.php):
<h1>{{ $blog->title }}</h1>
<p>{{ $blog->content }}</p>Article Show Page (resources/views/articles/show.blade.php):
<h1>{{ $article->title }}</h1>
<p>{{ $article->content }}</p>6. Test the URLs
- Blogs: 
http://yourapp.com/blogs/my-first-blog - Articles: 
http://yourapp.com/articles/my-first-article 
Key Notes:
- Slug Uniqueness: Use a package like 
spatie/laravel-sluggableto automate slug generation. - Shared Logic: Extract common functionality (e.g., slug generation) into traits or parent controllers.
 - Route Model Binding: Use 
sluginstead ofidby overridinggetRouteKeyName()in models. 
This approach ensures clean separation between post types while maintaining scalability.

								
													


No comment yet, add your voice below!