Laravel 9 create blog

Laravel 9 create blog

إنشاء مدونة في Laravel يتضمن عدة خطوات، بما في ذلك إعداد بيئة Laravel، وتصميم قاعدة البيانات، وإنشاء النماذج ووحدات التحكم وطرق العرض والمسارات، وتنفيذ ميزات مثل إنشاء منشورات المدونة وتحريرها وحذفها

Laravel 9 create blog جدول المحتويات

تثبيت خادم الويب XAMPP

لنظام Windows:

  1. تحميل XAMPP: قم بتحميل XAMPP من موقعه الرسمي: https://www.apachefriends.org/index.html

  2. تثبيت XAMPP:

    • قم بتشغيل ملف التثبيت الذي قمت بتحميله.
    • اتبع الخطوات المعروضة في المعالج لاختيار المكونات التي تريد تثبيتها (Apache و MySQL على الأقل).
    • اختر مجلد لتثبيت XAMPP.
  3. تشغيل Apache و MySQL:

    • بعد التثبيت، قم بتشغيل XAMPP Control Panel.
    • انقر فوق “Start” بجانب Apache و MySQL لتشغيل الخوادم.
  4. تحقق من العمل:

    • افتح متصفح الويب وقم بزيارة http://localhost للتأكد من أن XAMPP تعمل بشكل صحيح.

لنظام macOS:

  1. تحميل XAMPP: قم بتحميل XAMPP من الموقع الرسمي: https://www.apachefriends.org/index.html

  2. تثبيت XAMPP:

    • قم بفتح ملف التثبيت الذي قمت بتحميله.
    • اتبع الإرشادات لتثبيت XAMPP.
  3. تشغيل Apache و MySQL:

    • بعد التثبيت، افتح XAMPP Control Panel.
    • انقر فوق “Start” بجانب Apache و MySQL.
  4. تحقق من العمل:

    • افتح متصفح الويب واذهب إلى http://localhost للتأكد من أن XAMPP تعمل.

لنظام Linux:

  • تحميل XAMPP: قم بتحميل XAMPP من موقعه الرسمي: https://www.apachefriends.org/index.html
  • تثبيت XAMPP:
  • انتقل إلى المجلد الذي قمت بتحميل XAMPP إليه.
  • قم بفتح نافذة الطرفية وقم بتشغيل الأمر التالي لتثبيت XAMPP:
				
					sudo ./xampp-linux-x64-<إصدار>.run

				
			
  • (استبدل <إصدار> بالإصدار الذي قمت بتحميله)
  • تشغيل Apache و MySQL:
  • بعد التثبيت، افتح نافذة الطرفية وأدخل الأمر:
				
					sudo /opt/lampp/lampp start

				
			
  • تحقق من العمل:

افتح متصفح الويب واذهب إلى http://localhost للتحقق من أن XAMPP تعمل.

تثبيت Laravel 9

بعد التاكد من تثبيت composer علي الجهاز الخاص بك استخدم الكود التالي:

				
					composer create-project --prefer-dist laravel/laravel My-Blog "9.*"
				
			

بعد اكتمال التثبيت، انتقل إلى مجلد المشروع باستخدام:

				
					cd My-Blog
				
			

الاتصال بقاعدة البيانات Database

بعد تثبيت تطبيق Laravel 9، نحتاج أولاً إلى إنشاء اتصال بقاعدة بيانات MySQL. لذلك، يتعين علينا فتح ملف .env وتحت هذا الملف، نحتاج إلى إضافة تكوين قاعدة بيانات MySQL مثل اسم قاعدة بيانات MySQL واسم مستخدم قاعدة بيانات MySQL وتفاصيل كلمة المرور. بمجرد تحديد هذه التفاصيل، سيتم إجراء اتصال بقاعدة بيانات MySQL في إطار عمل Laravel 9. يمكنك العثور أدناه على تفاصيل تكوين قاعدة بيانات MySQL.

env.
				
					DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my-blog
DB_USERNAME=root
DB_PASSWORD=
				
			

Laravel UI

لارافيل UI هو حزمة تساعد في تنشيط واجهة تطبيق لارافيل الأمامية باستخدام عروض وموارد مسبقة لإطارات العمل الأمامية الشهيرة مثل Bootstrap وVue.js وReact. يبسط هذا الأمر عملية إعداد مكونات الواجهة الأمامية

				
					composer require laravel/ui
				
			

Bootstrap & Auth

يستخدم لتثبيت حزمة Bootstrap وإنشاء هيكل مبدئي لنظام المصادقة (Authentication) في Laravel. هذا الأمر يقوم بإعداد الجوانب الأساسية لنظام المصادقة مثل تسجيل الدخول (Login) وتسجيل المستخدمين (Registration)

				
					php artisan ui bootstrap --auth
				
			

HomeController

لقد قمت بإنشاء HomeController بعد استخدام الامر السابق والذي يمكنك العثور عليه لو اتبعت الرابط App\Http\Controllers\HomeController.php الآن افتحه وتاكد من لصق الكود التالي أدناه:

				
					<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Contracts\Support\Renderable
     */
    public function index()
    {
        return view('home');
    }
}

				
			

PostController , Table & Model

بعد ذلك نقوم بانشاء جدول في قاعدة البيانات و موديل و كونرولر بنفس الاسم عن طريق الكود التالي

				
					php artisan make:model Post -mc
				
			

بذلك قد انشأنا migration, controller and model باسم post

بعد تشغيل الأمر أعلاه، ستجد ملفًا جديدًا ضمن دليل قاعدة البيانات/الترحيلات. لذلك يتعين علينا فتح هذا الملف وتحت هذا الملف، يتعين علينا تحديد التعليمات البرمجية التالية ضمن ملف الترحيل هذا لإنشاء جدول posts في قاعدة بيانات MySQL.

Table Posts

				
					 public function up() {
  Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title')->nullable();
    $table->text('description')->nullable();
    $table->string('image')->nullable();
    $table->timestamps();
  });
  }
  
				
			

بعد ذلك نقوم بترحيل بيانات الجدول بالامر التالي

				
					php artisan migrate
				
			

بذلك تم انشاء جدول posts في قاعدة البيانات

ثم استخدام الاكواد التالية قبل انشاء صفحات blade

				
					npm install
				
			
				
					npm run dev
				
			

يمكنك استخدام الكود build التالي في حالة حدوث مشاكل في run dev 

				
					npm run build
				
			

بهذا تم استكمال بيئة لارافيل laravel complete

PostController

انت بالفعل قمت بإنشاء PostController والذي يمكنك العثور عليه لو اتبعت الرابط App\Http\Controllers\PostController .php الآن افتحه وتاكد من لصق الكود التالي أدناه:

				
					<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Str;
use App\Models\Post;

class PostController extends Controller
{
    public function index() {
        // $posts = Post::orderBy('created_at', 'desc')->get();
        $posts = Post::all();
        return view('index', ['posts' => $posts]);
      }

      // Create post
public function create() {
    return view('create');
  }
// Store post
public function store(Request $request) {
    // validations
    $request->validate([
      'title' => 'required',
      'description' => 'required',
      'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
    ]);
  
    $post = new Post;
  
    $file_name = time() . '.' . request()->image->getClientOriginalExtension();
    request()->image->move(public_path('images'), $file_name);
  
    $post->title = $request->title;
    $post->description = $request->description;
    $post->image = $file_name;
  
    $post->save();
    return redirect()->route('index')->with('success', 'Post created successfully.');
  }
}

				
			

لا تنسي اضافة الكود التالي للكنترولر add code to PostController في اعلي الصفحة

				
					use App\Models\Post;
				
			

Model

لاستكمال عملية التسجيل في قاعدة البيانات يجب ادخال الكود التالي في الموديل App/Models/Post

				
					<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;
    protected $fillable = 
    ['title', 'description', 'image'];
}

				
			

Blade Files

في البداية نقوم بانشاء مجلد layouts , داخل resources/views

داخل مجلد layouts ننشيء ملف باسم app.blade.php كما في الصورة التالية :

app.blade.php

ثم نقوم بنسخ الكود التالي داخل ملف app.blade.php

				
					<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>My Blog</title>

    
    <link rel="dns-prefetch" href="//fonts.bunny.net">
    <link data-asynced="1" as="style" onload="this.onload=null;this.rel='stylesheet'"  href="https://fonts.bunny.net/css?family=Nunito" rel="preload">

    
    @vite(['resources/sass/app.scss', 'resources/js/app.js'])
</head>
<body>
    <div id="app">
        <nav class="navbar navbar-expand-md navbar-dark bg-success bg-gradient shadow-sm">
            <div class="container">
                <a class="navbar-brand" href="{{ url('/') }}">
                    {{ config('app.name', 'Laravel') }}
                </a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
                    <span class="navbar-toggler-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    
                    <ul class="navbar-nav me-auto">

                    </ul>

                    
                    <ul class="navbar-nav ms-auto">
                        
                        @guest
                            @if (Route::has('login'))
                                <li class="nav-item">
                                    <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
                                </li>
                            @endif

                            @if (Route::has('register'))
                                <li class="nav-item">
                                    <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
                                </li>
                            @endif
                        @else
                            <li class="nav-item dropdown">
                                <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                                    {{ Auth::user()->name }}
                                </a>

                                <div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
                                    <a class="dropdown-item" href="{{ route('logout') }}"
                                       onclick="event.preventDefault();
                                                     document.getElementById('logout-form').submit();">
                                        {{ __('Logout') }}
                                    </a>

                                    <form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
                                        @csrf
                                    </form>
                                </div>
                            </li>
                        @endguest
                    </ul>
                </div>
            </div>
        </nav>

        <main class="py-4">
            @yield('content')
        </main>
    </div> <script data-no-optimize="1">!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).LazyLoad=e()}(this,function(){"use strict";function e(){return(e=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,a=arguments[e];for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(t[n]=a[n])}return t}).apply(this,arguments)}function i(t){return e({},it,t)}function o(t,e){var n,a="LazyLoad::Initialized",i=new t(e);try{n=new CustomEvent(a,{detail:{instance:i}})}catch(t){(n=document.createEvent("CustomEvent")).initCustomEvent(a,!1,!1,{instance:i})}window.dispatchEvent(n)}function l(t,e){return t.getAttribute(gt+e)}function c(t){return l(t,bt)}function s(t,e){return function(t,e,n){e=gt+e;null!==n?t.setAttribute(e,n):t.removeAttribute(e)}(t,bt,e)}function r(t){return s(t,null),0}function u(t){return null===c(t)}function d(t){return c(t)===vt}function f(t,e,n,a){t&&(void 0===a?void 0===n?t(e):t(e,n):t(e,n,a))}function _(t,e){nt?t.classList.add(e):t.className+=(t.className?" ":"")+e}function v(t,e){nt?t.classList.remove(e):t.className=t.className.replace(new RegExp("(^|\\s+)"+e+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")}function g(t){return t.llTempImage}function b(t,e){!e||(e=e._observer)&&e.unobserve(t)}function p(t,e){t&&(t.loadingCount+=e)}function h(t,e){t&&(t.toLoadCount=e)}function n(t){for(var e,n=[],a=0;e=t.children[a];a+=1)"SOURCE"===e.tagName&&n.push(e);return n}function m(t,e){(t=t.parentNode)&&"PICTURE"===t.tagName&&n(t).forEach(e)}function a(t,e){n(t).forEach(e)}function E(t){return!!t[st]}function I(t){return t[st]}function y(t){return delete t[st]}function A(e,t){var n;E(e)||(n={},t.forEach(function(t){n[t]=e.getAttribute(t)}),e[st]=n)}function k(a,t){var i;E(a)&&(i=I(a),t.forEach(function(t){var e,n;e=a,(t=i[n=t])?e.setAttribute(n,t):e.removeAttribute(n)}))}function L(t,e,n){_(t,e.class_loading),s(t,ut),n&&(p(n,1),f(e.callback_loading,t,n))}function w(t,e,n){n&&t.setAttribute(e,n)}function x(t,e){w(t,ct,l(t,e.data_sizes)),w(t,rt,l(t,e.data_srcset)),w(t,ot,l(t,e.data_src))}function O(t,e,n){var a=l(t,e.data_bg_multi),i=l(t,e.data_bg_multi_hidpi);(a=at&&i?i:a)&&(t.style.backgroundImage=a,n=n,_(t=t,(e=e).class_applied),s(t,ft),n&&(e.unobserve_completed&&b(t,e),f(e.callback_applied,t,n)))}function N(t,e){!e||0<e.loadingCount||0<e.toLoadCount||f(t.callback_finish,e)}function C(t,e,n){t.addEventListener(e,n),t.llEvLisnrs[e]=n}function M(t){return!!t.llEvLisnrs}function z(t){if(M(t)){var e,n,a=t.llEvLisnrs;for(e in a){var i=a[e];n=e,i=i,t.removeEventListener(n,i)}delete t.llEvLisnrs}}function R(t,e,n){var a;delete t.llTempImage,p(n,-1),(a=n)&&--a.toLoadCount,v(t,e.class_loading),e.unobserve_completed&&b(t,n)}function T(o,r,c){var l=g(o)||o;M(l)||function(t,e,n){M(t)||(t.llEvLisnrs={});var a="VIDEO"===t.tagName?"loadeddata":"load";C(t,a,e),C(t,"error",n)}(l,function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_loaded),s(e,dt),f(n.callback_loaded,e,a),i||N(n,a),z(l)},function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_error),s(e,_t),f(n.callback_error,e,a),i||N(n,a),z(l)})}function G(t,e,n){var a,i,o,r,c;t.llTempImage=document.createElement("IMG"),T(t,e,n),E(c=t)||(c[st]={backgroundImage:c.style.backgroundImage}),o=n,r=l(a=t,(i=e).data_bg),c=l(a,i.data_bg_hidpi),(r=at&&c?c:r)&&(a.style.backgroundImage='url("'.concat(r,'")'),g(a).setAttribute(ot,r),L(a,i,o)),O(t,e,n)}function D(t,e,n){var a;T(t,e,n),a=e,e=n,(t=It[(n=t).tagName])&&(t(n,a),L(n,a,e))}function V(t,e,n){var a;a=t,(-1<yt.indexOf(a.tagName)?D:G)(t,e,n)}function F(t,e,n){var a;t.setAttribute("loading","lazy"),T(t,e,n),a=e,(e=It[(n=t).tagName])&&e(n,a),s(t,vt)}function j(t){t.removeAttribute(ot),t.removeAttribute(rt),t.removeAttribute(ct)}function P(t){m(t,function(t){k(t,Et)}),k(t,Et)}function S(t){var e;(e=At[t.tagName])?e(t):E(e=t)&&(t=I(e),e.style.backgroundImage=t.backgroundImage)}function U(t,e){var n;S(t),n=e,u(e=t)||d(e)||(v(e,n.class_entered),v(e,n.class_exited),v(e,n.class_applied),v(e,n.class_loading),v(e,n.class_loaded),v(e,n.class_error)),r(t),y(t)}function $(t,e,n,a){var i;n.cancel_on_exit&&(c(t)!==ut||"IMG"===t.tagName&&(z(t),m(i=t,function(t){j(t)}),j(i),P(t),v(t,n.class_loading),p(a,-1),r(t),f(n.callback_cancel,t,e,a)))}function q(t,e,n,a){var i,o,r=(o=t,0<=pt.indexOf(c(o)));s(t,"entered"),_(t,n.class_entered),v(t,n.class_exited),i=t,o=a,n.unobserve_entered&&b(i,o),f(n.callback_enter,t,e,a),r||V(t,n,a)}function H(t){return t.use_native&&"loading"in HTMLImageElement.prototype}function B(t,i,o){t.forEach(function(t){return(a=t).isIntersecting||0<a.intersectionRatio?q(t.target,t,i,o):(e=t.target,n=t,a=i,t=o,void(u(e)||(_(e,a.class_exited),$(e,n,a,t),f(a.callback_exit,e,n,t))));var e,n,a})}function J(e,n){var t;et&&!H(e)&&(n._observer=new IntersectionObserver(function(t){B(t,e,n)},{root:(t=e).container===document?null:t.container,rootMargin:t.thresholds||t.threshold+"px"}))}function K(t){return Array.prototype.slice.call(t)}function Q(t){return t.container.querySelectorAll(t.elements_selector)}function W(t){return c(t)===_t}function X(t,e){return e=t||Q(e),K(e).filter(u)}function Y(e,t){var n;(n=Q(e),K(n).filter(W)).forEach(function(t){v(t,e.class_error),r(t)}),t.update()}function t(t,e){var n,a,t=i(t);this._settings=t,this.loadingCount=0,J(t,this),n=t,a=this,Z&&window.addEventListener("online",function(){Y(n,a)}),this.update(e)}var Z="undefined"!=typeof window,tt=Z&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),et=Z&&"IntersectionObserver"in window,nt=Z&&"classList"in document.createElement("p"),at=Z&&1<window.devicePixelRatio,it={elements_selector:".lazy",container:tt||Z?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",data_bg_hidpi:"bg-hidpi",data_bg_multi:"bg-multi",data_bg_multi_hidpi:"bg-multi-hidpi",data_poster:"poster",class_applied:"applied",class_loading:"litespeed-loading",class_loaded:"litespeed-loaded",class_error:"error",class_entered:"entered",class_exited:"exited",unobserve_completed:!0,unobserve_entered:!1,cancel_on_exit:!0,callback_enter:null,callback_exit:null,callback_applied:null,callback_loading:null,callback_loaded:null,callback_error:null,callback_finish:null,callback_cancel:null,use_native:!1},ot="src",rt="srcset",ct="sizes",lt="poster",st="llOriginalAttrs",ut="loading",dt="loaded",ft="applied",_t="error",vt="native",gt="data-",bt="ll-status",pt=[ut,dt,ft,_t],ht=[ot],mt=[ot,lt],Et=[ot,rt,ct],It={IMG:function(t,e){m(t,function(t){A(t,Et),x(t,e)}),A(t,Et),x(t,e)},IFRAME:function(t,e){A(t,ht),w(t,ot,l(t,e.data_src))},VIDEO:function(t,e){a(t,function(t){A(t,ht),w(t,ot,l(t,e.data_src))}),A(t,mt),w(t,lt,l(t,e.data_poster)),w(t,ot,l(t,e.data_src)),t.load()}},yt=["IMG","IFRAME","VIDEO"],At={IMG:P,IFRAME:function(t){k(t,ht)},VIDEO:function(t){a(t,function(t){k(t,ht)}),k(t,mt),t.load()}},kt=["IMG","IFRAME","VIDEO"];return t.prototype={update:function(t){var e,n,a,i=this._settings,o=X(t,i);{if(h(this,o.length),!tt&&et)return H(i)?(e=i,n=this,o.forEach(function(t){-1!==kt.indexOf(t.tagName)&&F(t,e,n)}),void h(n,0)):(t=this._observer,i=o,t.disconnect(),a=t,void i.forEach(function(t){a.observe(t)}));this.loadAll(o)}},destroy:function(){this._observer&&this._observer.disconnect(),Q(this._settings).forEach(function(t){y(t)}),delete this._observer,delete this._settings,delete this.loadingCount,delete this.toLoadCount},loadAll:function(t){var e=this,n=this._settings;X(t,n).forEach(function(t){b(t,e),V(t,n,e)})},restoreAll:function(){var e=this._settings;Q(e).forEach(function(t){U(t,e)})}},t.load=function(t,e){e=i(e);V(t,e)},t.resetStatus=function(t){r(t)},Z&&function(t,e){if(e)if(e.length)for(var n,a=0;n=e[a];a+=1)o(t,n);else o(t,e)}(t,window.lazyLoadOptions),t});!function(e,t){"use strict";function a(){t.body.classList.add("litespeed_lazyloaded")}function n(){console.log("[LiteSpeed] Start Lazy Load Images"),d=new LazyLoad({elements_selector:"[data-lazyloaded]",callback_finish:a}),o=function(){d.update()},e.MutationObserver&&new MutationObserver(o).observe(t.documentElement,{childList:!0,subtree:!0,attributes:!0})}var d,o;e.addEventListener?e.addEventListener("load",n,!1):e.attachEvent("onload",n)}(window,document);</script><script data-no-optimize="1">var litespeed_vary=document.cookie.replace(/(?:(?:^|.*;\s*)_lscache_vary\s*\=\s*([^;]*).*$)|^.*$/,"");litespeed_vary||fetch("/wp-content/plugins/litespeed-cache/guest.vary.php",{method:"POST",cache:"no-cache",redirect:"follow"}).then(e=>e.json()).then(e=>{console.log(e),e.hasOwnProperty("reload")&&"yes"==e.reload&&(sessionStorage.setItem("litespeed_docref",document.referrer),window.location.reload(!0))});</script><script data-optimized="1" type="litespeed/javascript" data-src="https://onemoka.com/wp-content/litespeed/js/d0cc0031bd7655f0878d7cfa9f9c69b4.js?ver=f0bd1"></script><script>const litespeed_ui_events=["mouseover","click","keydown","wheel","touchmove","touchstart"];var urlCreator=window.URL||window.webkitURL;function litespeed_load_delayed_js_force(){console.log("[LiteSpeed] Start Load JS Delayed"),litespeed_ui_events.forEach(e=>{window.removeEventListener(e,litespeed_load_delayed_js_force,{passive:!0})}),document.querySelectorAll("iframe[data-litespeed-src]").forEach(e=>{e.setAttribute("src",e.getAttribute("data-litespeed-src"))}),"loading"==document.readyState?window.addEventListener("DOMContentLoaded",litespeed_load_delayed_js):litespeed_load_delayed_js()}litespeed_ui_events.forEach(e=>{window.addEventListener(e,litespeed_load_delayed_js_force,{passive:!0})});async function litespeed_load_delayed_js(){let t=[];for(var d in document.querySelectorAll('script[type="litespeed/javascript"]').forEach(e=>{t.push(e)}),t)await new Promise(e=>litespeed_load_one(t[d],e));document.dispatchEvent(new Event("DOMContentLiteSpeedLoaded")),window.dispatchEvent(new Event("DOMContentLiteSpeedLoaded"))}function litespeed_load_one(t,e){console.log("[LiteSpeed] Load ",t);var d=document.createElement("script");d.addEventListener("load",e),d.addEventListener("error",e),t.getAttributeNames().forEach(e=>{"type"!=e&&d.setAttribute("data-src"==e?"src":e,t.getAttribute(e))});let a=!(d.type="text/javascript");!d.src&&t.textContent&&(d.src=litespeed_inline2src(t.textContent),a=!0),t.after(d),t.remove(),a&&e()}function litespeed_inline2src(t){try{var d=urlCreator.createObjectURL(new Blob([t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1")],{type:"text/javascript"}))}catch(e){d="data:text/javascript;base64,"+btoa(t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1"))}return d}</script></body>
</html>

				
			

index.blade.php

داخل resources/views ننشيء ملف باسم index.blade.php ثم نقوم بنسخ الكود التالي داخله

				
					@extends('layouts.app')


@section('content')
<div class="container">
    <div class="titlebar">
      @if (Auth::check())
      <a class="btn btn-success float-end" href="{{ url('/create') }}" role="button">Add Post</a>
      @endif
      <h1>All Posts</h1>
    </div>
    <hr>
  
    @if ($message = Session::get('success'))
    <div class="alert alert-success">
      <p>{{ $message }}</p>
    </div>
    @endif

    @if (count($posts) > 0)
    @foreach ($posts as $post)
      <div class="row">
        <div class="col-12">
          <div class="row">
            <div class="col-2">
              <img decoding="async" class="img-fluid" style="max-width:100%;" src="{{ asset('images/'.$post->image)}}">
            </div>
            <div class="col-10">
              <h4>{{$post->title}}</h4>
              <p>{{$post->description}}</p>
            </div>
          </div>
          <hr>
        </div>
      </div>
    @endforeach
  @else
    <p>No Posts found</p>
  @endif

@endsection
				
			

create.blade.php

داخل resources/views ننشيء ملف باسم create.blade.php ثم نقوم بنسخ الكود التالي داخله

				
					@extends('layouts.app')


@section('content')
<div class="container">
    <div class="titlebar">
      @if (Auth::check())
      <a class="btn btn-success float-end" href="{{ url('/create') }}" role="button">Add Post</a>
      @endif
      <h1>All Posts</h1>
    </div>
    <hr>
  
    @if ($message = Session::get('success'))
    <div class="alert alert-success">
      <p>{{ $message }}</p>
    </div>
    @endif

    @if (count($posts) > 0)
    @foreach ($posts as $post)
      <div class="row">
        <div class="col-12">
          <div class="row">
            <div class="col-2">
              <img decoding="async" class="img-fluid" style="max-width:100%;" src="{{ asset('images/'.$post->image)}}">
            </div>
            <div class="col-10">
              <h4>{{$post->title}}</h4>
              <p>{{$post->description}}</p>
            </div>
          </div>
          <hr>
        </div>
      </div>
    @endforeach
  @else
    <p>No Posts found</p>
  @endif

@endsection
				
			

login.blade.php

بعد ذلك نذهب الي المجلد auth داخل resources/views

داخل مجلد auth سنجد ملف باسم login.blade.php نقوم بنسخ الكود التالي:

				
					@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-6">
            <div class="card bg-warning p-2 bg-opacity-10 bg-gradient shadow-sm">
                <div class="card-header bg-warning bg-opacity-50 bg-gradient">{{ __('Login') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('login') }}">
                        @csrf

                        <div class="row mb-3">
                            <label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">

                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>


                        <div class="row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Login') }}
                                </button>

                                @if (Route::has('password.request'))
                                    <a class="btn btn-link" href="{{ route('password.request') }}">
                                        {{ __('Forgot Your Password?') }}
                                    </a>
                                @endif
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

				
			

register.blade.php

ثم نقوم بنسخ الكود التالي في ملف register.blade.php

				
					@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-6">
            <div class="card bg-warning p-2 bg-opacity-10 bg-gradient shadow-sm">
                <div class="card-header bg-success bg-opacity-75 bg-gradient text-light">{{ __('Register') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('register') }}">
                        @csrf

                        <div class="row mb-3">
                            <label for="name" class="col-md-4 col-form-label text-md-end">{{ __('Name') }}</label>

                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>

                                @error('name')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email">

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">

                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>

                            <div class="col-md-6">
                                <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
                            </div>
                        </div>

                        <div class="row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Register') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

				
			

home.blade.php

ثم نتاكد من نسخ الكود التالي في home.blade.php

				
					@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Dashboard') }}</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif

                    {{ __('You are logged in!') }}
                    <a href="{{ url('/') }}">GoTo Blog Posts</a>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

				
			

The Routes

web.php

داخل مجلد routes يوجد ملف  web.php نقوم بنسخ الكود التالي داخله

				
					<?php

use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Auth;


Route::get('/', [App\Http\Controllers\PostController::class, 'index'])->name('index');
Route::post('store', [App\Http\Controllers\PostController::class, 'store'])->name('posts.store');
Route::get('/create', [App\Http\Controllers\PostController::class, 'create']);

Auth::routes();

Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');


				
			

لامكانية مسح post

نقوم باضافة الكود التالي في PostController 

				
					
  public function destroy(Post $post)
    {
        $post->delete();
        return back()->with('success','Post delete successfully.');
    }
				
			

نقوم باضافة الكود التالي في routes.web

				
					
Route::delete('posts/{post}/delete', [App\Http\Controllers\PostController::class, 'destroy'])->name('posts.destroy');
				
			

نقوم باضافة الكود التالي في index.blade بعد لاين 31 وتعديل لاين 28 الي col-8

				
					         @if (Auth::check())
            <div class="col-2">
              <form action="{{route('posts.destroy',$post->id)}}" method="post">
                @method('delete')
                @csrf
                <input onclick="return confirm('هل انت متاكد ؟ ');" 
                class="text-danger" type="submit" value="Delete" title="تمت ">
            </form>{{-- <a class="btn btn-danger float-end" href="{{ route('posts.delete') }}" role="button">Delete</a> --}}
            </div>
          @endif
				
			

لعرض post في صفحة مستقلة

نقوم باضافة الكود التالي في PostController 

				
					  public function show($id) {
        $posts = Post::where('id', $id)->get();
        return view('show', compact('posts'));
      }
				
			

نقوم باضافة الكود التالي في routes.web

				
					Route::get('show/{post}', [App\Http\Controllers\PostController::class, 'show'])->name('show');

				
			

نقوم بتعديل صفحة index.blade ونسخ الكود التالي

				
					@extends('layouts.app')


@section('content')
<div class="container">
    <div class="titlebar">
      @if (Auth::check())
      <a class="btn btn-success float-end" href="{{ url('/create') }}" role="button">Add Post</a>
      @endif
      <h1>All Posts</h1>
    </div>
    <hr>
  
    @if ($message = Session::get('success'))
    <div class="alert alert-success">
      <p>{{ $message }}</p>
    </div>
    @endif

    @if (count($posts) > 0)
    @foreach ($posts as $post)
      <div class="row">
        <div class="col-12">
          <div class="row">
            <div class="col-2">
              <img decoding="async" class="img-fluid" style="max-width:70%;" src="{{ asset('images/'.$post->image)}}">
            </div>
            <div class="col-8" style="text-align: right;">
              <h4>{{$post->title}}</h4>
              <p>{{$post->description}}</p>
              <a href="{{ route('show',$post->id) }}" class="btn btn-link" style="float: left;">Read More</a>
            </div>
           @if (Auth::check())
            <div class="col-2 p-5">
              <form action="{{route('posts.destroy',$post->id)}}" method="post">
                @method('delete')
                @csrf
                <input onclick="return confirm('هل انت متاكد ؟ ');" 
                class="text-danger" type="submit" value="Delete" title="تمت ">
            </form>{{-- <a class="btn btn-danger float-end" href="{{ route('posts.delete') }}" role="button">Delete</a> --}}
            </div>
          @endif
          </div>
          <hr>
        </div>
      </div>
    @endforeach
  @else
    <p>No Posts found</p>
  @endif

@endsection
				
			

show.blade.php

نقوم بانشاء صفحة show.blade داخل resources/views ونسخ الكود التالي

				
					@extends('layouts.app')


@section('content')
<div class="container">
    <div class="titlebar">
      <a class="btn btn-success float-end" href="{{ url('/') }}" role="button">Back</a>
      @foreach ($posts as $post)
      <div class="row">
        <div class="col-6">
      <h1 class="p-5">{{$post->title}}</h1>
        </div>
          <div class="col-6 text-right">
      <img decoding="async" class="img-fluid" style="max-width:50%;" src="{{ asset('images/'.$post->image)}}">
    </div>
      </div>
    <hr>
            <div class="col-12" style="text-align: right;">
              <p style="font-size: x-large;">{{$post->description}}</p>
              @if (Auth::check())
              <form action="{{route('posts.destroy',$post->id)}}" method="post">
                @method('delete')
                @csrf
                <input onclick="return confirm('هل انت متاكد ؟ ');" 
                class="text-danger" type="submit" value="Delete" title="تمت ">
            </form>
            @endif
            </div>
      </div>
      <hr>
</div>
    @endforeach

@endsection
				
			

في حالة ظهور اي مشكلة اثناء التطبيق ساكون سعيد بحلها معكم . حظ سعيد

Sharing to

Facebook
Twitter
LinkedIn

تفاعلكم معنا يجعلنا نقدم لكم المزيد ويمنحنا طاقة ايجابية تشجعنا علي الاستمرار

3 أفكار عن “Laravel 9 create blog”

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

Scroll to Top