ساخت کوتاه کننده لینک با لاراول

به سرم زده یه سایت ساده کوتاه کننده لینک با لاراول بسازم و نشونتون بدم چجوری میشه انجامش داد و اول کار بگم آموزش نیست و احتیاجه از قبل با لاراول آشنا باشین .به نظرم کوتاه کننده لینک ساده ترین وبسایتیه که میشه نوشت،یه جورایی HelloWorldحساب میاد!
میخوام فقط یه صفحه بسازم لینک بهش میدی و کوتاه شدش رو تحویلت میده و وقتی لینک کوتاه شده باز میشه میره توهمون صفحه ای که باید بره .
لاراول رو نصب میکنم و فایل .env روبرای دسترسی به دیتابیس اصلاح میکنم ومدل ومیگریشن وکنترلررو با آرتیسن میسازم.
php artisan make:model Link -m -c
پوشه Auth توی کنترلرها و مدلUser ودوتامیگریشن مربوط به کاربرها و ریست پسورد رو هم پاک میکنم چون بهشون احتیاجی ندارم.میگریشن لینکها رو این شکلی مینویسم.


Schema::create('links', function (Blueprint $table) {
 $table->bigIncrements('id');
 $table->string("slug")->index()->nullable(); // لینک کوتاه شده
 $table->text("url");// لینک اصلی
 });


و میگریت رو انجام میدم.

php artisan migrate

خب حالا وقتشه مدل رو آماده کنم.

class Link extends Model
{
 public $timestamps = false;
 protected $fillable = [
 'slug',
 'url'
 ];
}

خب توی کنترلم اول یه متد مینویسم که صفحه اصلی رو که شامل فرم کوتاه کننده لینک هستش نشونمون بده.

public function show(Request $request)
 {
 return view('home');
 }

یه View جدید هم حاضر میکنم اسمش رو میذارم home.blade.php .
بعد توی web.php روت اصلی رو اصلاح میکنم.

Route::get('/', 'LinkController@show');

حالا میرم سراغ آماده کردن home.blade.php و فرم رو حاضر میکنم.

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>کوتاه کننده لینک</title>

 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
 crossorigin="anonymous">
 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
 crossorigin="anonymous">
</head>

<body>
 <div >
 <div >
 <div > 
 <h2 >کوتاه کننده لینک</h2> 
 <form>
 <input type="url" id="link" placeholder="لینک آدرس" required autofocus>
 <br>
 <button type="button">کوتاه کن</button>
 </form>
 </div>
 </div>
 </div>

 <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
 crossorigin="anonymous"></script>
</body>

</html>

و خب حالا باید یه چیزی بنویسم که بتونم با
ajax jquery
بهش وصل شم و درخواست لینک کوتاه شده بدم.
قبل از هر چیزی من باید به یه روشی مقدار
slug
رو پر کنم که هم خیلی کوتاه باشه و هم منحصر به فرد که بعدا کاربری لینک کوتاه شده رو باز کرد اشتباهی جایی نره. پس اول یه تابع مینویسم که آی دی مدل لینک رو بگیره و بر اساس اون یه رشته خیلی کوتاه و منحصر به فرد تحویلم بده.

protected function generateSlug($id)
 {
 $id-=1; // چون آی دی ها از یک شروع میشن و رشته ها از صفر یه دونه ازش کم میکنم
 $alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789-_";
 $alphaLen = strlen($alpha);
 $out = "";
 while($id > 0) { // تبدیل مبنا از عدد به مبنای من در آوردی
 $out.= $alpha[$id%$alphaLen]; // یه دونه از کاراکتر ها رو میگیرم
 $id = intval($id/$alphaLen); // آی دی رو تقسیم میکنم برای گرفتن المنت بعدی
 }
 return $out;
 }

معیارم بر اساس alpha خواهد بود. اگه بعدا هر گونه دستکاری توی alpha انجام بدم همه چی به طور کل خراب میشه . به نظرم همینی که هست خوبه!
خب حالا وقت به کار انداختن تابع تولید لینک کوتاه هستش.

public function requestLink(Request $request)
 {
 // اول ولیدیشن رو انجام میدم
 $this->validate($request, [ 
 'url' => 'required|url'
 ]);
 // اگه لینک از قبل وجود داشت میگیرم یا یه دونه جدیدش رو میسازم
 $link = Link::where('url', $request->input('url'))->firstOrCreate([
 'url' => $request->input('url')
 ]);
 // مقدار اسلاگ رو بر اساس آیدی تنظیم میکنم مهم نیست از قبل ساخته شده بوده یا نه چون نتیجه بر اساس آی دی هست همیشه همون مقداره
 $link->slug = $this->generateSlug($link->id);
 // سیو میکنم
 $link->save();
 return [ 
 'slug' => $link->slug
 ];
 }

و در نهایت به روت هام اضافه ش میکنم.

Route::post('/request-link', 'LinkController@requestLink')->name("request_link");


حالا وقت نوشتن کد های jquery هست برای کوتاه کردن لینک.

<script>
 $(function(){
 $("form button").click(function(){
 var button = $(this);
 $(button).prop('disabled', true);// دکمه رو تا زمان دریافت نتیجه غیرفعال میشه
 $("form .alert").remove();
 $.ajax({
 url: @json(route("request_link")),
 method: "POST",
 headers: {
 'X-CSRF-TOKEN': @json(csrf_token())
          },
 data: $("form").serialize(),
 success: function(response) {
 // اسلاگ رو نمایش میدیم
 $("form").prepend(`<div >
 ${response.slug}
            </div>`);
 $(button).prop('disabled', false); // دکمه رو فعال میشه
          },
 error: function(xhr, status, errorThrown) {
 // ورودی مشکل داره پس ارور ها رو نشون میدیم
 var urlErrors = xhr.responseJSON.errors.url;
 for(var i in urlErrors) {
 $("form").prepend(`<div >
                <a href="#" data-dismiss="alert" aria-label="close">×</a>
 ${urlErrors[i]}
              </div>`);
            }
 $(button).prop('disabled', false); // دکمه رو فعال میشه
          }
        });
      });
    });
 </script>

خب اینم از این فقط یه چیز دیگه باقی میمونه اونم اینه که به جای این چیز بیخودی یه لینک به جاش به کاربر بدیم که بتونه ازش استفاده کنه.
اول متد ریدایرکت کردن رو مینویسم.

public function openLink($slug)
 {
 return redirect()->to(Link::where('slug', $slug)->firstOrFail()->url);
 }

و به روت ها اضافه ش میکنم.

Route::get('/o/{slug}', 'LinkController@openLink')->name("open_link");

و در نهایت

requestLink


رو یه کم اصلاحش میکنم.

return [ 
 'slug' => route("open_link", ['slug' => $link->slug])
 ];


خب اینم از سایت ساده کوتاه کننده لینک و خب چون که توی ویرگول نمیشه کدها رو به خوبی مشاهده کرد من یه نسخه از این رو روی گیت هاب آپلود میکنم که بتونین اونجا مشاهده کنین

https://github.com/amir9480/laravel-url-shortener-sample

سایر نوشته هام:

https://virgool.io/@amiralizadeh9480/%D8%B3%D8%A7%D8%AE%D8%AA-%D9%81%D8%B1%D9%85-%D8%AA%D9%85%D8%A7%D8%B3-%D8%A8%D8%A7-%D9%85%D8%A7-%D8%B3%D8%A7%D8%AF%D9%87-%D8%AF%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-nlkf9yro0a0c
https://virgool.io/Software/%D8%B3%D8%A7%D8%AE%D8%AA-crud-%D8%A8%D8%A7-%D9%84%D8%A7%D8%B1%D9%88%D8%A7%D9%84-%D9%88-vue-oa3s5ageyafv
https://virgool.io/JavaScript8/%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%D9%81%D8%A7%DB%8C%D9%84-%D9%87%D8%A7%DB%8C-%D8%AA%D8%B1%D8%AC%D9%85%D9%87-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-%D8%AF%D8%B1-%D8%AC%D8%A7%D9%88%D8%A7-%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-mxxpowoydz0z