如何在Laravel框架中生成短链接并关联Article、Post、Music三个模型
Hey there! Let's tackle how to connect your existing short URL system with your Article, Post, and Music models. This approach uses polymorphic relationships—the cleanest way to link a single model to multiple other models without duplicating code. Here's a step-by-step breakdown:
First, modify your ShortLink model to support polymorphic relationships. This lets it associate with any of your three models seamlessly.
// app/Models/ShortLink.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphTo; class ShortLink extends Model { protected $fillable = ['code', 'url', 'shortable_type', 'shortable_id']; // Define the polymorphic relationship public function shortable(): MorphTo { return $this->morphTo(); } }
If your existing short_links table doesn't have the required polymorphic columns, create a migration to add them:
Run this command in your terminal:
php artisan make:migration add_shortable_fields_to_short_links_table
Then update the migration file:
// database/migrations/xxxx_xx_xx_add_shortable_fields_to_short_links_table.php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { public function up() { Schema::table('short_links', function (Blueprint $table) { // Adds `shortable_type` (stores the model class name) and `shortable_id` (stores the model ID) $table->morphs('shortable'); }); } public function down() { Schema::table('short_links', function (Blueprint $table) { $table->dropMorphs('shortable'); }); } };
Run the migration to apply the changes:
php artisan migrate
Each of your content models needs a method to access its associated short link. Add this to each model:
For Article:
// app/Models/Article.php use App\Models\ShortLink; use Illuminate\Database\Eloquent\Relations\MorphOne; public function shortLink(): MorphOne { // Use MorphMany instead if you want one model to have multiple short links return $this->morphOne(ShortLink::class, 'shortable'); }
For Post:
// app/Models/Post.php use App\Models\ShortLink; use Illuminate\Database\Eloquent\Relations\MorphOne; public function shortLink(): MorphOne { return $this->morphOne(ShortLink::class, 'shortable'); }
For Music:
// app/Models/Music.php use App\Models\ShortLink; use Illuminate\Database\Eloquent\Relations\MorphOne; public function shortLink(): MorphOne { return $this->morphOne(ShortLink::class, 'shortable'); }
When creating or updating a model (e.g., an Article), you can now attach a short link using the relationship. Here's an example in an Article controller:
// app/Http/Controllers/ArticleController.php use App\Models\Article; use Illuminate\Http\Request; use Illuminate\Support\Str; public function store(Request $request) { // Create the article first $article = Article::create($request->validated()); // Generate your short code (use your existing logic here—this is just an example) $shortCode = Str::random(6); // Attach the short link to the article (automatically sets shortable_type and shortable_id) $article->shortLink()->create([ 'code' => $shortCode, 'url' => route('articles.show', $article) // The full URL you want to shorten ]); return redirect()->route('articles.show', $article); }
To get the short link for any model instance, just call the shortLink relationship:
// Get an article and its short link $article = Article::find(1); $shortUrl = route('shortlinks.redirect', $article->shortLink->code); // Replace with your redirect route // Same for Post or Music $post = Post::find(5); $postShortUrl = route('shortlinks.redirect', $post->shortLink->code);
If you want to access the original model from the short link (for analytics or custom behavior), you can use the polymorphic relationship:
// In your ShortLinkController's redirect method $shortLink = ShortLink::where('code', $request->code)->firstOrFail(); $originalModel = $shortLink->shortable; // This will be an Article, Post, or Music instance // Example: Log a view for the original model $originalModel->increment('view_count'); // Redirect to the full URL return redirect($shortLink->url);
内容的提问来源于stack exchange,提问作者johnDoe220

