DDN ( Daily Dev Notes )
8 subscribers
4 photos
12 links
Download Telegram
🔌 میکروسرویس‌ها چجوری با هم حرف می‌زنن؟

تا اینجا فهمیدیم که توی معماری Microservices، سیستم از چند سرویس مستقل تشکیل میشه.
اما یه سؤال مهم وجود داره... 🤔
اگه هر سرویس مستقل باشه، پس این سرویس‌ها چجوری با هم ارتباط برقرار می‌کنن؟

فرض کنیم یه کاربر سفارشی ثبت می‌کنه:
Order Service سفارش رو ثبت می‌کنه
Payment Service پرداخت رو انجام میده
Notification Service پیامک ارسال می‌کنه

پس این سرویس‌ها باید یه راهی برای رد و بدل کردن اطلاعات داشته باشن.

به طور کلی دو مدل اصلی ارتباط داریم:
ارتباط مستقیم (Synchronous)
ارتباط غیرمستقیم (Asynchronous)


☎️ ارتباط مستقیم (Synchronous) :
توی این مدل، یه سرویس به سرویس دیگه درخواست می‌فرسته و منتظر جواب می‌مونه.
یه چیزی شبیه تماس تلفنی. 📞
تا طرف مقابل جواب نده، کار ادامه پیدا نمی‌کنه.
برای این مدل ارتباط روش ها و پروتکل های مختلفی وجود داره اما دو تا از اونا که بسیار زیاد استفاده میشن عبارتند از :
RESTAPI, gRPC

🌐 پروتکل REST API
محبوب‌ترین روش ارتباط بین سرویس‌ها همین REST هست.
فرض کنیم Order Service می‌خواد اطلاعات کاربر شماره 123 رو از User Service بگیره.
درخواستی شبیه این ارسال میشه:
GET /users/123

و پاسخ به صورت JSON برمی‌گرده:
{
"id": 123,
"name": "Ali",
"email": "ali@example.com"
}

در واقع REST معمولاً اطلاعات رو به شکل JSON روی HTTP منتقل می‌کنه.
شکل کلی انتقال داده در REST
REST

JSON

{
"id": 123,
"name": "Ali"
}

مزیتش اینه که ساده، خوانا و تقریباً روی همه زبان‌ها و فریمورک‌ها پشتیبانی میشه.
REST رو کی استفاده کنیم؟

ارتباط با فرانت‌اند
APIهای عمومی
پروژه‌هایی که سادگی مهم‌تر از سرعت خام هست

⚡️پروتکل gRPC
حالا فرض کنیم روزانه میلیون‌ها درخواست بین سرویس‌هامون جابجا میشه.
اینجا خیلی از شرکت‌ها به جای REST از gRPC استفاده می‌کنن.
برخلاف REST که JSON جابجا می‌کنه، gRPC از Protocol Buffers (Protobuf) استفاده می‌کنه.
اول ساختار داده رو تعریف می‌کنیم:
message User {
int32 id = 1;
string name = 2;
string email = 3;
}

شکل کلی انتقال داده در gRPC
gRPC

.proto

message User {
int32 id = 1;
string name = 2;
}

بعد هنگام ارسال، این اطلاعات به Binary تبدیل میشن:
0A 03 41 6C 69
12 0F 61 6C 69 ...

😅 طبیعتاً ما معمولاً این بایت‌ها رو مستقیم نمی‌بینیم.
اما به خاطر همین Binary بودن، حجم پیام‌ها کمتر و سرعت انتقال بیشتره.

کی از gRPC استفاده کنیم ؟
ارتباط داخلی بین سرویس‌ها
سیستم‌های پرترافیک
جاهایی که سرعت و Latency خیلی مهمه

(ادامه دارد )
—————-
@DDNotes
—————-
#Microservices #SoftwareArchitecture #SystemDesign #Backend #Laravel #DevOps
⚡️ یه نکته جالب درباره gRPC که کمتر بهش اشاره میشه
توی پست قبل گفتیم gRPC سریع‌تر از REST هست.
اما این سرعت فقط به خاطر Binary بودن Protobufها نیست. 👀
فرض کنیم یه سرویس بخواد این اطلاعات رو دریافت کنه:
اطلاعات کاربر
سبد خرید
سفارش‌ها
آدرس‌های کاربر
در REST معمولاً درخواست‌هایی شبیه این ارسال میشن:
GET /users/123
GET /carts/123
GET /orders/123
GET /addresses/123

یعنی چندین Request جداگانه بین سرویس‌ها رد و بدل میشه.
اما gRPC روی HTTP/2 ساخته شده و یه قابلیت مهم به اسم Multiplexing داره.
یعنی چندین درخواست و پاسخ می‌تونن همزمان روی یه Connection مشترک جابجا بشن.
به شکل ساده:
TCP Connection

├── GetUser()
├── GetCart()
├── GetOrders()
└── GetAddresses()

همه این درخواست‌ها می‌تونن روی همون Connection ارسال بشن. 🚀
البته یه تصور اشتباه رایج هم وجود داره:
REST = برای هر درخواست یک TCP Connection جدید
این جمله همیشه درست نیست.
REST هم می‌تونه Connection رو باز نگه داره و دوباره ازش استفاده کنه.
اما چیزی که gRPC رو متمایز می‌کنه، قابلیت ارسال همزمان چندین Stream روی یک Connection هست.
نتیجه؟
سربار کمتر
Latency کمتر
عملکرد بهتر در ارتباط بین میکروسرویس‌ها
به همین خاطر توی خیلی از سیستم‌های بزرگ، REST برای APIهای عمومی استفاده میشه و gRPC برای ارتباط داخلی بین سرویس‌ها. 😎
—————-
@DDNotes
—————-
#Microservices #gRPC #RESTAPI #HTTP2 #Backend #SystemDesign
DDN ( Daily Dev Notes )
🔌 میکروسرویس‌ها چجوری با هم حرف می‌زنن؟ تا اینجا فهمیدیم که توی معماری Microservices، سیستم از چند سرویس مستقل تشکیل میشه. اما یه سؤال مهم وجود داره... 🤔 اگه هر سرویس مستقل باشه، پس این سرویس‌ها چجوری با هم ارتباط برقرار می‌کنن؟ فرض کنیم یه کاربر سفارشی…
📬 ارتباط غیرمستقیم (Asynchronous)
حالا بریم سراغ مدل دوم.
فرض کنیم Order Service یه سفارش جدید ثبت کرده.
به جای اینکه مستقیم Notification Service رو صدا بزنه، یه پیام داخل یه صف قرار میده.
بعد Notification Service هر وقت آماده بود، اون پیام رو برمی‌داره و پردازش می‌کنه.
📦 درست مثل اینکه یه نامه بندازی داخل صندوق پست.
لازم نیست گیرنده همون لحظه حضور داشته باشه.

توی ادامه ی پست در مورد معروف ترین ابزار هایی که این مدل ارتباط رو برامون برقرار میکنن صحبت میکنیم
🐰 RabbitMQ و 📨 Apache Kafka
برای این مدل معمولاً از Message Brokerها استفاده می‌کنیم.
معروف‌ترین‌ها:
RabbitMQ
Apache Kafka
کارشون اینه که پیام‌ها رو بین سرویس‌ها جابجا کنن.
برای استفاده از این مسیج بروکر ها باید معماری Event-Driven داشته باشیم .

🎯 حالا معماری Event-Driven یعنی چی؟
قبل از هر جیز باید اشاره کنم که توی این مثال همه سرویس ها دارن به message broker گوش میدن و بهش متصلن.
فرض کنیم یه سفارش جدید ثبت شده.
Order Service یه Event منتشر می‌کنه:
{
"event": "OrderCreated",
"order_id": 987,
"user_id": 123,
"total_price": 250
}

شکل کلی انتقال داده در Event Driven
Kafka / RabbitMQ

Event

{
"event": "OrderCreated",
"order_id": 987
}

بعد هر سرویسی که به این رویداد علاقه‌مند باشه می‌تونه اون رو دریافت کنه:
Payment Service
Notification Service
Analytics Service
Loyalty Service
جالب اینجاست که Order Service حتی خبر نداره چه سرویس‌هایی دارن این Event رو مصرف می‌کنن. 😎

🔥 تفاوت اصلی رو با یه مثال ببینیم
فرض کنیم سفارشی ثبت شده و می‌خوایم پیامک ارسال کنیم.
در REST
POST /notifications/send

سرویس Order Service باید مستقیم با Notification Service صحبت کنه.
پس Notification Service باید همون لحظه آنلاین باشه.
در gRPC
rpc SendNotification(NotificationRequest)
returns (NotificationResponse);

باز هم Notification Service باید در دسترس باشه.
در Kafka یا RabbitMQ
{
"event": "OrderCreated",
"order_id": 987
}

سرویس Order Service فقط Event رو داخل Broker قرار میده و کارش تموم میشه.
هر زمان Notification Service آنلاین شد، پیام رو دریافت و پردازش می‌کنه
.
💥 چرا Event-Driven جلوی خرابی زنجیره‌ای رو می‌گیره؟
فرض کنیم Notification Service از کار افتاده.
در ارتباط مستقیم، ممکنه درخواست‌ها یکی یکی Fail بشن و کم‌کم مشکل به سرویس‌های دیگه هم منتقل بشه.
اما توی معماری Event-Driven، پیام‌ها داخل Kafka یا RabbitMQ ذخیره میشن و بعد از برگشتن سرویس پردازش میشن.
یعنی خرابی یه سرویس، لزوماً بقیه سیستم رو زمین نمی‌زنه. 🚀

🧠 پس کدوم بهتره؟
مثل اکثر سؤال‌های معماری نرم‌افزار، جواب اینه:
بستگی داره! 😄

معمولاً:
🔹 REST → برای APIهای عمومی
🔹 gRPC → برای ارتباط سریع بین سرویس‌ها
🔹 Kafka / RabbitMQ → برای Eventها و پردازش‌های غیرهمزمان
و نکته جالب اینه که اکثر سیستم‌های بزرگ از هر سه روش در کنار هم استفاده می‌کنن.
📚 منابع
🔹 برای درک عمیق‌تر Messaging، Eventها و سیستم‌های توزیع‌شده:
Designing Data-Intensive Applications - Martin Kleppmann
🔹 برای یادگیری Kafka:
Confluent Blog
—————-
@DDNotes
—————-
#Microservices #Kafka #RabbitMQ #gRPC #RESTAPI #SystemDesign #SoftwareArchitecture #Backend #DevOps
#Education_Prompt
🤖 اینکه Claude توکن کمتری مصرف کنه و دیرتر به محدودیت برسه...

1⃣وقتی با Claude (یا هر مدل زبانی دیگه‌ای) صحبت می‌کنی، صحبت‌ها تبدیل به یه سری قطعه‌ی کوچیک به اسم توکن میشن.
2⃣هر توکن تقریباً معادل ۳-۴ حرف انگلیسیه یا یه کلمه‌ی کوتاه.
وقتی فارسی صحبت می‌کنید معمولاً توکن بیشتری مصرف می‌کنه چون مدل برای فارسی به اندازه‌ی انگلیسی بهینه نیست.
3⃣مقدار استفاده‌ای که میشه از Claude داشت براساسِ توکن‌هایی که شما می‌فرستید (input)، هم توکن‌هایی که Claude جواب میده (output) هست.
🔢 همه‌ی چیزی که Claude توی یه مکالمه می‌بینه:
پیام‌های قبلی
جواب‌های قبلی Claude
فایل‌هایی که آپلود کردید
دستورالعمل‌های سیستم
نکته‌ی کلیدی: هر بار که پیام جدید می‌فرستید، Claude کل مکالمه رو از اول دوباره می‌خونه.
یعنی اگه ۲۰ پیام رد و بدل کردید، پیام ۲۱‌ ام توکنِ پردازش هر ۲۱ پیام رو داره، نه فقط آخری.
این یعنی مکالمه‌ی طولانی = توکن خیلی بیشتر برای هر پیام جدید.
چیا باعث میشه توکن زیاد مصرف بشه؟
۱. مکالمه‌ی طولانی بدون شروع تازه: هرچی چت طولانی‌تر بشه، هر پیام جدید توکن بیشتری مصرف می‌کنه.
۲. فایل‌های بزرگ آپلود کردن
۳. سوال‌های مبهم یا کلی : وقتی سوال نامشخص یا کلی می‌پرسید، Claude مجبوره طولانی جواب بده یا کلی فایل بخونه.
خواستن خروجی طولانی چیکار کنیم؟

۱. برای هر کار جدید، چت جدید باز کنید. مثلا نیاید توی همون چتی که داشتید گزارشکار می‌نوشتید، یهو از الکترومغناطیس سوال بپرسید.
چت جدید = context خالی = مصرف کم.
۲. سوال رو مشخص و با جزئیات بپرسید.
۳. فایل‌های غیرضروری آپلود نکنید.
۴. اگه چت خیلی طولانی شد، خلاصه‌اش رو کپی کنید و توی چت جدید بذارید.
۵. از مدل مناسب استفاده کنید.
🏷 مستر پرامپت | Mr Prompt
🔗Telgram | Bale
Forwarded from یک برنامه نویس تنبل (Arshia)
Laravel Migration Cheat Sheet
بهترین روش استفاده از enum و cast در Laravel

@TheRaymondDev
Forwarded from laravel-news
docker-compose.yml:


services:
laravel:
container_name: laravel
image: my-image-app
ports:
- "443:443"

mysql:
container_name: mysql
image: mysql:8.0
expose:
- 3306
volumes:
- mysql:/var/lib/mysql
Forwarded from Golden Code (Ali 🇨🇴)
بیشتر ما می‌نویسیم:
$user = User::where('email', $email)->firstOrFail();

اما اگه انتظار دارین دقیقاً یک رکورد وجود داشته باشه، "sole()" میتونه انتخب بهتری باشه:
$user = User::where('email', $email)->sole();

تفاوتشون؟

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

اما firstOrFail میره و اولین رکورد رو برامون میاره

"firstOrFail()"

- اگه رکوردی نباشد : خطا
- اگر چند رکورد باشن : اولین رکورد رو برمی‌گردونه

"sole()"

- اگه رکوردی نباشه :خطا
- اگر چند رکورد باشد : خطا

این تفاوت باعث میشه اگر داده‌های تکراری به اشتباه وارد دیتابیس بشن، خیلی زودتر متوجه مشکل بشیم.

#Laravel #Laravel_tip #لاراول

@GoldenCodeir 🔥
(به‌منبع و مثالش دقت کنید 👇🏾)
https://x.com/i/status/2062587421121028409
👩‍💻 چند نفر هنوز این اشتباه رو توی Validation لاراول انجام میدن؟ 👀

بیشتر مواقع برای بررسی وجود یک رکورد، این قانون رو می‌نویسیم:


Rule::exists('users', 'id')

اما یک مشکل وجود دارد...

اگر از Soft Delete استفاده می‌کنید، این Rule رکوردهای حذف‌شده را هم معتبر می‌داند. 😐

راه‌حل ساده است:


Rule::exists('users', 'id')->whereNull('deleted_at');


به این شکل فقط رکوردهای فعال اعتبارسنجی می‌شوند و دیگر شناسه کاربران Soft Deleted پذیرفته نخواهد شد.

این نکته کوچک می‌تواند از باگ‌های عجیبی جلوگیری کند؛ مخصوصاً در APIهایی که روی امنیت و صحت داده حساس هستند.
مدیریت
کنید؟

#Laravel #لاراول

📱 @MilwadKhosravi
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 یه نکته‌ی باحال توی لاراول که شاید خیلیا هنوز ازش استفاده نمی‌کنن!

اگه هنوز اینجوری می‌نویسی:
User::whereHas('posts', function ($query) {
$query->where('status', 'published');
})->with(['posts' => function ($query) {
$query->where('status', 'published');
}])->get();

😅 یه مشکل کوچیک داری...

همون شرط status = published رو دوبار نوشتی؛
یه بار برای whereHas() و یه بار هم برای with().

لاراول برای این قضیه یه متد تمیزتر داره:
User::withWhereHas('posts', function ($query) {
$query->where('status', 'published');
})->get();

🎯 با withWhereHas() هم رکوردهای اصلی فیلتر میشن، هم همون Relation با همون شرط Eager Load میشه.

### چرا بهتره؟ 🤔

کد کمتر
خوانایی بیشتر
حذف کدهای تکراری (DRY)
نگهداری و تغییرات راحت‌تر

💡 این قابلیت از اون ویژگی‌های کوچیک لاراوله که شاید زیاد به چشم نیاد، ولی وقتی توی پروژه‌های بزرگ ازش استفاده کنی، حسابی کدت تمیزتر و قابل نگهداری‌تر میشه.

🔥 شما قبلاً از withWhereHas() استفاده کردین یا هنوز همون ترکیب whereHas() + with() رو می‌نویسین؟

💬 نظرتون رو توی کامنت‌ها بنویسید.
‐------------
@DDNotes
-------------
#Laravel #PHP #Eloquent #LaravelTips #CleanCode #Backend #Programming
👍1
🚀 یه قابلیت کمتر شناخته‌شده‌ی لاراول که می‌تونه جون پروژه‌ رو نجات بده!

خیلی وقت‌ها تازه وقتی کاربران از کند بودن سایت شکایت می‌کنن، اون وقته که تازه می‌ریم دنبال پیدا کردن Queryهای کند! 😅

در حالی که لاراول خودش یه قابلیت داخلی داره که از همون اول، Queryهای کند رو بهت گزارش می‌ده.

کافیه اینو توی AppServiceProvider یا هر جای مناسب از پروژه‌ت قرار بدی:

DB::whenQueryingForLongerThan(500, function ($connection, $event) {
// Log or notify about slow queries
});

🎯 این متد هر Queryای که بیشتر از ۵۰۰ میلی‌ثانیه طول بکشه رو شناسایی می‌کنه تا قبل از اینکه به یه مشکل واقعی تبدیل بشه، ازش باخبر بشی.

## 🤔 چرا استفاده ازش ارزش داره؟

🔍 شناسایی Queryهای کند قبل از اینکه کاربر متوجه بشه.

پیدا کردن گلوگاه‌های عملکرد (Performance Bottlenecks) موقع توسعه، نه بعد از انتشار پروژه.

📈 بهینه‌سازی دیتابیس بر اساس داده‌های واقعی، نه حدس و گمان.

🛠️ کاهش زمان دیباگ و پیدا کردن مشکلات Performance.

---

💡 اگر این قابلیت رو با ابزارهایی مثل Laravel Pulse یا Laravel Telescope ترکیب کنی، دید خیلی بهتری نسبت به عملکرد دیتابیس و اپلیکیشن پیدا می‌کنی.

گاهی همین قابلیت‌های کوچیک لاراول می‌تونن ساعت‌ها زمان دیباگ و بهینه‌سازی رو برات ذخیره کنن.

🔥 شما تا حالا از DB::whenQueryingForLongerThan() استفاده کردین؟

یا برای پیدا کردن Queryهای کند از روش دیگه‌ای استفاده میکنین ؟
----------
@DDNotes
----------
#Laravel #PHP #Performance #Database #Eloquent #LaravelTips #Backend #WebDevelopment
Forwarded from Linuxor ?
من هیچ وقت نفهمیدم عربا چرا به لاراول می‌گن لارافیل؟ مگه "و" ندارن؟

شاید بخاطر اینه که پی اچ پی نمادش فیل هستش😂😂

@Linuxor
🚀 اگه هنوز از Pipeline توی لاراول استفاده نکردی، احتمالاً داری بخشی از قدرت این فریم‌ورک رو از دست میدی!

وقتی یه ورودی باید از چند مرحله پردازش عبور کنه، خیلی از ما یه عالمه if، foreach و شرط‌های تو در تو می‌نویسیم. 😅

اما لاراول یه راه خیلی تمیزتر و حرفه‌ای‌تر داره: Pipeline

فرض کن کاربر یه کامنت ارسال کرده و قبل از ذخیره شدن باید:

* ✂️ کلمات نامناسب حذف بشن.
* 🚫 اسپم تشخیص داده بشه.
* 🛡️ محتوای مخرب فیلتر بشه.
* 🔗 لینک‌های طولانی کوتاه بشن.

به‌جای اینکه همه‌ی این منطق رو داخل یه متد بزرگ بنویسی، هر مرحله رو داخل یه کلاس جدا قرار بده و با Pipeline به هم متصلشون کن.

use App\Pipelines\Comments\RemoveProfanity;
use App\Pipelines\Comments\RemoveSpam;
use App\Pipelines\Comments\RemoveHarmfulContent;
use App\Pipelines\Comments\ShortenUrls;
use Illuminate\Pipeline\Pipeline;

$comment = app(Pipeline::class)
->send($request->validated('comment'))
->through([
RemoveProfanity::class,
RemoveSpam::class,
RemoveHarmfulContent::class,
ShortenUrls::class,
])
->thenReturn();

---

## 🎯 چرا Pipeline این‌قدر کاربردیه؟

هر کلاس فقط یک مسئولیت داره (Single Responsibility)

🧪 تست کردن هر مرحله به‌صورت مستقل خیلی راحت‌تره.

🧩 اضافه یا حذف کردن مراحل پردازش فقط با اضافه یا حذف کردن یک Pipe انجام می‌شه.

📖 کدها خواناتر می‌شن و نگهداری پروژه ساده‌تر خواهد بود.

♻️ حتی می‌تونی همین Pipeها رو در بخش‌های مختلف پروژه دوباره استفاده کنی.

---

## 🧩 هر Pipe چطور به داده دسترسی پیدا می‌کنه؟

هر Pipe یک کلاس ساده با متد handle هست.

داده‌ای که با send() ارسال کردی، به‌عنوان اولین پارامتر وارد متد handle() می‌شه و بعد از پردازش، با $next() به Pipe بعدی ارسال می‌شه.

مثلاً Pipe حذف کلمات نامناسب:

namespace App\Pipelines\Comments;

use Closure;

class RemoveProfanity
{
public function handle(string $comment, Closure $next): string
{
$badWords = ['badword1', 'badword2'];

$comment = str_replace($badWords, '***', $comment);

return $next($comment);
}
}

و Pipe تشخیص اسپم:

namespace App\Pipelines\Comments;

use Closure;

class RemoveSpam
{
public function handle(string $comment, Closure $next): string
{
if (str_contains($comment, 'Buy now')) {
throw new \Exception('Spam detected.');
}

return $next($comment);
}
}

در نهایت هم Pipeline به همین شکل اجرا می‌شه:

$comment = app(Pipeline::class)
->send($request->validated('comment'))
->through([
RemoveProfanity::class,
RemoveSpam::class,
RemoveHarmfulContent::class,
ShortenUrls::class,
])
->thenReturn();

📌 ترتیب اجرای Pipeها دقیقاً به این صورته:

کامنت اولیه


RemoveProfanity


RemoveSpam


RemoveHarmfulContent


ShortenUrls


نتیجه نهایی

---

## 💡 فقط String نیست!

نکته‌ی جالب اینه که Pipeها محدود به string نیستن. تقریباً هر نوع داده‌ای رو می‌تونی داخل Pipeline ارسال کنی، مثل:

* 👤 یک Model (مثل User)
* 📦 یک DTO
* 🗂️ یک آرایه
* 📚 یک Collection
* 🛠️ حتی یک Query Builder

مثلاً با یک Model:

$user = app(Pipeline::class)
->send($user)
->through([
VerifyEmail::class,
CheckSubscription::class,
AssignPermissions::class,
])
->thenReturn();

هر Pipe دقیقاً همون شیء User رو دریافت می‌کنه، تغییرات موردنیاز رو روی اون اعمال می‌کنه و با:

return $next($user);

اون رو به مرحله‌ی بعد ارسال می‌کنه.

---

💡 هر جا داده‌ای قرار باشه از چند مرحله‌ی پردازش عبور کنه، Pipeline یکی از بهترین انتخاب‌هاست.

من معمولاً از Pipeline برای این سناریوها استفاده می‌کنم:

🔹 پردازش فرم‌ها
🔹 اعتبارسنجی‌های چندمرحله‌ای
🔹 پردازش فایل‌ها و تصاویر
🔹 فیلتر کردن محتوا
🔹 ساخت Queryهای داینامیک

---

🔥 شما تا حالا از Illuminate\Pipeline\Pipeline توی پروژه‌هاتون استفاده کردین؟

یا هنوز همه‌ی منطق رو داخل یک Service یا Controller می‌نویسین؟ 👇

───────────────
📢 @DDNotes
───────────────

#Laravel #PHP #Pipeline #CleanCode #DesignPatterns #Backend #LaravelTips #SoftwareArchitecture
Forwarded from Linuxor ?
اینی که می‌بینید اسمش Magika هست گوگل به تازگی منتشرش کرده؛ یه سیستم بر پایه هوش مصنوعیه که می‌تونه محتوای واقعی هر فایلی رو تشخیص بده، حتی اگه فایل خودش رو یه چیز دیگه جا زده باشه.
مثلاً بدافزاری که قیافه‌ی یه فایل PDF رو گرفته، یا اسکریپت‌های مخفی که خودشون رو شبیه عکس نشون میدن.

این ابزار رایگانه و متن‌باز هم هست :

securityresearch.google/magika

@Linuxor
🚀 یه نکته‌ی کوچیک در Validation لاراول که می‌تونه جلوی باگ‌های عجیبی رو بگیره!

خیلی وقت‌ها برای اعتبارسنجی از Rule معروف required استفاده می‌کنیم، اما یه رفتار مهم داره که خیلی‌ها ازش خبر ندارن.

قانون required روی آرایه‌ی خالی ([]) هم خطا می‌ده.

مثلاً این Validation:

$request->validate([
'items' => ['required', 'array'],
]);

این درخواست رو رد می‌کنه:

{
"items": []
}

چون لاراول آرایه‌ی خالی رو هم یک مقدار "خالی" (Empty) در نظر می‌گیره و Rule required شکست می‌خوره.

---

## 🤔 اگه آرایه‌ی خالی معتبر باشه چی؟

فرض کن داری API یک سبد خرید رو پیاده‌سازی می‌کنی.

کاربر ممکنه هنوز هیچ محصولی اضافه نکرده باشه، پس این درخواست کاملاً معتبره:

{
"items": []
}

اما همچنان می‌خوای مطمئن بشی که کلید items حتماً داخل درخواست وجود داره.

اینجاست که Rule **present** به کارت میاد.

$request->validate([
'items' => ['present', 'array'],
]);

حالا رفتار لاراول اینطوری می‌شه:

این درخواست معتبره:

{
"items": []
}

اما این درخواست رد می‌شه:

{}

چون فیلد items بوجود داشته باشهشه**، حتی اگر مقدارش خالی باشه.

---
🎯 تفاوت required و present

required
فیلد باید وجود داشته باشه.
مقدار خالی مجاز نیست.

present
فیلد باید وجود داشته باشه.
مقدار خالی هم مجازه.
---

## 💡 چه زمانی از present استفاده کنیم؟

این Rule مخصوصاً توی این سناریوها خیلی کاربردیه:

🔹 توسعه APIهای REST

🔹 درخواست‌های PUT و PATCH

🔹 اعتبارسنجی آرایه‌هایی که ممکنه خالی باشن.

🔹 زمانی که می‌خوای «ارسال نشده»ه»*«ارسال شده ولی خالیه»ه»** تفاوت قائل بشی.

---
پس این تفاوت رو همیشه یادت باشه:ه:**

* از **required** استفاده کن وقتی فیهم وجود داشته باشه و هم مقدار داشته باشهه باشه**.
* از **present** استفاده وجود داشتن فیلدداشتن فیلد** برات مهمه و مقدار خالی هم قابل قبوله.

همین تفاوت کوچیک می‌تونه رفتار Validation پروژه‌ات رو خیلی دقیق‌تر و قابل پیش‌بینی‌تر کنه.

---

🔥 شما تا حالا از Rule present توی پروژه‌هاتون استفاده کردین؟

یا همیشه برای این سناریوها سراغ required می‌رفتین؟ 👇

───────────────
@DDNotes
───────────────

#Laravel #PHP #Validation #LaravelTips #Backend #API #CleanCode #WebDevelopment