uk
Feedback
| AmirHossein |

| AmirHossein |

Відкрити в Telegram

نوشته‌های یک برنامه‌نویس ناشی 🫂 @StartUnity

Показати більше
635
Підписники
-324 години
-87 днів
-230 день
Архів дописів
🔴 سیستم جدیدی که در آپدیت های آینده به LaraGram اضافه میشه، سیستمی برای مدیریت خطا ها در استفاده از متد های Telegram هست. ◀️
🔴 سیستم جدیدی که در آپدیت های آینده به LaraGram اضافه میشه، سیستمی برای مدیریت خطا ها در استفاده از متد های Telegram هست. ◀️ 3 متد اضافه میشه که روی تمامی API Method های Teelgram به صورت Chain اجرا میشه. ◀️ متد اول tries هست که تعداد تلاش ها برای اجرای یک متد رو مشخص میکنه، به عنون مثال اگر هر 5 بار اجرای متد شکست خورد، متد دوم یعنی catch اجرا میشه و کالبک خودش رو که همراه با خطا هست اجرا میکه. ◀️ متد catch نیز درصورت برخورد با خطا میتونه چندین بار تلاش برای اجرا کالبک خودش بکنه، و درصورتی که تلاش های catch هم با شکست مواجه شد، متد سوم یعنی finally، کالبک خودش رو اجرا میکنه. 🔴 این 3 متد برای مدیریت خطا های سمت API بسیار مفید هستن. ⭐️ اگر مایل بودید با دادن استار به ریپوزیوری ها از پروژه ها حمایت کنید. 📱 LaraGram 📱 Laraquest 📱 Core@AmirhDeveloper@LaraXGram .

منی که دوباره ۲۰۰ تا متد برای توضیح آماده کردم: 😐

فصل پنج - Migrations and Database بخش اول - تعریف و اجرای Migrationها برای ساخت یک جدول ساده با استفاده از مایگریشن در لاراول، می‌توانید مراحل زیر را انجام دهید: ابتدا یک فایل مایگریشن جدید با دستور زیر ایجاد می‌کنیم:
php artisan make:migration create_posts_table --create=posts
این دستور یک فایل مایگریشن جدید به نام create_posts_table در پوشه database/migrations ایجاد می‌کند. حالا می‌توانید به فایل ایجاد شده مراجعه کنید و متد up() را ویرایش کنید تا جدول posts ساخته شود. به عنوان مثال:
return new class extends Migration
{
 public function up()
 {
  Schema::create('posts', function (Blueprint $table) {
   $table->id();
   $table->string('title');
   $table->text('content')->nullable();
   $table->timestamps();
  });
 }

 public function down()
 {
  Schema::dropIfExists('posts');
 }
}
مایگریشن بالا یک جدول با نام posts ایجاد میکند و 5 فیلد مشخص شده در متد up را در آن ایجاد میکند. در نهایت، برای اجرای مایگریشن و ایجاد جدول در پایگاه داده، دستور زیر را اجرا کنید:
php artisan migrate
در ادامه متد های قابل استفاده برای ساخت جدول توضیح داده می شود. در این قسمت با یک فساد جدید به نام Schema آشنا می شویم، این فساد برای تعریف، ایجاد، تغییر و حذف جداول و ستون‌های پایگاه داده در مایگریشن‌ها به‌کار می‌رود. 1- متد create این متد برای ایجاد یک جدول جدید استفاده می‌شود. درون این متد، می‌توان با استفاده از کلاس Blueprint ستون‌ها و ویژگی‌های جدول را تعریف کرد.
Schema::create('posts', function (Blueprint $table) {
 //
});
2- متد table این متد مشابه create اما برای تغییر ساختار یک جدول موجود استفاده می‌شود. می‌توانید ستون‌ها را اضافه، تغییر یا حذف کنید. 3- متد hasTable این متد بررسی می‌کند که آیا جدول مشخصی در پایگاه داده وجود دارد یا خیر.
if (Schema::hasTable('posts')) {
 //
}
4- متد hasColumn این متد بررسی می‌کند که آیا ستون خاصی در یک جدول مشخص وجود دارد یا خیر.
if (Schema::hasColumn('posts', 'title')) {
 //
}
5- متد hasIndex این متد بررسی می‌کند که آیا یک ایندکس (کلید یا شاخص) خاص در جدول موردنظر وجود دارد یا خیر. توجه داشته باشید که این متد ممکن است به همراه برخی نسخه‌های دیتابیس‌ها یا پل‌های خاص لاراول بیشتر کاربرد داشته باشد.
if (Schema::hasIndex('posts', 'posts_title_index')) {
 //
}
6- متد connection این متد برای انجام عملیات Schema بر روی یک اتصال خاص پایگاه داده استفاده می‌شود. به شما اجازه می‌دهد با دیتابیس‌های مختلفی کار کنید.
Schema::connection('sqlite')->create('products', function (Blueprint $table) {
 //
});
7- متد rename این متد نام یک جدول را تغییر می‌دهد.
Schema::rename('old_posts', 'new_posts');
8- متد drop این متد برای حذف کامل یک جدول استفاده می‌شود.
Schema::drop('posts');
9- متد dropIfExists این متد جدول را تنها در صورتی که وجود داشته باشد، حذف می‌کند. این رویکرد از بروز خطا در صورت عدم وجود جدول جلوگیری می‌کند. 10- متد enableForeignKeyConstraints این متد، محدودیت‌های کلید خارجی را در پایگاه داده فعال می‌کند. این متد معمولاً در سیستم‌های مدیریت پایگاه داده مانند MySQL و SQLite مفید است.
Schema::enableForeignKeyConstraints();
11- متد disableForeignKeyConstraints این متد، محدودیت‌های کلید خارجی را در پایگاه داده غیرفعال می‌کند. غیرفعال کردن محدودیت‌ها می‌تواند برای حذف جداول یا تغییر ساختار آنها (مانند حذف یا اضافه کردن ستون‌های مرتبط) که ممکن است در حالت عادی باعث خطا شود، مفید باشد. 12- متد withoutForeignKeyConstraints این متد یک Closure را اجرا می‌کند که در حین اجرای آن، محدودیت‌های کلید خارجی به طور موقت غیرفعال می‌شوند. پس از پایان اجرای Closure، محدودیت‌ها به‌طور خودکار به حالت اولیه بازمی‌گردند.
Schema::withoutForeignKeyConstraints(function () {
 Schema::dropIfExists('posts');
});
در قسمت ها بعدی با متد کلاس Blueprint برای کار با column ها می پردازیم. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۵ 💠 @AmirhDeveloper .

فصل پنج - Migrations and Database بخش اول - تعریف و اجرای Migrationها در لاراول، Migrations یک سیستم برای مدیریت و ایجاد تغییرات در ساختار پایگاه داده است. این سیستم به توسعه‌دهندگان امکان می‌دهد تا جدول‌ها، ستون‌ها و روابط پایگاه داده را با استفاده از کد PHP تعریف، تغییر و مدیریت کنند. با استفاده از مایگریشن ها، تغییرات در پایگاه داده در کنار کد پروژه نگهداری می‌شود و می‌توان آن را به‌راحتی در محیط‌های مختلف به‌روزرسانی کرد. اهداف و مزایای استفاده از مایگریشن‌ها 1- مایگریشن ها به شما این امکان را می‌دهند که تغییرات پایگاه داده را با تغییرات کد هماهنگ کنید. 2- به‌راحتی می‌توانید تغییرات اعمال شده را به نسخه قبلی برگردانید. 3- وقتی توسعه‌دهندگان مختلف روی یک پروژه کار می‌کنند، می‌توانند تغییرات پایگاه داده را به‌صورت کنترل‌شده و منظم در بین خودشان به اشتراک بگذارند. 4- به‌جای ویرایش دستی پایگاه داده، می‌توانید از دستورات ساده برای افزودن یا تغییر جداول استفاده کنید. ایجاد و اجرای مایگریشن برای ایجاد مایگریشن جدید، می‌توانید از دستور Artisan زیر استفاده کنید:
php artisan make:migration create_users_table --create=users
فلگ --create بیانگر این است که مایگریشن برای ساخت جدول جدید می باشد. این دستور یک فایل مایگریشن جدید در پوشه database/migrations ایجاد می‌کند. در فایل مایگریشن معمولاً دو متد اصلی وجود دارد: 1- متد up شامل دستوراتی برای ایجاد یا تغییر ساختار جدول (افزودن ستون‌ها، روابط و غیره) است. 2- متد down شامل دستوراتی برای بازگردانی تغییرات اعمال‌شده در متد up() است. ساختار یک فایل مایگریشن یک مایگریشن نمونه، به شکل زیر است:
return new class extends Migration
{
 public function up(): void
 {
  Schema::create('flights', function (Blueprint $table) {
   $table->id();
   $table->string('name');
   $table->string('airline');
   $table->timestamps();
  });
 }

 public function down(): void
 {
  Schema::drop('flights');
 }
};
اجرای مهاجرت‌ها برای اجرای مایگریشن‌ها و اعمال تغییرات روی پایگاه داده از دستور زیر استفاده می‌شود:
php artisan migrate
این دستور تمامی مایگریشن‌هایی که هنوز اجرا نشده‌اند را اعمال می‌کند. برای بازگرداندن آخرین سری از تغییرات می‌توانید از دستور زیر استفاده کنید:
php artisan migrate:rollback
برای بازگرداندن تمامی تغییرات و شروع از ابتدا:
php artisan migrate:reset
سایر دستورات در پست مربوطه توضیح داده می شود. تغییرات در جداول موجود اگر بخواهید تغییراتی در جداول موجود اعمال کنید، باید از مایگریشن جدیدی استفاده کنید. مثلاً برای افزودن ستون به جدول users می‌توانید از دستور زیر بهره ببرید:
php artisan make:migration add_phone_to_users_table --table=users
فلگ --table بیانگر این است که مایگریشن برای ویرایش جدول موجود می باشد. سپس در فایل مایگریشن ایجادشده می‌توانید تغییرات خود را اعمال کنید. اصول نام‌گذاری مایگریشن‌ها انتخاب نام‌های مناسب برای مایگریشن‌ها از اهمیت ویژه‌ای برخوردار است، زیرا نه تنها باعث خوانایی و شفافیت کد می‌شود، بلکه به وضوح نقش و وظیفه‌ی هر مایگریشن را مشخص می‌کند. لاراول از نام فایل‌ها و کلاس‌های مایگریشن برای سازمان‌دهی و اجرای صحیح آن‌ها استفاده می‌کند. 1- نام مایگریشن باید عملی که انجام می‌دهد را توصیف کند. به عنوان مثال: create_users_table add_email_to_users_table remove_phone_from_users_table update_orders_status 2- نام مایگریشن معمولاً با فعلی که عمل اصلی را توصیف می‌کند شروع می‌شود، سپس به اسم جدول یا ستون مورد نظر اشاره می‌کند. این قالب باعث شفافیت بیشتر می‌شود و به راحتی می‌توان فهمید که مایگریشن چه کاری انجام می‌دهد. 3- هنگام اشاره به جداول، معمولاً از نام‌های جمع استفاده می‌شود. برای مثال، مایگریشن مربوط به جدول کاربران به صورت create_users_table نام‌گذاری می‌شود و نه create_user_table. 4- سعی کنید از نام‌های طولانی و زائد پرهیز کنید. نام‌ها باید توصیفی و مختصر باشند. برای مثال، به جای add_new_email_column_to_users_table می‌توانید از add_email_to_users_table استفاده کنید. 5- برای نام‌گذاری فایل‌ها و کلاس‌های مایگریشن از قالب snake_case استفاده می‌شود، که بین کلمات از خط زیرین _ استفاده می‌کند. این قالب به‌طور پیش‌فرض توسط دستور php artisan make:migration رعایت می‌شود. در قسمت بعدی با متد های ساخت جداول به وسیله ی مایگریشن ها آشنا می شویم. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۵ 💠 @AmirhDeveloper .

فصل 4 اینجا به پایان رسید. این فصل طولانی ترین فصل بود، و سایر فصل ها سریع تر پیش میرن. اگر چیزی در رابطه با الوکوئنت و مدل ها جا مونده بگید توضیح بدیم و فصل 5 رو شروع کنیم.

فصل چهار - مدل‌ها و Eloquent ORM بخش دهم - Route Model Binding ‏Route Model Binding به ما اجازه می‌دهد تا به صورت مستقیم و خودکار مدل‌های لاراول را از URL به دست آوریم و در کنترلر استفاده کنیم. به عنوان مثال، اگر یک Post داریم و بخواهیم یک پست خاص را با استفاده از شناسه (ID) در URL بازیابی کنیم، معمولاً بدون استفاده از این ویژگی کدی شبیه به زیر می‌نویسیم:
Route::get('/posts/{id}', function($id) {
 $post = Post::findOrFail($id);
 return view('posts.show', compact('post'));
});
اما با استفاده از Route Model Binding می‌توانیم کد را ساده‌تر کنیم:
Route::get('/posts/{post}', function(Post $post) {
 return view('posts.show', compact('post'));
});
لاراول از مقدار {post} در مسیر استفاده می‌کند تا مدل Post را بر اساس مقدار (به طور پیش‌فرض id) جستجو کرده و به کنترلر ارسال کند. نکته: این قابلیت برای انواع مدل‌ها قابل استفاده است و شما می‌توانید از Custom Key‌ها نیز استفاده کنید. همانطور که توضیح داده شد، {post} به طور پیشفرض بر اساس فیلد id جست و جو می کند، اما میتوانید به سادگی فیلد پیشفرض را تغییر دهید:
Route::get('/posts/{post:slug}', function(Post $post) {
 return view('posts.show', compact('post'));
});
در کد بالا به جای {post}، از {post:slug} استفاده شده، به این معنی که از فیلد slug برای جست و جو استفاده شود، میتوانید فیلد مورد نظر را به جای slug بنویسید. همچنین میتوانید فیلد پیشفرض را در مدل تغییر دهید:
class Post extends Model
{
 public function getRouteKeyName()
 {
  return 'slug';
 }
}
در این صورت با نوشتن {post} به طور پیشفرض از فیلد slug برای جست و جو استفاده می شود. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .

فصل چهار - مدل‌ها و Eloquent ORM بخش نهم - Transactions تراکنش‌ها یا Transactionها برای انجام چندین عملیات پایگاه داده به صورت یکجا استفاده می‌شوند. به عبارت دیگر، اگر همه عملیات موفق باشند، تغییرات به پایگاه داده اعمال می‌شود، اما اگر یکی از عملیات‌ها با خطا مواجه شود، تمامی تغییرات لغو می‌شوند (rollback). این موضوع به ویژه برای اطمینان از یکپارچگی داده‌ها در سناریوهایی که شامل چندین عملیات هستند مفید است، مانند ثبت چند جدول همزمان، مدیریت تراکنش‌های بانکی و غیره. لاراول برای مدیریت تراکنش‌ها متدهایی را فراهم می‌کند که در فساد DB قرار دارند. متد ها عبارتند از: 1- متد beginTransaction برای شروع یک تراکنش. 2- متد commit برای تأیید و ثبت تراکنش. 3- متد rollBack برای لغو تغییرات در صورت بروز خطا. 4- متد afterCommit برای انجام عملیات پس از commit. مثال:
try {
 DB::beginTransaction();

 DB::table('users')->insert([
  'name' => 'John',
  'email' => 'john@example.com',
  'password' => bcrypt('1234')
 ]);

 DB::table('profiles')->insert([
  'user_id' => 1,
  'bio' => 'Test Bio',
  'age' => 25
 ]);

 DB::commit();
} catch (\Exception $e) {
 DB::rollBack();
 echo "Error: " . $e->getMessage();
}
در ابتدا تراکنش با beginTransaction آغاز می‌شود. دو عملیات insert در جدول‌های مختلف انجام می‌شود. اگر همه عملیات بدون خطا انجام شوند، با commit تغییرات ثبت می‌شود. اگر خطا رخ دهد (مانند ارور در هر یک از عملیات)، با استفاده از catch خطا مدیریت شده و rollBack فراخوانی می‌شود تا تغییرات لغو شود. لاراول همچنین یک متد ساده‌تر و قابل خواندن‌تر به نام transaction ارائه می‌دهد که می‌توان کل تراکنش را در یک Closure قرار داد: مثال:
DB::transaction(function () {
 DB::table('users')->insert([
  'name' => 'John',
  'email' => 'john@example.com',
  'password' => bcrypt('1234')
 ]);

 DB::table('profiles')->insert([
  'user_id' => 2,
  'bio' => 'Test Bio',
  'age' => 30
 ]);
})
اگر کد داخل transaction موفق باشد، تغییرات به صورت خودکار ذخیره (commit) می‌شود. در صورت بروز خطا، تغییرات به صورت خودکار لغو (rollback) می‌شوند. این متد علاوه بر اجرای کد در قالب تراکنش، تعداد دفعاتی که باید در صورت مواجهه با خطا مجدد تلاش کند را می‌پذیرد. این ویژگی برای مواقعی که با عملیات‌های رقابتی روبرو هستید (مانند lockها یا عملیات با احتمال تعارض) مفید است.
DB::transaction(function () {
 // 
}, 3)
متد afterCommit به شما امکان می‌دهد که یک callback یا عملیات خاص را پس از موفقیت‌آمیز بودن commit اجرا کنید. برای مثال، می‌توانید پس از ذخیره تغییرات، رویدادهایی مثل ارسال ایمیل را انجام دهید.
DB::afterCommit(function () {
 echo "Success";
});
می‌توانید از پارامترهایی برای کنترل تراکنش استفاده کنید. به عنوان مثال، تنظیم چندین تراکنش تو در تو (nested transactions) نیز در لاراول امکان‌پذیر است. تراکنش‌ها در سناریوهایی مانند عملیات مالی، مدیریت سفارشات یا عملیات‌های مربوط به موجودی کالا اهمیت زیادی دارند. با استفاده از آن‌ها می‌توانید از ناسازگاری داده‌ها و بروز اشکالات جدی در پایگاه داده جلوگیری کنید. به طور خلاصه، تراکنش‌ها در لاراول به شما امکان می‌دهند عملیات مختلف پایگاه داده را به صورت امن انجام دهید، به طوری که در صورت بروز خطا همه تغییرات برگردانده شود. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .

فصل چهار - مدل‌ها و Eloquent ORM بخش هشتم - Observers مشاهده‌گرها یا Observer‌ ها به عنوان کلاس‌هایی شناخته می‌شوند که برای نظارت بر رخدادهای مدل‌های Eloquent طراحی شده‌اند. زمانی که می‌خواهید منطق خاصی را قبل یا بعد از رخ دادن یک عمل (مانند ایجاد، به‌روزرسانی یا حذف یک رکورد) انجام دهید، می‌توانید از Observerها استفاده کنید. این امر منجر به جداسازی بهتر منطق بیزنسی از کنترلرها و مدل‌ها و بهبود قابلیت نگهداری کد می‌شود. لاراول اجازه می‌دهد تا به چندین رخداد پیش‌فرض مدل گوش دهید که با آنها در بخش قبل آشنا شدیم. برای ایجاد یک Observer جدید می‌توانید از دستور Artisan استفاده کنید:
php artisan make:observer UserObserver --model=User
این دستور یک کلاس به نام UserObserver می‌سازد و آن را با مدل User مرتبط می‌کند. پس از ایجاد، شما می‌توانید متدهایی مانند created، updated و غیره را در آن تعریف کنید تا بر اساس رخدادها اجرا شوند. فرض کنید می‌خواهیم زمانی که یک کاربر جدید ایجاد شد، یک پیام خوش‌آمدگویی برای او ارسال شود. ابتدا یک Observer برای مدل User ایجاد می‌کنیم. در فایل app/Observers/UserObserver.php کدی مانند زیر را اضافه می‌کنیم:

class UserObserver
{
 public function created(User $user)
 {
  Mail::to($user->email)->send(new \App\Mail\WelcomeMail($user));
 }
}
متد created درواقع یک رخداد است که با لیست آنها در بخش قبل آشنا شده ایم، درنتیجه میتوان از هر یک از آنها بسته به نیاز به جای created استفاده کرد. باید این Observer را در AppServiceProvider یا هر جای دیگری که مناسب است، ثبت کنید. این کار معمولاً در متد boot انجام می‌شود:
class AppServiceProvider extends ServiceProvider
{
 public function boot()
 {
  User::observe(UserObserver::class);
 }
}
اکنون، هر بار که یک شیء جدید از مدل User ایجاد شود، متد created در UserObserver فراخوانی می‌شود و ایمیل خوش‌آمدگویی ارسال می‌شود. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .

فصل چهار - مدل‌ها و Eloquent ORM بخش هفتم - Events ایونت ها به شما اجازه می‌دهند تا قبل و بعد از رخ دادن عملیات‌های مختلفی روی مدل‌ها (مانند ایجاد، به‌روزرسانی، حذف و غیره) کدهای دلخواهی را اجرا کنید. این قابلیت به شما امکان می‌دهد تا فرآیندهایی مانند ثبت لاگ‌ها، ارسال اعلان‌ها، اعتبارسنجی‌ها و سایر عملیات وابسته به مدل‌ها را به‌صورت خودکار و در لحظه مدیریت کنید. لاراول رویدادهای مختلفی را برای مدل‌ها فراهم می‌کند که می‌توانید آن‌ها را در هر مرحله از چرخه حیات یک مدل استفاده کنید. این رویدادها به شما اجازه می‌دهند قبل یا بعد از عملیاتی مانند ایجاد، به‌روزرسانی، حذف یا بازگردانی رکوردها، کدهای سفارشی خود را اجرا کنید. لیست رویدادهای Eloquent 1- رویداد retrieved بعد از اینکه یک مدل از دیتابیس بازیابی شد، اجرا می‌شود. 2- رویداد creating قبل از ایجاد یک رکورد جدید در دیتابیس اجرا می‌شود. 3- رویداد created بعد از ایجاد یک رکورد جدید اجرا می‌شود. 4- رویداد updating قبل از به‌روزرسانی یک رکورد اجرا می‌شود. 5- رویداد updated بعد از به‌روزرسانی یک رکورد اجرا می‌شود. 6- رویداد saving قبل از ذخیره‌شدن (چه ایجاد و چه به‌روزرسانی) یک مدل اجرا می‌شود. 7- رویداد saved بعد از ذخیره‌شدن یک مدل اجرا می‌شود. 8- رویداد deleting قبل از حذف یک رکورد اجرا می‌شود. 9- رویداد deleted بعد از حذف یک رکورد اجرا می‌شود. 10- رویداد restoring قبل از بازگردانی یک رکورد حذف‌شده اجرا می‌شود. 11- رویداد restored بعد از بازگردانی یک رکورد حذف‌شده اجرا می‌شود. 12- رویداد trashed بعد از soft delete شدن یک رکورد اجرا می شود. 13- رویداد forceDeleting قبل از حذف کامل حتی با وجود soft delete اجرا می شود. 14- رویداد forceDeleted بعد از حذف کامل حتی با وجود soft delete اجرا می شود. 15- رویداد replicating قبل از replicate شدن یک رکورد اجرا می شود. برای استفاده از رویدادها در Eloquent، شما می‌توانید از متد boot() در مدل خود استفاده کنید و در آن رویدادهای دلخواه را تعریف کنید.
protected static function boot()
{
 parent::boot();
 static::creating(function ($user) {
  Log::info('Creating new user: ' . $user->name);
 });

 static::created(function ($user) {
  Log::info('New user Created: ' . $user->name);
 });
}
در این مثال: در رویداد creating، لاگ مربوط به زمانی که یک کاربر جدید در حال ایجاد است ثبت می‌شود. در رویداد created، لاگ مربوط به زمانی که یک کاربر با موفقیت ایجاد شد ثبت می‌شود. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .

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

گزارشی از تغییرات پروژه و هدفم از توسعه LaraGram☕ سیستم کش تا حدودی به LaraGram اضافه شده. در حال حاضر config ها و service provider ها و package ها کش میشن. کش service provider های deferrable تا حدی وابسته به سیستم event هست که هنوز پیاده سازی نشده ولی فعلا کار میکنه بدون ایراد. به زودی سیستم event و listener ها به container اضافه میشن و این مشکل هم کاملا برطرف میشه. از طرفی console kernel و http kernel نیاز به بازنویسی کامل داره برای event ها. اینها تنها بخشی از تغییرات مورد نیاز برای اضافه کردن یک سیستم کشینگ هست، تغییرات زیادی هم صورت گرفته مثلا service provider ها گسترده تر شدن، bootstrapper ها به application اضافه شدن. وظیفه ساخت application از متد ساده __construct به سیستم application builder داده شده. ConfigRepository گسترده تر شده کنارش ProviderRepository اضافه شده، PackageManifest و AliasLoader و و و و ... اینها همه بخش کوچکی از پیچیدگی های توسعه framework هستن. یه نکته این وسط بگم که حواستون رو موقع commit و push کردن جمع کنید تا مثل من کد هارو push نکنید توی branch اشتباهی، الان حتی نمیتونم باگ فیکس بدم😒 وقتی توسعه LaraGram رو شروع کردم هدف خاصی پشتش نبود. صرفا تازه با Laravel آشنا شده بودم و منم میخواستم یکی مثلشو بزنم. شروع به ساخت ورژن 1 LaraGram کردم، تقریبا هر روز روش فعالیت داشتم و یک نسخه پایدار ازش رو توسعه دادم و موفق شدم اون رو توی صفحه نمونه های تلگرام هم منتشر کنم. جلوتر که رفتم و فهمیدم حتی PHP هم بلد نیستم، از اونجا هدفم از توسعه LaraGram شد یادگیری. 90 درصد دانشی که الان از PHP، Laravel، Design patterns و... دارم رو با توسعه LaraGram بدست اوردم. اگر بخوایم سطح علمی من رو از ابتدای شروع پروژه LaraGram نسبت به الان مقایسه کنیم میتونیم کد های ورژن 1 لاراگرام رو با ورژن 2 مقایسه کنیم. ورژن 1، شاید اون اوایل برای خودم خفن بود ولی الان حتی نمیخوام نگاهش کنم☕ تمام LaraGram یک کپی از Laravel هست برای توسعه ربات، اما این کپی کردن که حتی 10 درصدش هم تا الان کپی نشده حدود 2 سال زمان برده. من هیچی از PHP بلد نبودم ولی الان هسته فریم ورک بزرگی مثل لاراول رو حفظ هستم، به معنای واقعی حفظم. کافیه یک متد از اون وسطای vendor ببینم و بفهمم مال چیه و کجاس. همه ش رو مدیون توسعه LaraGram هستم. حفظ بودن هسته Laravel شاید خودش ارزشی نداشته باشه ولی این حفظ بودن به معنی اینه که ده ها دیزاین پترن و شیوه های کد نویسی، سینتکس ها و ... رو یادگرفتم. همیشه یادگیری با دیدن فیلم آموزشی و خوندن داکیومنت و کتاب نیست. بخش بزرگی از یادگیری دست به کد شدنه، بدون ترس از دیدن کد های پیچیده شروع به خوندشون کردن. اون اوایل هیچی از Laravel نمیفهمیدم، حتی برای پیدا کردن نقطه شروع Laravel چند روز داشتم فایل هاشو زیر و رو میکردم. من کتابی از برنامه نویسی نخوندم، ویدئو هم در حد مقدماتی php و laravel دیدم که کلا 0.5 درصد چیزی که بلدم هم نیست، بقیه همش با توسعه پروژه مخصوصا LaraGram بوده. یه بخشی هم از آموزش دادن بوده، بخشی از پست هایی که توی این کانال گزاشم رو خودم باهاش یاد گرفتم. این به این معنی نیست کتاب نخونید و فیلم نبینید، هر کدوم سرجای خودشه. تا زمانی که شروع به زدن پروژه نکنید، هر چند صد ساعت ویدئو دیدن و کتاب خوندن فایده ای نداره. این تنها دلیل من از توسعه LaraGram هست😒 @AmirhDeveloper .

بعد کلی وقت گفت و گو ها به LaraGram اضافه شدن! 🔴 با گفت و گو ها میتونید به سادگی یک گفت و گو بین کاربر و ربات ایجاد کنید. ⬇️
بعد کلی وقت گفت و گو ها به LaraGram اضافه شدن! 🔴 با گفت و گو ها میتونید به سادگی یک گفت و گو بین کاربر و ربات ایجاد کنید. ⬇️ قابلیت ها: ◀️ ولیدیت کردن پاسخ هر سوال ◀️ نام گذاری برای هر سوال جهت پردازش راحت تر. ◀️ ارسال سوال به صورت media ◀️ ساخت گفت و گو با کیبورد ◀️ مشخص کردن کامند جهت skip سوال ◀️ مشخص کردن تعداد Attempt ◀️ مشخص کردن Timeout بدون پاسخ ماندن ◀️ مشحص کردن کامند لغو گفت و گو ◀️ مشخص کردن عملیات پس از گفت و گو ◀️ رویداد لغو گفت و گو ◀️ رویداد پایان گفت و گو همه این قابلیت ها تنها با متد های پیش ساخته با یک خط کد. میتونید گفت و گو هارو با یک کامند ایجاد کنید:
php laragram make:conversation Greeting
و به سادگی اون رو توی کنترلر ها یا لیسنر ها شروع کنید:
Conversation::start('Greeting');
پس از آن ربات به صورت خودکار عملیات اعتبارسنجی پاسخ ها و مدیریت آن ها را بر عهده خواهد گرفت. ◀️ در ادامه متد های has و hasNot به سیستم کش اضافه شده برای بررسی وجود یک کش. ◀️ متد های getUpdateType و getUpdateMessageSubType به فساد Request اضافه شدن برای بررسی نوع آپدیت. ◀️ کانفیگ های limit و allowed_updates به Laraquest اضافه شدن برای Long Polling. ◀️ متد starting به فساد Console اضافه شده برای ثبت کامند در پروایدر ها. ◀️ فایل های کانفیگ کاملا تغییر کردند و درصورت بروزرسانی پروژه نیاز کانفیگ مجدد دارند. ◀️ سایر تغییرات رفع ایراد بوده. ⭐️ اگر مایل بودید با دادن استار به ریپوزیوری ها از پروژه ها حمایت کنید ⭐️ 📱 LaraGram 📱 Laraquest 📱 Core@AmirhDeveloper@LaraXGram

بعد کلی وقت گفت و گو ها به LaraGram اضافه شدن! 🔴 با گفت و گو ها میتونید به سادگی یک گفت و گو بین کاربر و ربات ایجاد کنید. ⬇️
بعد کلی وقت گفت و گو ها به LaraGram اضافه شدن! 🔴 با گفت و گو ها میتونید به سادگی یک گفت و گو بین کاربر و ربات ایجاد کنید. ⬇️ قابلیت ها: ◀️ ولیدیت کردن پاسخ هر سوال ◀️ نام گذاری برای هر سوال جهت پردازش راحت تر. ◀️ ارسال سوال به صورت media ◀️ ساخت گفت و گو با کیبورد ◀️ مشخص کردن کامند جهت skip سوال ◀️ مشخص کردن تعداد Attempt ◀️ مشخص کردن Timeout بدون پاسخ ماندن ◀️ مشحص کردن کامند لغو گفت و گو ◀️ مشخص کردن عملیات پس از گفت و گو ◀️ رویداد لغو گفت و گو ◀️ رویداد پایان گفت و گو همه این قابلیت ها تنها با متد های پیش ساخته با یک خط کد. میتونید گفت و گو هارو با یک کامند ایجاد کنید:
php laragram make:conversation Greeting
و به سادگی اون رو توی کنترلر ها یا لیسنر ها شروع کنید:
Conversation::start('Greeting');
پس از آن ربات به صورت خودکار عملیات اعتبارسنجی پاسخ ها و مدیریت آن ها را بر عهده خواهد گرفت. ◀️ در ادامه متد های has و hasNot به سیستم کش اضافه شده برای بررسی وجود یک کش. ◀️ متد های getUpdateType و getUpdateMessageSubType به فساد Request اضافه شدن برای بررسی نوع آپدیت. ◀️ کانفیگ های limit و allowed_updates به Laraquest اضافه شدن برای Long Polling. ◀️ متد starting به فساد Console اضافه شده برای ثبت کامند در پروایدر ها. ◀️ فایل های کانفیگ کاملا تغییر کردند و درصورت بروزرسانی پروژه نیاز کانفیگ مجدد دارند. ◀️ سایر تغییرات رفع ایراد بوده. ⭐️ اگر مایل بودید با دادن استار به ریپوزیوری ها از پروژه ها حمایت کنید ⭐️ 📱 LaraGram 📱 Laraquest 📱 Core@AmirhDeveloper@LaraXGram

فصل چهار - مدل‌ها و Eloquent ORM بخش هفتم - Accessors و Mutators به شما این امکان را می‌دهند که نحوه دسترسی به ویژگی‌های مدل یا نحوه تغییر و ذخیره‌سازی داده‌ها در مدل را سفارشی‌سازی کنید. شما می‌توانید Accessors برای نمایش داده‌ها به شکلی متفاوت و Mutators برای ذخیره‌سازی داده‌ها با فرمت موردنظر خود ایجاد کنید. 1- Accessors (دسترسی‌دهنده‌ها) برای تغییر داده‌هایی استفاده می‌شود که هنگام دسترسی به یک ویژگی مدل نمایش داده می‌شوند. فرض کنید یک مدل کاربر (User) دارید و می‌خواهید نام کاربر همیشه با حرف اول بزرگ نمایش داده شود.
protected function name(): Attribute
{
 return Attribute::make(
  get: fn ($value) => ucfirst($value)
 );
}
در این مثال، هر زمانی که به ویژگی name مدل User دسترسی پیدا کنید، مقدار آن با حرف اول بزرگ برگردانده می‌شود. 2- Mutators (تغییر‌دهنده‌ها) برای تغییر و اصلاح داده‌ها قبل از ذخیره‌سازی در دیتابیس استفاده می‌شوند. فرض کنید می‌خواهید مطمئن شوید که هر زمان ایمیل کاربر ذخیره می‌شود، به حروف کوچک تبدیل شود.
protected function email(): Attribute
{
 return Attribute::make(
  set: fn ($value) => strtolower($value)
 );
}
در این مثال، هر زمانی که ایمیلی به مدل User اختصاص داده می‌شود، قبل از ذخیره‌سازی به حروف کوچک تبدیل خواهد شد. 3- ترکیب Accessors و Mutators در بسیاری از موارد، شما می‌توانید Accessors و Mutators را در یک متد به صورت ترکیبی استفاده کنید. یعنی یک متد هم می‌تواند داده‌ها را هنگام دسترسی تغییر دهد (Accessor) و هم هنگام ذخیره‌سازی (Mutator). فرض کنید می‌خواهید نام کاربر هنگام دسترسی به آن با حرف بزرگ و هنگام ذخیره‌سازی با حروف کوچک مدیریت شود.
protected function name(): Attribute
{
 return Attribute::make(
  get: fn ($value) => ucfirst($value),
  set: fn ($value) => strtolower($value)
 );
}
در این مثال، نام کاربر هنگام بازیابی از دیتابیس با حرف بزرگ نمایش داده می‌شود، اما قبل از ذخیره به حروف کوچک تبدیل می‌شود. 4- استفاده از Accessors و Mutators هنگامی که Accessors و Mutators تعریف می‌شوند، شما می‌توانید به‌طور معمول از ویژگی‌های مدل استفاده کنید.
$user = new User();
$user->name = 'jane doe';
echo $user->name; // Jane doe
5- روش قدیمی (ورژن 8 به قبل) در روش قدیمی، برای تعریف Accessors و Mutators باید از متدهای get{AttributeName}Attribute و set{AttributeName}Attribute استفاده می‌کردید.
public function getNameAttribute($value)
{
 return ucfirst($value);
}

public function setEmailAttribute($value)
{
 $this->attributes['email'] = strtolower($value);
}
اما در استفاده با روش جدید یکسان است. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .

فصل چهار - مدل‌ها و Eloquent ORM بخش ششم - Casts کست یک ویژگی در مدل‌های لاراول است که به شما امکان می‌دهد نوع داده‌ای که از ستون‌های دیتابیس بازیابی می‌شود یا به دیتابیس ذخیره می‌شود را خودکار مدیریت کنید. لاراول از Casts برای تبدیل داده‌ها به نوع‌های مختلف استفاده می‌کند تا توسعه‌دهندگان بدون نیاز به نوشتن کد اضافی، نوع داده موردنظر خود را مدیریت کنند. برای تعریف Castهای پیش‌فرض، متد casts() را در مدل خود پیاده‌سازی می‌کنید.
protected function casts(): array
{
 return [
  'is_active' => 'boolean',
  'birthday' => 'date',
 ];
}
این کست ها باعث می شود داده به طور خودکار به فرمت یا نوع مشخص شده تبدیل شوند، به عنوان مثال اگر فیلد is_active برابر 0 باشد به واسطه کست ها به false تبدیل می شود. در لاراول، چندین نوع Cast پیش‌فرض وجود دارد که به شما امکان می‌دهد داده‌ها را به صورت خودکار به نوع‌های مختلف تبدیل کنید. در زیر لیست این Castها آورده شده است:
'is_active' => 'boolean',
'age' => 'integer',
'price' => 'float',
'phone_number' => 'string',
'meta' => 'array',
'preferences' => 'json',
'settings' => 'object',
'tags' => 'collection',
'birthday' => 'date',
'created_at' => 'datetime',
'event_time' => 'timestamp',
'birthday' => 'immutable_date',
'created_at' => 'immutable_datetime',
'password' => 'encrypted',
علاوه بر Castهای پیش‌فرض، لاراول این امکان را به شما می‌دهد تا Casts سفارشی بسازید. این Castها به شما اجازه می‌دهند که تبدیل‌های پیچیده‌تری برای داده‌ها اعمال کنید. برای ساخت یک Cast سفارشی، ابتدا باید یک کلاس ایجاد کنید که قرارداد (interface) CastsAttributes را پیاده‌سازی کند. این کلاس باید دو متد get() و set() را پیاده‌سازی کند. برای این کار می توانید از دستور زیر استفاده کنید:
php artisan make:cast Uppercase
این کامند یک کلاس برای کست سفارشی شما ایجاد می کنید و شما می توانید متد ها آن را پیاده سازی کنید:
class Uppercase implements CastsAttributes
{
 public function get($model, string $key, $value, array $attributes)
 {
  return strtoupper($value);
 }

 public function set($model, string $key, $value, array $attributes)
 {
  return strtolower($value);
 }
}
درصورتی که یک فیلد را از دیتابیس فراخوانی کنیم و کست Uppercase ما روی آن اعمال شده باشد متد get اجرا خواهد شد و درصورت دخیره در یک فیلد دیتابیس دارای کست Uppercase متد set اجرا خواهد شد. توضیح ورودی های متد set و متد get: 1- پارامتر model: این پارامتر یک شیء مدل را شامل می‌شود که نشان‌دهنده مدل فعلی است که در حال تعامل با آن هستید. این پارامتر به شما اجازه می‌دهد به ویژگی‌های مدل دسترسی داشته باشید. 2- پارامتر key: این پارامتر نام ویژگی (attribute)‌ای است که Cast برای آن تعریف شده است. با این پارامتر، می‌توانید بدانید که کدام فیلد از مدل در حال پردازش است. 3- پارامتر value: این پارامتر مقدار فعلی ویژگی (attribute) را شامل می‌شود. هنگام استفاده از get()، مقدار بازیابی‌شده از دیتابیس در این پارامتر قرار دارد و در set()، مقدار جدیدی که کاربر برای آن ویژگی تنظیم کرده است. 4- پارامتر attributes: این پارامتر آرایه‌ای شامل همه ویژگی‌های مدل و مقادیر آن‌ها است. این پارامتر به شما امکان می‌دهد به سایر ویژگی‌های مدل دسترسی پیدا کنید و بر اساس مقادیر آن‌ها تغییراتی ایجاد کنید. پس از تعریف Cast سفارشی، شما می‌توانید آن را در متد casts() مدل خود استفاده کنید.
protected function casts(): array
{
 return [
  'name' => Uppercase::class,
 ];
}
نکته: در نسخه 10 به قبل کست ها به جای متد در یک پراپرتی ثبت میشوند:
protected $casts = [
 'is_admin' => 'boolean',
];
▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .

فصل چهار - مدل‌ها و Eloquent ORM بخش پنجم - پراپرتی های مدل 1- پراپرتی table نام جدول دیتابیس مرتبط با مدل را مشخص می‌کند. به‌صورت پیش‌فرض، لاراول نام مدل را با حروف کوچک و به صورت جمع تبدیل می‌کند.
protected $table = 'my_custom_table';
2- پراپرتی primaryKey برای مشخص کردن نام ستون کلید اصلی جدول استفاده می‌شود. به‌صورت پیش‌فرض، از ستون id به عنوان کلید اصلی استفاده می‌کند.
protected $primaryKey = 'user_id';
3- پراپرتی keyType نوع داده کلید اصلی را مشخص می‌کند. به‌صورت پیش‌فرض، لاراول از نوع int برای کلید اصلی استفاده می‌کند.
protected $keyType = 'string';
4- پراپرتی incrementing مشخص می‌کند که آیا کلید اصلی به صورت خودکار افزایش می‌یابد یا خیر. به‌صورت پیش‌فرض، این ویژگی true است و کلید اصلی افزایش می‌یابد.
public $incrementing = false;
5- پراپرتی timestamps مشخص می‌کند که آیا ستون‌های created_at و updated_at به‌صورت خودکار مدیریت شوند یا خیر. به‌صورت پیش‌فرض، این ویژگی true است.
public $timestamps = false;
6- پراپرتی dateFormat فرمت ذخیره‌سازی تاریخ‌ها در دیتابیس را مشخص می‌کند. به‌صورت پیش‌فرض، از فرمت Y-m-d H:i:s استفاده می‌کند.
protected $dateFormat = 'U';
7- پراپرتی connection مشخص می‌کند که مدل باید از کدام اتصال دیتابیس استفاده کند. به‌صورت پیش‌فرض، مدل‌ها از اتصال اصلی که در فایل config/database.php تعریف شده است استفاده می‌کنند.
protected $connection = 'mysql2';
8- پراپرتی fillable لیستی از ستون‌هایی را مشخص می‌کند که در هنگام انتساب جمعی (Mass Assignment) اجازه مقداردهی دارند. این ویژگی برای جلوگیری از حملات Mass Assignment بسیار مهم است.
protected $fillable = ['name', 'email', 'password'];
9- پراپرتی guarded برعکس fillable عمل می‌کند و ستون‌هایی که نباید به‌صورت جمعی مقداردهی شوند را مشخص می‌کند. اگر guarded را خالی بگذارید، به معنای آن است که همه ستون‌ها محافظت شده‌اند.
protected $guarded = ['is_admin'];
10- پراپرتی hidden مشخص می‌کند که کدام ستون‌ها در هنگام تبدیل مدل به آرایه یا JSON باید مخفی شوند و نمایش داده نشوند.
protected $hidden = ['password', 'remember_token'];
11- پراپرتی visible برعکس hidden عمل می‌کند و مشخص می‌کند که فقط ستون‌های مشخص‌شده در خروجی JSON یا آرایه نمایش داده شوند. سایر ستون‌ها مخفی خواهند بود.
protected $visible = ['name', 'email'];
12- پراپرتی dates مشخص می‌کند که کدام ستون‌ها به عنوان تاریخ در نظر گرفته شوند و به‌طور خودکار به Carbon تبدیل شوند. به‌صورت پیش‌فرض، ستون‌های created_at و updated_at به عنوان تاریخ مدیریت می‌شوند.
protected $dates = ['birthday'];
13- پراپرتی touches برای به‌روزرسانی زمان مدل‌های مرتبط استفاده می‌شود. اگر یک مدل دارای رابطه‌ای باشد که باید هنگام تغییر مدل فرزند، زمان به‌روزرسانی (updated_at) مدل والد نیز تغییر کند، می‌توانید از این ویژگی استفاده کنید.
protected $touches = ['post'];
14- پراپرتی perPage تعداد رکوردهایی که در هر صفحه برای صفحه‌بندی (pagination) نمایش داده می‌شوند را تنظیم می‌کند. به‌صورت پیش‌فرض، مقدار perPage برابر 15 است.
protected $perPage = 20;
15- پراپرتی morphClass برای روابط Polymorphic استفاده می‌شود و مشخص می‌کند که لاراول چه مقداری را در ستون *_type قرار دهد. به‌صورت پیش‌فرض، نام کامل کلاس مدل در ستون *_type ذخیره می‌شود.
protected $morphClass = 'post';
16- پراپرتی relationResolvers برای بازنویسی روابط در مدل‌ها استفاده می‌شود. اگر بخواهید نحوه فراخوانی یک رابطه را تغییر دهید یا به‌صورت دلخواه تعریف کنید، می‌توانید از relationResolvers استفاده کنید.
protected $relationResolvers = [
 'profile' => 'resolveProfile',
];

public function resolveProfile()
{
 return $this->hasOne(Profile::class);
}
17- پراپرتی foreignKeyType برای تعریف نوع داده کلیدهای خارجی استفاده می‌شود.
protected $foreignKeyType = 'string';
تعدادی از پراپرتی در پست های بعدی توضیح داده می شود. توجه داشته باشید که مدل ها، پراپرتی ها و متد های قابل Override زیادی دارند که در این دوره نام برده نمی شوند. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .

فصل چهار - مدل‌ها و Eloquent ORM بخش چهارم - اسکوپ ها اسکوپ‌ها (Scopes) در لاراول به شما اجازه می‌دهند که منطق جستجو یا کوئری‌های پیچیده‌ای را به صورت توابع قابل استفاده مجدد تعریف کنید. این اسکوپ‌ها به شما کمک می‌کنند که کوئری‌های مشابه را در سراسر برنامه به راحتی مدیریت کنید. اسکوپ‌ها به دو دسته اصلی تقسیم می‌شوند: 1- Local Scopes (اسکوپ‌های محلی) 2- Global Scopes (اسکوپ‌های سراسری) اسکوپ‌های محلی به شما اجازه می‌دهند که منطق فیلتر کردن را در یک تابع درون مدل تعریف کنید و سپس آن را در هر کوئری که به مدل مربوط می‌شود، به‌راحتی فراخوانی کنید. اسکوپ‌های محلی به عنوان متدهایی در مدل تعریف می‌شوند و با کلمه scope شروع می‌شوند. برای استفاده از آن‌ها نیازی به نوشتن scope در هنگام فراخوانی نیست. فرض کنید یک جدول کاربران داریم که دارای یک ستون active است. می‌خواهیم کاربران فعال را با استفاده از یک اسکوپ بازیابی کنیم.
class User extends Model
{
 public function scopeActive($query)
 {
  return $query->where('active', 1);
 }
}

// Usage:
$activeUsers = User::active()->get();
اسکوپ active فقط کاربران فعال (active = 1) را بازیابی می‌کند. همانطور که در مثال مشخص است متد اسکوپ با "scope" شروع می شود اما در هنگام استفاده از متد حذف می شود. پذیرفتن پارامترها در اسکوپ‌های محلی: اسکوپ‌های محلی می‌توانند پارامترهای ورودی داشته باشند تا بتوانند بر اساس نیازهای مختلف تنظیم شوند.
class User extends Model
{
 public function scopeOlderThan($query, $age)
 {
  return $query->where('age', '>', $age);
 }
}

// Usage:
$users = User::olderThan(25)->get();
——— اسکوپ‌های سراسری به شما اجازه می‌دهند که یک محدودیت یا فیلتر را برای تمام کوئری‌های یک مدل اعمال کنید. به محض این که یک مدل بارگذاری یا بازیابی می‌شود، اسکوپ سراسری به‌طور خودکار اعمال می‌شود، مگر اینکه به‌صراحت آن را غیرفعال کنید. برای تعریف یک اسکوپ سراسری، شما باید یک کلاس جدید که از Scope پیروی می‌کند ایجاد کنید. این کلاس شامل متد apply است که منطق اسکوپ در آن تعریف می‌شود. می توانید از کامند زیر استفاده کنید:
php artisan make:scope ActiveScope
فرض کنید شما می‌خواهید فقط کاربران فعال را به صورت پیش‌فرض نمایش دهید. ابتدا یک کلاس اسکوپ سراسری ایجاد می‌کنیم:
class ActiveScope implements Scope
{
 public function apply(Builder $builder, Model $model)
 {
  $builder->where('active', 1);
 }
}
سپس باید این اسکوپ سراسری را به مدل مورد نظر اضافه کنیم.
class User extends Model
{
 protected static function booted()
 {
  static::addGlobalScope(new ActiveScope);
 }
}
حالا هر بار که شما کوئری برای بازیابی کاربران اجرا کنید، این اسکوپ سراسری به‌طور خودکار اعمال می‌شود و فقط کاربران فعال را برمی‌گرداند. در برخی موارد ممکن است بخواهید اسکوپ سراسری را برای یک کوئری خاص غیرفعال کنید. برای این کار از متد withoutGlobalScope یا withoutGlobalScopes استفاده می‌کنید.
// Without ActiveScope
$users = User::withoutGlobalScope(ActiveScope::class)->get();

// Without any global scope
$users = User::withoutGlobalScopes()->get();
شما می‌توانید به صورت پویا اسکوپ‌های سراسری خود را با پارامترهای ورودی تنظیم کنید. برای این کار کافی است اسکوپ سراسری خود را با یک پارامتر سفارشی تعریف کنید.
class AgeScope implements Scope
{
 protected $age;

 public function __construct($age)
 {
  $this->age = $age;
 }

 public function apply(Builder $builder, Model $model)
 {
  $builder->where('age', '>', $this->age);
 }
}

// Usage:
class User extends Model
{
 protected static function booted()
 {
  static::addGlobalScope(new AgeScope(30));
 }
}
حالا هر بار که کوئری برای بازیابی کاربران اجرا شود، این اسکوپ اعمال می‌شود و فقط کاربران با سن بیشتر از 30 نمایش داده می‌شوند. به طور کلی اسکوپ های محلی برای تعریف فیلترها یا منطق‌های قابل استفاده مجدد به صورت اختیاری استفاده می‌شود، درصورتی که اسکوپ های سراسری برای اعمال خودکار فیلترها یا محدودیت‌ها روی تمام کوئری‌ها استفاده می‌شوند. هر دو نوع اسکوپ به شما کمک می‌کنند تا کدها را تمیزتر و قابل مدیریت‌تر کرده و کوئری‌ها را با قابلیت استفاده مجدد و انعطاف‌پذیرتر پیاده‌سازی کنید. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .

فصل چهار - مدل‌ها و Eloquent ORM بخش سوم - روابط - قسمت هفتم متد های روابط 1- متد with برای Eager Loading روابط استفاده می‌شود. با استفاده از این متد، می‌توانید قبل از اجرای کوئری و دریافت نتایج، تمام روابط مرتبط با مدل را نیز به‌طور پیش‌فرض بارگذاری کنید.
$posts = Post::with('comments')->get();
این کد همه پست‌ها را به همراه نظرات (comments) مرتبط با آن‌ها در یک کوئری بارگذاری می‌کند. (comments نام رابطه تعریف شده می باشد) 2- متد withCount تعداد رکوردهای مرتبط با هر رکورد از مدل اصلی را بدون بارگذاری کامل رابطه محاسبه می‌کند. این متد تعداد رکوردهای مرتبط را به عنوان یک ستون اضافی برمی‌گرداند. 3- متد withMax مقدار بیشینه یک فیلد از رکوردهای مرتبط را محاسبه می‌کند. 4- متد withAvg مقدار میانگین یک فیلد از رکوردهای مرتبط را محاسبه می‌کند. 5- متد withSum مقدار جمع یک فیلد از رکوردهای مرتبط را محاسبه می‌کند. 6- متد withExists بررسی می‌کند که آیا یک رابطه مرتبط وجود دارد یا خیر، و این نتیجه را به عنوان یک ستون exists برمی‌گرداند. 7- متد without برای غیرفعال کردن بارگذاری یک رابطه خاص که قبلاً در یک اسکوپ یا کوئری دیگر بارگذاری شده است استفاده می‌شود.
$posts = Post::without('comments')->get();
8- متد withOnly فقط روابط خاصی که مشخص شده‌اند را بارگذاری می‌کند، حتی اگر اسکوپ‌های دیگر در حال بارگذاری روابط دیگر باشند.
$posts = Post::withOnly('comments')->get();
9- متد withWhereHas برای بارگذاری روابط همراه با یک شرط خاص روی رکوردهای آن رابطه استفاده می‌شود.
$posts = Post::withWhereHas('comments', function ($query) {
 $query->where('likes', '>', 10);
})->get();
این کد پست‌هایی را بارگذاری می‌کند که نظرات آن‌ها بیش از 10 لایک دارند. 10- متد morphWithCount برای بارگذاری رابطه‌های چندشکلی به همراه شمارش رکوردهای مرتبط استفاده می‌شود.
$users = User::morphWithCount([Post::class => ['comments']])->get();
این کد رابطه‌های چندشکلی را با شمارش تعداد نظرات در پست‌ها برای هر کاربر بارگذاری می‌کند. 11- متد load برای Lazy Loading استفاده می‌شود. این متد پس از اجرای کوئری اصلی، روابط مرتبط را بارگذاری می‌کند.
$post = Post::find(1);
$post->load('comments');
12- متد loadMissing روابطی که قبلاً بارگذاری نشده‌اند را بارگذاری می‌کند. اگر یک رابطه قبلاً بارگذاری شده باشد، این متد دوباره آن را بارگذاری نمی‌کند. 13- متد loadCount برای بارگذاری تعداد رکوردهای مرتبط با مدل اصلی استفاده می‌شود، بدون اینکه رابطه به‌طور کامل بارگذاری شود. 14- متد loadMorph برای بارگذاری روابط چندشکلی (Polymorphic) استفاده می‌شود و به شما اجازه می‌دهد که رابطه‌های چندشکلی خاصی را بارگذاری کنید.
$comment = Comment::find(1);
$comment->loadMorph('commentable', [Post::class => ['comments'], Video::class => ['likes']]);
این کد بارگذاری چندشکلی را برای رابطه commentable انجام می‌دهد و روابط comments برای پست‌ها و likes برای ویدئوها بارگذاری می‌شود. 15- متد loadMorphCount تعداد رکوردهای مرتبط در رابطه‌های چندشکلی را بدون بارگذاری کامل آن‌ها محاسبه می‌کند.
$comment = Comment::find(1);
$comment->loadMorphCount('commentable', [Post::class => ['comments'], Video::class => ['likes']]);
این کد تعداد نظرات برای پست‌ها و تعداد لایک‌ها برای ویدئوها را برای هر نظر به صورت چندشکلی بارگذاری می‌کند. 16- متد loadSum برای محاسبه جمع یک ستون خاص در رابطه‌های مرتبط استفاده می‌شود.
$post = Post::find(1);
$post->loadSum('comments', 'likes');
17- متد has برای اعمال شرط بر اساس وجود یا عدم وجود رکوردهای مرتبط استفاده می‌شود. در واقع، این متد پست‌هایی را برمی‌گرداند که رابطه‌ی مشخصی دارند.
$posts = Post::has('comments')->get();
18- متد orHas به عنوان جایگزین OR در کوئری برای چک کردن وجود رکوردهای مرتبط استفاده می‌شود.
$posts = Post::has('comments')->orHas('likes')->get();
19- متد resolveRelationUsing برای بازنویسی نحوه‌ی استفاده از یک رابطه به صورت دلخواه در لاراول استفاده می‌شود. با استفاده از این متد، شما می‌توانید تعریف سفارشی از یک رابطه را در مدل خود پیاده‌سازی کنید.
User::resolveRelationUsing('profile', function ($model) {
 return $model->hasOne(Profile::class);
});
این کد نحوه بارگذاری رابطه profile را برای مدل User بازنویسی می‌کند. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .

فصل چهار - مدل‌ها و Eloquent ORM بخش سوم - روابط - قسمت ششم رابطه Polymorphic Relationships به شما اجازه می‌دهند که یک مدل به چندین مدل دیگر به‌صورت پویا و با استفاده از یک ساختار واحد مرتبط شود. به عبارت دیگر، در این نوع رابطه، یک مدل می‌تواند به چندین مدل مختلف مرتبط باشد و نیازی به تعریف جداول جداگانه برای هر نوع مدل مرتبط نیست. این نوع روابط به دو دسته اصلی تقسیم می‌شوند: 1- One-to-One/One-to-Many 2- Many-to-Many نوع One-to-One/One-to-Many: در این نوع رابطه، یک مدل می‌تواند به چندین مدل مختلف به صورت یک به یک یا یک به چند مرتبط شود. برای این کار از دو ستون morphable_id و morphable_type در جدول استفاده می‌شود که به ترتیب شناسه مدل و نوع مدل مرتبط را مشخص می‌کنند. فرض کنید شما می‌خواهید یک سیستم نظر‌دهی ایجاد کنید که کاربران بتوانند به پست‌ها و ویدئوها نظر دهند. به جای ایجاد دو جدول جداگانه برای نظرهای پست‌ها و نظرهای ویدئوها، می‌توانید از یک جدول مشترک comments استفاده کنید و از رابطه Polymorphic بهره ببرید. 1- ساختار جداول: جدول comments در کنار سایر فیلد ها، دو فیلد commentable_id و commentable_type را دارد. نکته: شیوه نام گذاری، اسم مفرد جدول با پسوند های able_id و able_type می باشد، مانند commentable_id و commentable_type. تعریف مدل ها: ابتدا با متد های مربوطه آشنا می شویم: 1- متد morphTo این متد برای ارتباط با یک مدل چندشکلی استفاده می‌شود. پارامتر ها: 1- نام رابطه. اگر این پارامتر مشخص نشود، لاراول به‌صورت خودکار نام رابطه را با توجه به فیلدهای *_id و *_type تشخیص می‌دهد. 2- نام ستون *_type که نوع مدل را نگه می‌دارد. به طور پیش‌فرض لاراول ستون *_type را با توجه به نام رابطه ایجاد می‌کند. 3- نام ستون *_id که شناسه مدل را نگه می‌دارد. به طور پیش‌فرض لاراول ستون *_id را با توجه به نام رابطه ایجاد می‌کند. 2- متد morphOne این متد برای تعریف رابطه یک به یک چندشکلی استفاده می‌شود. در این رابطه، یک مدل می‌تواند به یک رکورد از مدل‌های مختلف مرتبط باشد. پارامتر ها: 1- نام کلاس مدلی که رابطه با آن برقرار است. 2- نام رابطه چندشکلی که برای فیلدهای *_id و *_type در مدل فرزند استفاده می‌شود. 3- متد morphMany این متد مشابه morphOne اما برای تعریف رابطه یک به چند چندشکلی استفاده می‌شود. یعنی یک مدل می‌تواند با چندین رکورد از مدل‌های مختلف مرتبط باشد. 4- متد morphToMany این متد مشابه morphOne اما برای تعریف رابطه چند به چند چندشکلی استفاده می‌شود. یعنی یک مدل می‌تواند با چندین رکورد از مدل‌های مختلف از طریق یک جدول واسط مرتبط باشد. 5- متد morphedByMany این متد مشابه morphOne اما برای تعریف رابطه چند به چند چندشکلی از سمت مدل معکوس استفاده می‌شود. یعنی مدلی که در رابطه‌ی چند به چند چندشکلی، سمت دیگر رابطه است. ——— مدل Comment: در این مدل، از متد morphTo برای ارتباط با مدل‌های دینامیک (پست‌ها و ویدئوها) استفاده می‌شود.
public function commentable()
{
 return $this->morphTo();
}
مدل Post و Video از متد morphMany استفاده می‌شود تا مشخص شود که هر پست می‌تواند چندین نظر داشته باشد. (این متد در هر دو مدل تعریف می شود. بسته به نوع رابطه از متد morphOne نیز استفاده می شود.)
public function comments()
{
 return $this->morphMany(Comment::class, 'commentable');
}
شیوه استفاده مانند روابط قبلی می باشد. ——— نوع Many-to-Many: یک مدل می‌تواند به چندین مدل مختلف مرتبط شود و برعکس. برای پیاده‌سازی این رابطه، به سه جدول نیاز دارید: یکی برای مدل اصلی، یکی برای مدل‌های مرتبط و یک جدول واسط. فرض کنید یک سیستم tags دارید که برچسب‌ها می‌توانند به پست‌ها، ویدئوها و حتی به سایر مدل‌ها مرتبط باشند. ساختار جداول: جدول اصلی با نام tags یک فیلد id به صورت primary key دارد. جدول واسط با نام taggables دو فیلد taggable_id و taggable_type طبق قوانین نام گذاری و یک فیلد tag_id به صورت کلید خارجی برای جدول tags می باشد. تعریف مدل‌ها: مدل Tag: در این مدل، از متد morphedByMany برای تعریف ارتباط برچسب با مدل‌های مختلف (پست‌ها، ویدئوها) استفاده می‌شود.
public function posts()
{
 return $this->morphedByMany(Post::class, 'taggable');
}

public function videos()
{
 return $this->morphedByMany(Video::class, 'taggable');
}
مدل Post و Video: از متد morphToMany برای ارتباط با برچسب‌ها استفاده می‌شود.
public function tags()
{
 return $this->morphToMany(Tag::class, 'taggable');
}
شیوه استفاده نیز مانند روابط Many To Many است. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .

فصل چهار - مدل‌ها و Eloquent ORM بخش سوم - روابط - قسمت پنجم رابطه Has-Many-Through و Has-One-Through رابطه Has-Many-Through زمانی استفاده می‌شود که یک مدل بتواند از طریق یک مدل واسط (Intermediate Model) به چندین رکورد در یک مدل دیگر دسترسی پیدا کند. به عبارت دیگر، این رابطه به شما اجازه می‌دهد که یک مدل با یک مدل دورتر (که مستقیماً به آن مرتبط نیست) ارتباط داشته باشد و بتوانید از طریق یک مدل واسط، رکوردهای آن را بازیابی کنید. مثال: فرض کنید شما سه جدول دارید: 1- جدول کشورها. 2- جدول کاربران که هر کاربر متعلق به یک کشور است. 3- جدول پست‌ها که هر پست توسط یک کاربر نوشته شده است. اگر بخواهید همه پست‌هایی که در یک کشور خاص نوشته شده‌اند را پیدا کنید، این کار را از طریق رابطه Has-Many-Through انجام می‌دهید. 1- ساختار جداول: جدول countries اطلاعات کشورها را نگهداری می‌کند. این جدول دارای یک فیلد id به عنوان primary key است. جدول users اطلاعات کاربران را نگهداری می‌کند. این جدول دارای یک فیلد id به عنوان primary key و یک کلید خارجی (country_id) است که به جدول countries اشاره دارد. جدول posts اطلاعات پست‌های نوشته شده توسط کاربران را نگهداری می‌کند. این جدول دارای یک فیلد id به عنوان primary key و یک کلید خارجی (user_id) است که به جدول users اشاره دارد. 2- تعریف رابطه: ابتدا با دو متد جدید برای ایجاد روابط آشنا می شویم: 1- متد hasOneThrough زمانی استفاده می‌شود که یک رکورد از یک مدل از طریق یک مدل واسط، تنها به یک رکورد از مدل دیگری مرتبط باشد.
public function relatedModel()
{
 return $this->hasOneThrough(FinalModel::class, IntermediateModel::class);
}
پارامترها: 1- نام مدل نهایی که قصد دارید به آن دسترسی داشته باشید. 2- نام مدل واسط که بین مدل اصلی و مدل نهایی قرار دارد. 3- نام ستون کلید خارجی در مدل واسط که به مدل اصلی (جایی که رابطه را تعریف می‌کنید) اشاره می‌کند.(اختیاری) 4- نام ستون کلید خارجی در مدل نهایی که به مدل واسط اشاره می‌کند.(اختیاری) 5- نام ستون کلید محلی در مدل اصلی. به‌طور پیش‌فرض از id استفاده می‌شود.(اختیاری) 6- نام ستون کلید محلی در مدل واسط. به‌طور پیش‌فرض از id استفاده می‌شود.(اختیاری) 2- متد hasManyThrough برای دسترسی به چندین رکورد از یک مدل از طریق یک مدل واسط استفاده می‌شود. این متد معمولاً در مواقعی استفاده می‌شود که یک مدل بتواند از طریق یک مدل واسط به چندین رکورد در یک مدل دیگر دسترسی داشته باشد. سینتکس و پارامتر ها مشابه hasOneThrough می باشد. ——— در این مثال، کشورها (Country) از طریق کاربران (User) به پست‌ها (Post) مرتبط هستند. بنابراین، یک کشور می‌تواند از طریق کاربران خود به چندین پست دسترسی داشته باشد. مدل Country: این مدل از طریق کاربران به پست‌ها دسترسی پیدا می‌کند. رابطه Has-Many-Through در این مدل تعریف می‌شود.
public function posts()
{
 return $this->hasManyThrough(Post::class, User::class, 'country_id', 'user_id');
}
مدل User: رابطه‌ای مستقیم بین کاربران و پست‌ها وجود دارد. این مدل برای ارتباط میان کشورها و پست‌ها استفاده می‌شود.
public function country()
{
 return $this->belongsTo(Country::class);
}

public function posts()
{
 return $this->hasMany(Post::class);
}
مدل Post: هر پست متعلق به یک کاربر است.
public function user()
{
 return $this->belongsTo(User::class);
}
3- استفاده از رابطه: حال اگر بخواهید تمام پست‌های نوشته‌شده در یک کشور خاص (مثلاً "USA") را پیدا کنید:
$country = Country::find(1); // USA
$posts = $country->posts;
در این مثال، کشور "USA" از طریق کاربران خود به تمام پست‌هایی که کاربرانش نوشته‌اند، دسترسی پیدا می‌کند. ——— روابط Has-Many-Through و Has-One-Through در ساختار جداول و مدل ها کاملا یکسان هستند، جز تفاوت در استفاده از متد های hasManyThrough یا hasOneThrough بسته به نوع رابطه. تفاوت در عمل نیز به این صورت است که Has-One-Through برای زمانی استفاده می‌شود که می‌خواهیم از طریق یک مدل واسط به یک رکورد از مدل نهایی دسترسی پیدا کنیم، در صورتی که Has-Many-Through برای زمانی است که می‌خواهیم از طریق یک مدل واسط به چندین رکورد از مدل نهایی دسترسی داشته باشیم. به طور کلی انتظار داریم از Has-One-Through فقط یک رکورد دریافت کنیم، در حالی که از Has-Many-Through ممکن است چندین رکورد دریافت کنیم. ▫️ 🟠 🔎 #laravel #لاراول #فصل_۴ 💠 @AmirhDeveloper .