💡 یک مثال واقعی از کاربرد 9Router
فرض کنید من اشتراک دانشجویی Gemini Pro گوگل رو فعال کردم و به Antigravity دسترسی دارم. طبیعتاً میتونم از محیط کدنویسی Antigravity استفاده کنم، اما شخصاً تجربه کار با Claude Code رو بیشتر دوست دارم.
مشکل اینجاست که برای استفاده مستقیم از Claude Code باید یک اشتراک جداگانه تهیه کنم، در حالی که همین حالا بابت اشتراک Gemini هزینه پرداخت شده.
اینجاست که 9Router جذاب میشود:
🔹 میتونم اکانت Antigravity خودم رو به 9Router وصل کنم و مدلهای موجود داخلش رو بهصورت API در اختیار داشته باشم.
🔹 حتی میتونم Claude Code رو طوری تنظیم کنم که درخواستهاش از طریق 9Router به Antigravity ارسال بشه و از مدلها و سهمیه همون اشتراک استفاده کنه.
یعنی بهجای اینکه برای هر ابزار AI یک اشتراک جداگانه بخرم، میتونم ابزار موردعلاقهام (مثل Claude Code، Cursor یا Codex) رو روی اشتراکهایی که از قبل دارم سوار کنم و همه رو از یک نقطه مدیریت کنم.
در واقع 9Router فقط یک Router نیست؛ یک لایه هوشمند بین ابزارهای برنامهنویسی و سرویسهای هوش مصنوعی مختلفه که باعث میشه هزینه کمتر، انعطاف بیشتر و دردسر کمتری داشته باشی. 🚀
@DDNotes
فرض کنید من اشتراک دانشجویی Gemini Pro گوگل رو فعال کردم و به Antigravity دسترسی دارم. طبیعتاً میتونم از محیط کدنویسی Antigravity استفاده کنم، اما شخصاً تجربه کار با Claude Code رو بیشتر دوست دارم.
مشکل اینجاست که برای استفاده مستقیم از Claude Code باید یک اشتراک جداگانه تهیه کنم، در حالی که همین حالا بابت اشتراک Gemini هزینه پرداخت شده.
اینجاست که 9Router جذاب میشود:
🔹 میتونم اکانت Antigravity خودم رو به 9Router وصل کنم و مدلهای موجود داخلش رو بهصورت API در اختیار داشته باشم.
🔹 حتی میتونم Claude Code رو طوری تنظیم کنم که درخواستهاش از طریق 9Router به Antigravity ارسال بشه و از مدلها و سهمیه همون اشتراک استفاده کنه.
یعنی بهجای اینکه برای هر ابزار AI یک اشتراک جداگانه بخرم، میتونم ابزار موردعلاقهام (مثل Claude Code، Cursor یا Codex) رو روی اشتراکهایی که از قبل دارم سوار کنم و همه رو از یک نقطه مدیریت کنم.
در واقع 9Router فقط یک Router نیست؛ یک لایه هوشمند بین ابزارهای برنامهنویسی و سرویسهای هوش مصنوعی مختلفه که باعث میشه هزینه کمتر، انعطاف بیشتر و دردسر کمتری داشته باشی. 🚀
@DDNotes
یه پکیج فرم ساز خوب برای لاراول
معمولاً هر پروژهای که جلو میره، یه عالمه فرم جدید لازم پیدا میکنه؛ فرم تماس با ما، فرم ثبتنام، فرم نظرسنجی، فرم تیکت پشتیبانی، فرم درخواست همکاری و ...
حالا تصور کن به جای اینکه برای هر فرم بری migration، validation، blade و controller جدا بنویسی، یه پنل داشته باشی و همه اینا رو با Drag & Drop بسازی
پکیج Laravel Form Builder دقیقاً برای همین ساخته شده.
چند تا ویژگی خفن:
✅ ساخت فرم با Drag & Drop
✅ بیش از ۲۱ نوع فیلد مختلف
✅ شرطی کردن فیلدها (مثلاً اگه کاربر گزینه خاصی رو انتخاب کرد، فیلد جدید نمایش داده بشه)
✅ آپلود فایل و تصویر
✅ فیلدهای تکرارشونده (Repeater)
✅ خروجی CSV، Excel و PDF
✅ ارسال ایمیل بعد از ثبت فرم
✅ Webhook
✅ API آماده
✅ امکان نمایش فرم با
نکته جالبش اینه که فرمها داخل دیتابیس ذخیره میشن و برای اضافه یا تغییر فرمها لازم نیست هر بار کد پروژه رو دستکاری بشه.
برای پروژههای SaaS، CRM، پنل مشتریان، سیستمهای ثبت درخواست و حتی ساخت فرمساز اختصاصی خیلی کاربردیه.
🔗 GitHub:
https://github.com/haider-kamran/laravel-form-builder
#Laravel #PHP #OpenSource #FormBuilder #WebDevelopment
معمولاً هر پروژهای که جلو میره، یه عالمه فرم جدید لازم پیدا میکنه؛ فرم تماس با ما، فرم ثبتنام، فرم نظرسنجی، فرم تیکت پشتیبانی، فرم درخواست همکاری و ...
حالا تصور کن به جای اینکه برای هر فرم بری migration، validation، blade و controller جدا بنویسی، یه پنل داشته باشی و همه اینا رو با Drag & Drop بسازی
پکیج Laravel Form Builder دقیقاً برای همین ساخته شده.
چند تا ویژگی خفن:
✅ ساخت فرم با Drag & Drop
✅ بیش از ۲۱ نوع فیلد مختلف
✅ شرطی کردن فیلدها (مثلاً اگه کاربر گزینه خاصی رو انتخاب کرد، فیلد جدید نمایش داده بشه)
✅ آپلود فایل و تصویر
✅ فیلدهای تکرارشونده (Repeater)
✅ خروجی CSV، Excel و PDF
✅ ارسال ایمیل بعد از ثبت فرم
✅ Webhook
✅ API آماده
✅ امکان نمایش فرم با
form('slug')نکته جالبش اینه که فرمها داخل دیتابیس ذخیره میشن و برای اضافه یا تغییر فرمها لازم نیست هر بار کد پروژه رو دستکاری بشه.
برای پروژههای SaaS، CRM، پنل مشتریان، سیستمهای ثبت درخواست و حتی ساخت فرمساز اختصاصی خیلی کاربردیه.
🔗 GitHub:
https://github.com/haider-kamran/laravel-form-builder
#Laravel #PHP #OpenSource #FormBuilder #WebDevelopment
GitHub
GitHub - haider-kamran/laravel-form-builder
Contribute to haider-kamran/laravel-form-builder development by creating an account on GitHub.
🟢 راهاندازی Node.js و Socket.IO روی هاست اشتراکی (cPanel) بخش اول
اگه بخوایم Socket.IO رو روی هاست اشتراکی اجرا کنیم، معمولاً اولین چالش نصب پکیجها و بعد از اون تنظیم مسیرهای Socket.IO هست. توی این آموزش قدمبهقدم میبینیم چطور میشه یه اپ Express به همراه Socket.IO رو روی هاست اشتراکی راهاندازی کرد.
۱. ساخت اپلیکیشن Node.js
اول از داخل Application Manager یه اپ Node.js جدید میسازیم:
آدرس اپ: مثلاً
Startup File:
نسخه Node.js: متناسب با نیاز پروژه
بعد از ساخت اپ، پوشه پروژه ایجاد میشه و میتونیم فایلهای مورد نیازمون رو داخلش قرار بدیم.
۲. نصب Dependency ها
بعضی وقتها ممکنه نصب Dependency ها از داخل cPanel امکانپذیر نباشه؛ مثلاً زمانی که دسترسی به رجیستری پیشفرض npm وجود نداره یا اینترنت بینالملل با اختلال مواجه شده.
در این شرایط میتونیم داخل پوشه پروژه یک فایل
مثلاً برای استفاده از رجیستری چابکان:
بعد از ذخیره فایل، دوباره از داخل cPanel سعی میکنیم Dependency ها رو نصب کنیم.
اگر باز هم cPanel از رجیستری جدید استفاده نکرد، باید نصب رو به صورت دستی انجام بدیم.
اگر به Terminal یا SSH دسترسی داشته باشیم که کار خیلی ساده است:
اما روی بعضی هاستهای اشتراکی دسترسی SSH وجود نداره.
راهحلی که من استفاده کردم این بود که داخل
بعد از داخل cPanel و بخش Run JS Script اسکریپت
نمونه خروجی موفق:
وقتی خروجی مشابه این رو ببینیم یعنی Dependency ها با موفقیت نصب شدن و میتونیم سراغ مرحله بعدی یعنی راهاندازی Socket.IO بریم.
—————-
@DDNotes
—————-
#NodeJS #SocketIO #WebSocket #cPanel #SharedHosting #ExpressJS #JavaScript #Backend #Realtime #توسعه_وب
اگه بخوایم Socket.IO رو روی هاست اشتراکی اجرا کنیم، معمولاً اولین چالش نصب پکیجها و بعد از اون تنظیم مسیرهای Socket.IO هست. توی این آموزش قدمبهقدم میبینیم چطور میشه یه اپ Express به همراه Socket.IO رو روی هاست اشتراکی راهاندازی کرد.
۱. ساخت اپلیکیشن Node.js
اول از داخل Application Manager یه اپ Node.js جدید میسازیم:
آدرس اپ: مثلاً
testingStartup File:
app.jsنسخه Node.js: متناسب با نیاز پروژه
بعد از ساخت اپ، پوشه پروژه ایجاد میشه و میتونیم فایلهای مورد نیازمون رو داخلش قرار بدیم.
۲. نصب Dependency ها
بعضی وقتها ممکنه نصب Dependency ها از داخل cPanel امکانپذیر نباشه؛ مثلاً زمانی که دسترسی به رجیستری پیشفرض npm وجود نداره یا اینترنت بینالملل با اختلال مواجه شده.
در این شرایط میتونیم داخل پوشه پروژه یک فایل
.npmrc ایجاد کنیم و رجیستری مورد نظرمون رو به npm معرفی کنیم.مثلاً برای استفاده از رجیستری چابکان:
registry=https://mirror2.chabokan.net/npm/
بعد از ذخیره فایل، دوباره از داخل cPanel سعی میکنیم Dependency ها رو نصب کنیم.
اگر باز هم cPanel از رجیستری جدید استفاده نکرد، باید نصب رو به صورت دستی انجام بدیم.
اگر به Terminal یا SSH دسترسی داشته باشیم که کار خیلی ساده است:
npm install express socket.io
اما روی بعضی هاستهای اشتراکی دسترسی SSH وجود نداره.
راهحلی که من استفاده کردم این بود که داخل
package.json یک اسکریپت برای نصب Dependency ها تعریف کردم:{
"scripts": {
"npm-install": "npm install"
}
}بعد از داخل cPanel و بخش Run JS Script اسکریپت
npm-install رو اجرا کردم و npm تمام پکیجها رو نصب کرد.نمونه خروجی موفق:
returncode: 0
stdout:
> node-test@1.0.0 npm-install
> npm install
added 22 packages, and audited 91 packages in 5s
16 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
stderr:
وقتی خروجی مشابه این رو ببینیم یعنی Dependency ها با موفقیت نصب شدن و میتونیم سراغ مرحله بعدی یعنی راهاندازی Socket.IO بریم.
—————-
@DDNotes
—————-
#NodeJS #SocketIO #WebSocket #cPanel #SharedHosting #ExpressJS #JavaScript #Backend #Realtime #توسعه_وب
🟢 راهاندازی Node.js و Socket.IO روی هاست اشتراکی (cPanel) - بخش دوم
توی پست قبلی اپلیکیشن Node.js رو ساختیم و Dependency ها رو نصب کردیم. حالا اگه بخوایم Socket.IO رو روی هاست اشتراکی اجرا کنیم، باید بدونیم که معمولاً Node.js روی cPanel پشت Passenger اجرا میشه و با VPS تفاوتهایی داره.
۱. ساخت فایل app.js
اول یه فایل
اینجا Express و Socket.IO رو مقداردهی اولیه کردیم.
۲. تنظیم Socket.IO
حالا باید Socket.IO رو به سرور HTTP متصل کنیم:
نکته مهم اینه که مقدار
فرض کنید اپلیکیشن رو روی آدرس زیر ساخته باشیم:
در این حالت مسیر Socket.IO باید چیزی شبیه این باشه:
۳. ثبت Route تست
برای اینکه مطمئن بشیم Express درست کار میکنه، یه Route تست تعریف میکنیم:
بعد از Restart کردن اپلیکیشن، با باز کردن این آدرس باید پیام بالا نمایش داده بشه:
اگر این صفحه باز شد یعنی Node.js و Express بدون مشکل در حال اجرا هستند.
۴. مدیریت اتصال کاربران
حالا میتونیم اولین Event مربوط به Socket.IO رو تعریف کنیم:
هر بار که یک کاربر متصل بشه، این Event اجرا میشه و یک پیام تست برای کلاینت ارسال میکنه.
۵. نکته مهم Passenger
روی اکثر هاستهای اشتراکی نباید از:
استفاده کنیم.
Passenger خودش سرور رو مدیریت میکنه و معمولاً فقط کافیه در انتهای فایل بنویسیم:
بعد از ذخیره فایل، اپلیکیشن رو Restart کنید تا تغییرات اعمال بشن.
در پست بعدی اتصال کلاینت، تست WebSocket و رفع خطای معروف 404 مربوط به Socket.IO رو بررسی میکنیم.
—————-
@DDNotes
—————-
#NodeJS #SocketIO #Express #cPanel #SharedHosting #WebSocket #Backend #JavaScript #آموزش_برنامه_نویسی #توسعه_وب
توی پست قبلی اپلیکیشن Node.js رو ساختیم و Dependency ها رو نصب کردیم. حالا اگه بخوایم Socket.IO رو روی هاست اشتراکی اجرا کنیم، باید بدونیم که معمولاً Node.js روی cPanel پشت Passenger اجرا میشه و با VPS تفاوتهایی داره.
۱. ساخت فایل app.js
اول یه فایل
app.js داخل پوشه پروژه میسازیم:const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const app = express();
const server = http.createServer(app);اینجا Express و Socket.IO رو مقداردهی اولیه کردیم.
۲. تنظیم Socket.IO
حالا باید Socket.IO رو به سرور HTTP متصل کنیم:
const io = new Server(server, {
cors: {
origin: '*',
},
path: '/testing/socket.io',
});نکته مهم اینه که مقدار
path باید با آدرس اپلیکیشنی که داخل cPanel ساختیم هماهنگ باشه.فرض کنید اپلیکیشن رو روی آدرس زیر ساخته باشیم:
https://yourdomain.com/testing
در این حالت مسیر Socket.IO باید چیزی شبیه این باشه:
/testing/socket.io
۳. ثبت Route تست
برای اینکه مطمئن بشیم Express درست کار میکنه، یه Route تست تعریف میکنیم:
app.get('/testing/node-test', (req, res) => {
res.send('Node.js application is working');
});بعد از Restart کردن اپلیکیشن، با باز کردن این آدرس باید پیام بالا نمایش داده بشه:
https://yourdomain.com/testing/node-test
اگر این صفحه باز شد یعنی Node.js و Express بدون مشکل در حال اجرا هستند.
۴. مدیریت اتصال کاربران
حالا میتونیم اولین Event مربوط به Socket.IO رو تعریف کنیم:
io.on('connection', socket => {
console.log('New Client Connected');
socket.emit(
'server-message',
'Socket.IO connection successful'
);
});هر بار که یک کاربر متصل بشه، این Event اجرا میشه و یک پیام تست برای کلاینت ارسال میکنه.
۵. نکته مهم Passenger
روی اکثر هاستهای اشتراکی نباید از:
server.listen(...)
استفاده کنیم.
Passenger خودش سرور رو مدیریت میکنه و معمولاً فقط کافیه در انتهای فایل بنویسیم:
module.exports = server;
بعد از ذخیره فایل، اپلیکیشن رو Restart کنید تا تغییرات اعمال بشن.
در پست بعدی اتصال کلاینت، تست WebSocket و رفع خطای معروف 404 مربوط به Socket.IO رو بررسی میکنیم.
—————-
@DDNotes
—————-
#NodeJS #SocketIO #Express #cPanel #SharedHosting #WebSocket #Backend #JavaScript #آموزش_برنامه_نویسی #توسعه_وب
🟢 راهاندازی Node.js و Socket.IO روی هاست اشتراکی (cPanel) - بخش سوم
تا اینجا سرور Node.js و Socket.IO رو راهاندازی کردیم. حالا اگه بخوایم مطمئن بشیم WebSocket واقعاً کار میکنه، باید یه کلاینت تست بسازیم.
۱. اضافه کردن کلاینت Socket.IO
داخل صفحه HTML تست:
و بعد:
دقت کنید که مقدار
۲. دریافت پیام سرور
برای تست اتصال:
اگر همه چیز درست باشه باید داخل Console مرورگر پیام زیر رو ببینید:
۳. خطای معروف 404
یکی از رایجترین خطاهایی که روی هاست اشتراکی دیده میشه اینه:
این خطا معمولاً یکی از این دلایل رو داره:
مسیر
اپلیکیشن بعد از تغییرات Restart نشده.
درخواستها به جای
فایل Startup اشتباه انتخاب شده.
۴. بررسی لاگها
اگر اتصال برقرار نشد، لاگهای Node.js داخل cPanel بهترین محل برای پیدا کردن مشکل هستن.
معمولاً خطاهای زیر خیلی کمک میکنن:
یا:
یا:
۵. تست نهایی
اگر:
Route تست Express باز میشه
خطای 404 ندارید
پیام Socket.IO دریافت میشه
یعنی WebSocket با موفقیت روی هاست اشتراکی شما راهاندازی شده 🎉
از اینجا به بعد میتونید چت آنلاین، نوتیفیکیشن لحظهای، پنل ادمین Real-time و حتی سیستم Broadcast لاراول رو پیادهسازی کنید.
—————-
@DDNotes
—————-
#NodeJS #SocketIO #WebSocket #cPanel #SharedHosting #ExpressJS #JavaScript #Backend #Realtime #توسعه_وب
تا اینجا سرور Node.js و Socket.IO رو راهاندازی کردیم. حالا اگه بخوایم مطمئن بشیم WebSocket واقعاً کار میکنه، باید یه کلاینت تست بسازیم.
۱. اضافه کردن کلاینت Socket.IO
داخل صفحه HTML تست:
<script src="https://cdn.socket.io/4.8.1/socket.io.min.js"></script>
و بعد:
const socket = io({
path: '/testing/socket.io',
});دقت کنید که مقدار
path باید دقیقاً با مقداری که روی سرور تنظیم کردیم یکسان باشه.۲. دریافت پیام سرور
برای تست اتصال:
socket.on('server-message', message => {
console.log(message);
});اگر همه چیز درست باشه باید داخل Console مرورگر پیام زیر رو ببینید:
Socket.IO connection successful
۳. خطای معروف 404
یکی از رایجترین خطاهایی که روی هاست اشتراکی دیده میشه اینه:
GET /socket.io/?EIO=4&transport=polling 404
این خطا معمولاً یکی از این دلایل رو داره:
مسیر
path روی سرور و کلاینت یکسان نیست.اپلیکیشن بعد از تغییرات Restart نشده.
درخواستها به جای
/testing/socket.io به /socket.io ارسال میشن.فایل Startup اشتباه انتخاب شده.
۴. بررسی لاگها
اگر اتصال برقرار نشد، لاگهای Node.js داخل cPanel بهترین محل برای پیدا کردن مشکل هستن.
معمولاً خطاهای زیر خیلی کمک میکنن:
Cannot find module ...
یا:
EADDRINUSE
یا:
404 Not Found
۵. تست نهایی
اگر:
Route تست Express باز میشه
خطای 404 ندارید
پیام Socket.IO دریافت میشه
یعنی WebSocket با موفقیت روی هاست اشتراکی شما راهاندازی شده 🎉
از اینجا به بعد میتونید چت آنلاین، نوتیفیکیشن لحظهای، پنل ادمین Real-time و حتی سیستم Broadcast لاراول رو پیادهسازی کنید.
—————-
@DDNotes
—————-
#NodeJS #SocketIO #WebSocket #cPanel #SharedHosting #ExpressJS #JavaScript #Backend #Realtime #توسعه_وب
📄 فایل نهایی app.js
اگر همه مراحل پستهای قبلی رو انجام داده باشید، فایل نهایی میتونه چیزی شبیه نمونه زیر باشه:
بعد از ذخیره فایل:
اپلیکیشن رو Restart کنید.
آدرس زیر رو باز کنید:
اگر پیام:
نمایش داده شد یعنی هم Express و هم Socket.IO روی هاست اشتراکی شما با موفقیت در حال کار هستند.
💡 فراموش نکنید که مقدار
—————-
@DDNotes
—————-
#NodeJS #SocketIO #Express #cPanel #SharedHosting #WebSocket #JavaScript #Backend #Realtime #توسعه_وب
اگر همه مراحل پستهای قبلی رو انجام داده باشید، فایل نهایی میتونه چیزی شبیه نمونه زیر باشه:
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: '*',
},
path: '/testing/socket.io',
});
app.get('/testing/node-test', (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Socket.IO Test</title>
</head>
<body>
<h2>Socket.IO Connection Test</h2>
<div id="status">
Connecting...
</div>
<script src="https://cdn.socket.io/4.8.1/socket.io.min.js"></script>
<script>
const socket = io({
path: '/testing/socket.io'
});
socket.on('connect', () => {
document.getElementById('status').innerHTML =
'✅ Connected Successfully';
});
socket.on('server-message', message => {
console.log(message);
document.getElementById('status').innerHTML =
'✅ ' + message;
});
socket.on('disconnect', () => {
document.getElementById('status').innerHTML =
'❌ Disconnected';
});
</script>
</body>
</html>
`);
});
io.on('connection', socket => {
console.log('New Client Connected');
socket.emit(
'server-message',
'Socket.IO connection successful'
);
socket.on('disconnect', () => {
console.log('Client Disconnected');
});
});
module.exports = server;بعد از ذخیره فایل:
اپلیکیشن رو Restart کنید.
آدرس زیر رو باز کنید:
https://yourdomain.com/testing/node-test
اگر پیام:
✅ Socket.IO connection successful
نمایش داده شد یعنی هم Express و هم Socket.IO روی هاست اشتراکی شما با موفقیت در حال کار هستند.
💡 فراموش نکنید که مقدار
/testing باید با Application URL که داخل cPanel ساختهاید یکسان باشد. اگر مثلاً اپلیکیشن را روی /node-app ساخته باشید باید تمام مسیرها را متناسب با آن تغییر دهید.—————-
@DDNotes
—————-
#NodeJS #SocketIO #Express #cPanel #SharedHosting #WebSocket #JavaScript #Backend #Realtime #توسعه_وب
🚀 میکروسرویسها دقیقاً چی هستن و چرا همه دربارهشون حرف میزنن؟
این روزا هر جا صحبت از معماری نرمافزار میشه، یه نفر حتماً اسم Microservice رو میاره! 😅
از نتفلیکس و آمازون گرفته تا اوبر، همه یه جایی از این معماری استفاده میکنن.
ولی واقعاً Microservice چیه و چرا اینقدر محبوب شده؟ 🤔
فرض کنیم یه فروشگاه اینترنتی داریم. 👇
توی یه معماری سنتی یا همون Monolith، همه چیز داخل یه پروژه بزرگ قرار میگیره:
مدیریت کاربران
محصولات
سفارشها
پرداخت
ارسال پیامک و ایمیل
پنل مدیریت
یعنی همه این بخشها کنار هم توی یه کدبیس قرار دارن.
📦 Monolith = یه ساختمان بزرگ که همه اتاقهاش زیر یه سقف هستن
اما توی معماری Microservices داستان فرق میکنه.
هر بخش تبدیل میشه به یه سرویس مستقل:
User Service
Product Service
Order Service
Payment Service
Notification Service
هر سرویس کد، دیتابیس، توسعه و استقرار خودش رو داره.
🏘 Microservices = یه شهر کوچیک که از چندین ساختمان مستقل تشکیل شده
خب چرا شرکتهای بزرگ عاشق Microservice هستن؟
📈 مقیاسپذیری بهتر
فرض کنیم یه کمپین تبلیغاتی راه انداختیم و ناگهان تعداد سفارشها ۱۰ برابر شد.
توی Monolith معمولاً باید کل برنامه رو Scale کنیم.
ولی توی Microservices فقط همون Order Service رو Scale میکنیم.
یعنی منابع سرور خیلی بهینهتر مصرف میشن.
💥 خرابی یک بخش، کل سیستم رو نمیخوابونه
فرض کنیم سرویس ارسال ایمیل خراب بشه.
توی خیلی از معماریهای Monolith ممکنه این خرابی روی بخشهای دیگه هم اثر بذاره.
اما توی Microservices معمولاً فقط همون سرویس دچار مشکل میشه و بقیه سیستم به کارش ادامه میده.
😎 یعنی یه خرابی کوچیک لزوماً کل کسبوکار رو از کار نمیندازه.
👥 تیمها مستقلتر کار میکنن
حالا فرض کنیم یه شرکت ۵۰ تا برنامهنویس داره.
یه تیم روی پرداخت کار میکنه.
یه تیم روی سفارشها.
یه تیم روی کاربران.
هر تیم میتونه بدون درگیر شدن با بقیه، سرویس خودش رو توسعه بده و نسخه جدید منتشر کنه.
برای همین شرکتهای بزرگ خیلی راحتتر میتونن رشد کنن.
ولی یه نکته مهم... ⚠️
Microservice یه عصای جادویی نیست!
درسته که مزایای زیادی داره، اما دردسرهای خودش رو هم داره:
مدیریت چندین سرویس
ارتباط بین سرویسها
مانیتورینگ
لاگینگ
DevOps
مدیریت خطاها
به همین خاطر همیشه هم انتخاب درستی نیست.
توی پست بعدی میبینیم چه زمانی باید سراغ Microservice بریم و چه زمانی بهتره اصلاً سمتش نریم! 🔥
—————-
@DDNotes
—————-
#Microservices #SoftwareArchitecture #SystemDesign #Backend #Laravel #DevOps
این روزا هر جا صحبت از معماری نرمافزار میشه، یه نفر حتماً اسم Microservice رو میاره! 😅
از نتفلیکس و آمازون گرفته تا اوبر، همه یه جایی از این معماری استفاده میکنن.
ولی واقعاً Microservice چیه و چرا اینقدر محبوب شده؟ 🤔
فرض کنیم یه فروشگاه اینترنتی داریم. 👇
توی یه معماری سنتی یا همون Monolith، همه چیز داخل یه پروژه بزرگ قرار میگیره:
مدیریت کاربران
محصولات
سفارشها
پرداخت
ارسال پیامک و ایمیل
پنل مدیریت
یعنی همه این بخشها کنار هم توی یه کدبیس قرار دارن.
📦 Monolith = یه ساختمان بزرگ که همه اتاقهاش زیر یه سقف هستن
اما توی معماری Microservices داستان فرق میکنه.
هر بخش تبدیل میشه به یه سرویس مستقل:
User Service
Product Service
Order Service
Payment Service
Notification Service
هر سرویس کد، دیتابیس، توسعه و استقرار خودش رو داره.
🏘 Microservices = یه شهر کوچیک که از چندین ساختمان مستقل تشکیل شده
خب چرا شرکتهای بزرگ عاشق Microservice هستن؟
📈 مقیاسپذیری بهتر
فرض کنیم یه کمپین تبلیغاتی راه انداختیم و ناگهان تعداد سفارشها ۱۰ برابر شد.
توی Monolith معمولاً باید کل برنامه رو Scale کنیم.
ولی توی Microservices فقط همون Order Service رو Scale میکنیم.
یعنی منابع سرور خیلی بهینهتر مصرف میشن.
💥 خرابی یک بخش، کل سیستم رو نمیخوابونه
فرض کنیم سرویس ارسال ایمیل خراب بشه.
توی خیلی از معماریهای Monolith ممکنه این خرابی روی بخشهای دیگه هم اثر بذاره.
اما توی Microservices معمولاً فقط همون سرویس دچار مشکل میشه و بقیه سیستم به کارش ادامه میده.
😎 یعنی یه خرابی کوچیک لزوماً کل کسبوکار رو از کار نمیندازه.
👥 تیمها مستقلتر کار میکنن
حالا فرض کنیم یه شرکت ۵۰ تا برنامهنویس داره.
یه تیم روی پرداخت کار میکنه.
یه تیم روی سفارشها.
یه تیم روی کاربران.
هر تیم میتونه بدون درگیر شدن با بقیه، سرویس خودش رو توسعه بده و نسخه جدید منتشر کنه.
برای همین شرکتهای بزرگ خیلی راحتتر میتونن رشد کنن.
ولی یه نکته مهم... ⚠️
Microservice یه عصای جادویی نیست!
درسته که مزایای زیادی داره، اما دردسرهای خودش رو هم داره:
مدیریت چندین سرویس
ارتباط بین سرویسها
مانیتورینگ
لاگینگ
DevOps
مدیریت خطاها
به همین خاطر همیشه هم انتخاب درستی نیست.
توی پست بعدی میبینیم چه زمانی باید سراغ Microservice بریم و چه زمانی بهتره اصلاً سمتش نریم! 🔥
—————-
@DDNotes
—————-
#Microservices #SoftwareArchitecture #SystemDesign #Backend #Laravel #DevOps
⚠️ چه زمانی Microservice انتخاب خوبیه و چه زمانی فقط دردسر درست میکنه؟
یکی از رایجترین اشتباهات برنامهنویسها اینه که فکر میکنن:
اما واقعیت اینه که خیلی وقتها سادهترین راه، بهترین راهه. 😅
❌ پروژههایی که بهتره Microservice نباشن
📝 مثال اول: یه وبلاگ ساده
فرض کنیم میخوایم یه وبلاگ راه بندازیم.
امکاناتش هم ایناست:
مقاله
دستهبندی
کاربران
نظرات
حالا اگه برای این پروژه بیایم:
User Service
Article Service
Comment Service
Category Service
بسازیم، عملاً داریم بیدلیل پروژه رو پیچیده میکنیم.
چون حالا باید:
چند سرویس رو Deploy کنیم
لاگها رو مدیریت کنیم
ارتباط سرویسها رو کنترل کنیم
خطاهای شبکه رو هندل کنیم
در حالی که یه Monolith ساده میتونه همه این کارها رو خیلی راحت انجام بده.
🛒 مثال دوم: فروشگاه اینترنتی کوچک
فرض کنیم یه فروشگاه اینترنتی داریم که روزی ۵۰ تا سفارش ثبت میکنه.
توی همچین شرایطی معمولاً:
✅ توسعه سریعتره
✅ هزینه نگهداری کمتره
✅ دیباگ راحتتره
✅ تیم کوچیکتر هم از پسش برمیاد
پس استفاده از Microservice بیشتر شبیه Over Engineering میشه تا یه تصمیم فنی درست.
✅ نمونه پروژههایی که Microservice توشون میدرخشه
🚕 اوبر یا اسنپ خودمون
اوبر فقط یه اپ تاکسی نیست!
پشت صحنه دهها سیستم مختلف داره:
مدیریت رانندهها
مدیریت مسافرها
پرداخت
قیمتگذاری لحظهای
مسیریابی
اعلانها
هر کدوم از این بخشها بار و نیازهای متفاوتی دارن.
اینجاست که Microservices واقعاً ارزش خودش رو نشون میده.
🎬 نتفلیکس
نتفلیکس میلیونها کاربر همزمان داره.
جستجو، پخش ویدیو، پیشنهاد فیلم، مدیریت حساب کاربری و دهها بخش دیگه به صورت مستقل کار میکنن.
اگه تیم پیشنهاد فیلم بخواد یه قابلیت جدید منتشر کنه، لازم نیست کل سیستم دوباره Deploy بشه.
این دقیقاً همون جاییه که Microservices میدرخشه. ✨
یه قانون طلایی که همیشه یادت بمونه 👇
اگه:
✅ تازه پروژه رو شروع کردی
✅ تیم کوچیکی داری
✅ هنوز کاربرهای زیادی نداری
✅ محصولت MVP هست
به احتمال زیاد یه Monolith تمیز و اصولی بهترین انتخابه.
وقتی واقعاً به مشکل مقیاس، تیمهای متعدد و استقرار مستقل رسیدی، اون موقع میتونی به مهاجرت به Microservices فکر کنی.
معمولاً بزرگترین شرکتهای دنیا هم اول کار با Monolith شروع کردن و بعداً به سمت Microservices رفتن. 😉
📚 منابع برای مطالعه بیشتر
🔹 مقاله معروف مارتین فاولر:
Microservices - Martin Fowler
🔹 کتاب فوقالعاده برای شروع:
Building Microservices - Sam Newman
—————-
@DDNotes
—————-
#Microservices #SoftwareArchitecture #SystemDesign #Backend #Laravel #DevOps
یکی از رایجترین اشتباهات برنامهنویسها اینه که فکر میکنن:
«هرچی معماری پیچیدهتر باشه، حرفهایتره!»
اما واقعیت اینه که خیلی وقتها سادهترین راه، بهترین راهه. 😅
❌ پروژههایی که بهتره Microservice نباشن
📝 مثال اول: یه وبلاگ ساده
فرض کنیم میخوایم یه وبلاگ راه بندازیم.
امکاناتش هم ایناست:
مقاله
دستهبندی
کاربران
نظرات
حالا اگه برای این پروژه بیایم:
User Service
Article Service
Comment Service
Category Service
بسازیم، عملاً داریم بیدلیل پروژه رو پیچیده میکنیم.
چون حالا باید:
چند سرویس رو Deploy کنیم
لاگها رو مدیریت کنیم
ارتباط سرویسها رو کنترل کنیم
خطاهای شبکه رو هندل کنیم
در حالی که یه Monolith ساده میتونه همه این کارها رو خیلی راحت انجام بده.
🛒 مثال دوم: فروشگاه اینترنتی کوچک
فرض کنیم یه فروشگاه اینترنتی داریم که روزی ۵۰ تا سفارش ثبت میکنه.
توی همچین شرایطی معمولاً:
✅ توسعه سریعتره
✅ هزینه نگهداری کمتره
✅ دیباگ راحتتره
✅ تیم کوچیکتر هم از پسش برمیاد
پس استفاده از Microservice بیشتر شبیه Over Engineering میشه تا یه تصمیم فنی درست.
✅ نمونه پروژههایی که Microservice توشون میدرخشه
🚕 اوبر یا اسنپ خودمون
اوبر فقط یه اپ تاکسی نیست!
پشت صحنه دهها سیستم مختلف داره:
مدیریت رانندهها
مدیریت مسافرها
پرداخت
قیمتگذاری لحظهای
مسیریابی
اعلانها
هر کدوم از این بخشها بار و نیازهای متفاوتی دارن.
اینجاست که Microservices واقعاً ارزش خودش رو نشون میده.
🎬 نتفلیکس
نتفلیکس میلیونها کاربر همزمان داره.
جستجو، پخش ویدیو، پیشنهاد فیلم، مدیریت حساب کاربری و دهها بخش دیگه به صورت مستقل کار میکنن.
اگه تیم پیشنهاد فیلم بخواد یه قابلیت جدید منتشر کنه، لازم نیست کل سیستم دوباره Deploy بشه.
این دقیقاً همون جاییه که Microservices میدرخشه. ✨
یه قانون طلایی که همیشه یادت بمونه 👇
اگه:
✅ تازه پروژه رو شروع کردی
✅ تیم کوچیکی داری
✅ هنوز کاربرهای زیادی نداری
✅ محصولت MVP هست
به احتمال زیاد یه Monolith تمیز و اصولی بهترین انتخابه.
وقتی واقعاً به مشکل مقیاس، تیمهای متعدد و استقرار مستقل رسیدی، اون موقع میتونی به مهاجرت به Microservices فکر کنی.
معمولاً بزرگترین شرکتهای دنیا هم اول کار با Monolith شروع کردن و بعداً به سمت Microservices رفتن. 😉
📚 منابع برای مطالعه بیشتر
🔹 مقاله معروف مارتین فاولر:
Microservices - Martin Fowler
🔹 کتاب فوقالعاده برای شروع:
Building Microservices - Sam Newman
—————-
@DDNotes
—————-
#Microservices #SoftwareArchitecture #SystemDesign #Backend #Laravel #DevOps
martinfowler.com
Microservices
Defining the microservices architectural style by describing their nine common characteristics
👍1
🔌 میکروسرویسها چجوری با هم حرف میزنن؟
تا اینجا فهمیدیم که توی معماری Microservices، سیستم از چند سرویس مستقل تشکیل میشه.
اما یه سؤال مهم وجود داره... 🤔
اگه هر سرویس مستقل باشه، پس این سرویسها چجوری با هم ارتباط برقرار میکنن؟
فرض کنیم یه کاربر سفارشی ثبت میکنه:
Order Service سفارش رو ثبت میکنه
Payment Service پرداخت رو انجام میده
Notification Service پیامک ارسال میکنه
پس این سرویسها باید یه راهی برای رد و بدل کردن اطلاعات داشته باشن.
به طور کلی دو مدل اصلی ارتباط داریم:
✅ ارتباط مستقیم (Synchronous)
✅ ارتباط غیرمستقیم (Asynchronous)
☎️ ارتباط مستقیم (Synchronous) :
توی این مدل، یه سرویس به سرویس دیگه درخواست میفرسته و منتظر جواب میمونه.
یه چیزی شبیه تماس تلفنی. 📞
تا طرف مقابل جواب نده، کار ادامه پیدا نمیکنه.
برای این مدل ارتباط روش ها و پروتکل های مختلفی وجود داره اما دو تا از اونا که بسیار زیاد استفاده میشن عبارتند از :
RESTAPI, gRPC
🌐 پروتکل REST API
محبوبترین روش ارتباط بین سرویسها همین REST هست.
فرض کنیم Order Service میخواد اطلاعات کاربر شماره 123 رو از User Service بگیره.
درخواستی شبیه این ارسال میشه:
و پاسخ به صورت JSON برمیگرده:
در واقع REST معمولاً اطلاعات رو به شکل JSON روی HTTP منتقل میکنه.
شکل کلی انتقال داده در REST
مزیتش اینه که ساده، خوانا و تقریباً روی همه زبانها و فریمورکها پشتیبانی میشه.
REST رو کی استفاده کنیم؟
✅ ارتباط با فرانتاند
✅ APIهای عمومی
✅ پروژههایی که سادگی مهمتر از سرعت خام هست
⚡️پروتکل gRPC
حالا فرض کنیم روزانه میلیونها درخواست بین سرویسهامون جابجا میشه.
اینجا خیلی از شرکتها به جای REST از gRPC استفاده میکنن.
برخلاف REST که JSON جابجا میکنه، gRPC از Protocol Buffers (Protobuf) استفاده میکنه.
اول ساختار داده رو تعریف میکنیم:
شکل کلی انتقال داده در gRPC
بعد هنگام ارسال، این اطلاعات به Binary تبدیل میشن:
😅 طبیعتاً ما معمولاً این بایتها رو مستقیم نمیبینیم.
اما به خاطر همین Binary بودن، حجم پیامها کمتر و سرعت انتقال بیشتره.
کی از gRPC استفاده کنیم ؟
✅ ارتباط داخلی بین سرویسها
✅ سیستمهای پرترافیک
✅ جاهایی که سرعت و Latency خیلی مهمه
(ادامه دارد )
—————-
@DDNotes
—————-
#Microservices #SoftwareArchitecture #SystemDesign #Backend #Laravel #DevOps
تا اینجا فهمیدیم که توی معماری 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 معمولاً درخواستهایی شبیه این ارسال میشن:
یعنی چندین Request جداگانه بین سرویسها رد و بدل میشه.
اما gRPC روی HTTP/2 ساخته شده و یه قابلیت مهم به اسم Multiplexing داره.
یعنی چندین درخواست و پاسخ میتونن همزمان روی یه Connection مشترک جابجا بشن.
به شکل ساده:
همه این درخواستها میتونن روی همون Connection ارسال بشن. 🚀
البته یه تصور اشتباه رایج هم وجود داره:
❌ REST = برای هر درخواست یک TCP Connection جدید
این جمله همیشه درست نیست.
REST هم میتونه Connection رو باز نگه داره و دوباره ازش استفاده کنه.
اما چیزی که gRPC رو متمایز میکنه، قابلیت ارسال همزمان چندین Stream روی یک Connection هست.
نتیجه؟
✅ سربار کمتر
✅ Latency کمتر
✅ عملکرد بهتر در ارتباط بین میکروسرویسها
به همین خاطر توی خیلی از سیستمهای بزرگ، REST برای APIهای عمومی استفاده میشه و gRPC برای ارتباط داخلی بین سرویسها. 😎
—————-
@DDNotes
—————-
#Microservices #gRPC #RESTAPI #HTTP2 #Backend #SystemDesign
توی پست قبل گفتیم 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 Driven
بعد هر سرویسی که به این رویداد علاقهمند باشه میتونه اون رو دریافت کنه:
Payment Service
Notification Service
Analytics Service
Loyalty Service
جالب اینجاست که Order Service حتی خبر نداره چه سرویسهایی دارن این Event رو مصرف میکنن. 😎
🔥 تفاوت اصلی رو با یه مثال ببینیم
فرض کنیم سفارشی ثبت شده و میخوایم پیامک ارسال کنیم.
در REST
سرویس Order Service باید مستقیم با Notification Service صحبت کنه.
پس Notification Service باید همون لحظه آنلاین باشه.
در gRPC
باز هم Notification Service باید در دسترس باشه.
در Kafka یا RabbitMQ
سرویس 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
حالا بریم سراغ مدل دوم.
فرض کنیم 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
Forwarded from مستر پرامپت | Mr Prompt
#Education_Prompt
🤖 اینکه Claude توکن کمتری مصرف کنه و دیرتر به محدودیت برسه...
🔗 Telgram | Bale
🤖 اینکه Claude توکن کمتری مصرف کنه و دیرتر به محدودیت برسه...
1⃣وقتی با Claude (یا هر مدل زبانی دیگهای) صحبت میکنی، صحبتها تبدیل به یه سری قطعهی کوچیک به اسم توکن میشن.
2⃣هر توکن تقریباً معادل ۳-۴ حرف انگلیسیه یا یه کلمهی کوتاه.
وقتی فارسی صحبت میکنید معمولاً توکن بیشتری مصرف میکنه چون مدل برای فارسی به اندازهی انگلیسی بهینه نیست.
3⃣مقدار استفادهای که میشه از Claude داشت براساسِ توکنهایی که شما میفرستید (input)، هم توکنهایی که Claude جواب میده (output) هست.
🔢 همهی چیزی که Claude توی یه مکالمه میبینه:
پیامهای قبلی
جوابهای قبلی Claude
فایلهایی که آپلود کردید
دستورالعملهای سیستم
نکتهی کلیدی: هر بار که پیام جدید میفرستید، Claude کل مکالمه رو از اول دوباره میخونه.
یعنی اگه ۲۰ پیام رد و بدل کردید، پیام ۲۱ ام توکنِ پردازش هر ۲۱ پیام رو داره، نه فقط آخری.
این یعنی مکالمهی طولانی = توکن خیلی بیشتر برای هر پیام جدید.
❓ چیا باعث میشه توکن زیاد مصرف بشه؟
۱. مکالمهی طولانی بدون شروع تازه: هرچی چت طولانیتر بشه، هر پیام جدید توکن بیشتری مصرف میکنه.
۲. فایلهای بزرگ آپلود کردن
۳. سوالهای مبهم یا کلی : وقتی سوال نامشخص یا کلی میپرسید، Claude مجبوره طولانی جواب بده یا کلی فایل بخونه.
❓خواستن خروجی طولانی چیکار کنیم؟🏷 مستر پرامپت | Mr Prompt
۱. برای هر کار جدید، چت جدید باز کنید. مثلا نیاید توی همون چتی که داشتید گزارشکار مینوشتید، یهو از الکترومغناطیس سوال بپرسید.
چت جدید = context خالی = مصرف کم.
۲. سوال رو مشخص و با جزئیات بپرسید.
۳. فایلهای غیرضروری آپلود نکنید.
۴. اگه چت خیلی طولانی شد، خلاصهاش رو کپی کنید و توی چت جدید بذارید.
۵. از مدل مناسب استفاده کنید.
🔗 Telgram | Bale
Forwarded from یک برنامه نویس تنبل (Arshia)
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 laravel-news
کدام گزینه دربارهی expose: 3306 صحیح است؟
Anonymous Quiz
8%
حذف expose باعث میشود کانتینر laravel دیگر نتواند به mysql متصل شود.
14%
وجود expose برای دسترسی از سیستم میزبان (Host) به MySQL الزامی است.
55%
اگر هر دو سرویس در یک Docker Network باشند، حذف expose تأثیری بر ارتباط laravel و mysql ندارد.
23%
expose همان عملکرد ports را دارد و پورت 3306 را روی سیستم میزبان منتشر میکند.
Forwarded from Golden Code (Ali 🇨🇴)
بیشتر ما مینویسیم:
اما اگه انتظار دارین دقیقاً یک رکورد وجود داشته باشه، "sole()" میتونه انتخب بهتری باشه:
تفاوتشون؟
شرایطی رو تصور کنید که به اشتباه دو رکورد با ایمیل یکسان داریم.
اگه از sole استفاده کنیم بهمون خطا میده چون انتظار داره فقط یک رکورد برگرده،
اما firstOrFail میره و اولین رکورد رو برامون میاره
✅ "firstOrFail()"
- اگه رکوردی نباشد : خطا
- اگر چند رکورد باشن : اولین رکورد رو برمیگردونه
✅ "sole()"
- اگه رکوردی نباشه :خطا
- اگر چند رکورد باشد : خطا
این تفاوت باعث میشه اگر دادههای تکراری به اشتباه وارد دیتابیس بشن، خیلی زودتر متوجه مشکل بشیم.
#Laravel #Laravel_tip #لاراول
@GoldenCodeir 🔥
(بهمنبع و مثالش دقت کنید 👇🏾)
https://x.com/i/status/2062587421121028409
$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
X (formerly Twitter)
Punyapal Shah (@MrPunyapal) on X
Laravel tip:
If your query should return exactly one record, `sole()` expresses that intent better than `firstOrFail()`.
It will fail if zero records exist and also if multiple records exist.
Small difference. Big guarantee. 👇
If your query should return exactly one record, `sole()` expresses that intent better than `firstOrFail()`.
It will fail if zero records exist and also if multiple records exist.
Small difference. Big guarantee. 👇
Forwarded from Milwad Khosravi | میلاد خسروی
بیشتر مواقع برای بررسی وجود یک رکورد، این قانون رو مینویسیم:
Rule::exists('users', 'id')
اما یک مشکل وجود دارد...
اگر از Soft Delete استفاده میکنید، این Rule رکوردهای حذفشده را هم معتبر میداند. 😐
راهحل ساده است:
Rule::exists('users', 'id')->whereNull('deleted_at');
به این شکل فقط رکوردهای فعال اعتبارسنجی میشوند و دیگر شناسه کاربران Soft Deleted پذیرفته نخواهد شد.
این نکته کوچک میتواند از باگهای عجیبی جلوگیری کند؛ مخصوصاً در APIهایی که روی امنیت و صحت داده حساس هستند.کنید؟
مدیریت
#Laravel #لاراول
Please open Telegram to view this post
VIEW IN TELEGRAM
🚀 یه نکتهی باحال توی لاراول که شاید خیلیا هنوز ازش استفاده نمیکنن!
اگه هنوز اینجوری مینویسی:
😅 یه مشکل کوچیک داری...
همون شرط status = published رو دوبار نوشتی؛
یه بار برای whereHas() و یه بار هم برای with().
لاراول برای این قضیه یه متد تمیزتر داره:
🎯 با withWhereHas() هم رکوردهای اصلی فیلتر میشن، هم همون Relation با همون شرط Eager Load میشه.
### چرا بهتره؟ 🤔
✅ کد کمتر
✅ خوانایی بیشتر
✅ حذف کدهای تکراری (DRY)
✅ نگهداری و تغییرات راحتتر
💡 این قابلیت از اون ویژگیهای کوچیک لاراوله که شاید زیاد به چشم نیاد، ولی وقتی توی پروژههای بزرگ ازش استفاده کنی، حسابی کدت تمیزتر و قابل نگهداریتر میشه.
🔥 شما قبلاً از withWhereHas() استفاده کردین یا هنوز همون ترکیب whereHas() + with() رو مینویسین؟
💬 نظرتون رو توی کامنتها بنویسید.
‐------------
@DDNotes
-------------
#Laravel #PHP #Eloquent #LaravelTips #CleanCode #Backend #Programming
اگه هنوز اینجوری مینویسی:
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های کند رو بهت گزارش میده.
کافیه اینو توی
🎯 این متد هر Queryای که بیشتر از ۵۰۰ میلیثانیه طول بکشه رو شناسایی میکنه تا قبل از اینکه به یه مشکل واقعی تبدیل بشه، ازش باخبر بشی.
## 🤔 چرا استفاده ازش ارزش داره؟
🔍 شناسایی Queryهای کند قبل از اینکه کاربر متوجه بشه.
⚡ پیدا کردن گلوگاههای عملکرد (Performance Bottlenecks) موقع توسعه، نه بعد از انتشار پروژه.
📈 بهینهسازی دیتابیس بر اساس دادههای واقعی، نه حدس و گمان.
🛠️ کاهش زمان دیباگ و پیدا کردن مشکلات Performance.
---
💡 اگر این قابلیت رو با ابزارهایی مثل Laravel Pulse یا Laravel Telescope ترکیب کنی، دید خیلی بهتری نسبت به عملکرد دیتابیس و اپلیکیشن پیدا میکنی.
گاهی همین قابلیتهای کوچیک لاراول میتونن ساعتها زمان دیباگ و بهینهسازی رو برات ذخیره کنن.
🔥 شما تا حالا از
یا برای پیدا کردن Queryهای کند از روش دیگهای استفاده میکنین ؟
----------
@DDNotes
----------
#Laravel #PHP #Performance #Database #Eloquent #LaravelTips #Backend #WebDevelopment
خیلی وقتها تازه وقتی کاربران از کند بودن سایت شکایت میکنن، اون وقته که تازه میریم دنبال پیدا کردن 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
🚀 اگه هنوز از Pipeline توی لاراول استفاده نکردی، احتمالاً داری بخشی از قدرت این فریمورک رو از دست میدی!
وقتی یه ورودی باید از چند مرحله پردازش عبور کنه، خیلی از ما یه عالمه
اما لاراول یه راه خیلی تمیزتر و حرفهایتر داره: Pipeline
فرض کن کاربر یه کامنت ارسال کرده و قبل از ذخیره شدن باید:
* ✂️ کلمات نامناسب حذف بشن.
* 🚫 اسپم تشخیص داده بشه.
* 🛡️ محتوای مخرب فیلتر بشه.
* 🔗 لینکهای طولانی کوتاه بشن.
بهجای اینکه همهی این منطق رو داخل یه متد بزرگ بنویسی، هر مرحله رو داخل یه کلاس جدا قرار بده و با
---
## 🎯 چرا Pipeline اینقدر کاربردیه؟
✅ هر کلاس فقط یک مسئولیت داره (Single Responsibility)
🧪 تست کردن هر مرحله بهصورت مستقل خیلی راحتتره.
🧩 اضافه یا حذف کردن مراحل پردازش فقط با اضافه یا حذف کردن یک Pipe انجام میشه.
📖 کدها خواناتر میشن و نگهداری پروژه سادهتر خواهد بود.
♻️ حتی میتونی همین Pipeها رو در بخشهای مختلف پروژه دوباره استفاده کنی.
---
## 🧩 هر Pipe چطور به داده دسترسی پیدا میکنه؟
هر Pipe یک کلاس ساده با متد
دادهای که با
مثلاً Pipe حذف کلمات نامناسب:
و Pipe تشخیص اسپم:
در نهایت هم Pipeline به همین شکل اجرا میشه:
📌 ترتیب اجرای Pipeها دقیقاً به این صورته:
---
## 💡 فقط String نیست!
نکتهی جالب اینه که Pipeها محدود به
* 👤 یک Model (مثل
* 📦 یک DTO
* 🗂️ یک آرایه
* 📚 یک Collection
* 🛠️ حتی یک Query Builder
مثلاً با یک Model:
هر Pipe دقیقاً همون شیء
اون رو به مرحلهی بعد ارسال میکنه.
---
💡 هر جا دادهای قرار باشه از چند مرحلهی پردازش عبور کنه، Pipeline یکی از بهترین انتخابهاست.
من معمولاً از Pipeline برای این سناریوها استفاده میکنم:
🔹 پردازش فرمها
🔹 اعتبارسنجیهای چندمرحلهای
🔹 پردازش فایلها و تصاویر
🔹 فیلتر کردن محتوا
🔹 ساخت Queryهای داینامیک
---
🔥 شما تا حالا از
یا هنوز همهی منطق رو داخل یک Service یا Controller مینویسین؟ 👇
───────────────
📢 @DDNotes
───────────────
#Laravel #PHP #Pipeline #CleanCode #DesignPatterns #Backend #LaravelTips #SoftwareArchitecture
وقتی یه ورودی باید از چند مرحله پردازش عبور کنه، خیلی از ما یه عالمه
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