کُدفیوز :‌ آموزش و نکات حرفه ای php و لاراول
285 subscribers
8 links
سلام به همه برنامه‌نویسان و علاقه‌مندان به دنیای PHP و لاراول! 👋

کُدفیوز جاییه که توش آموزش‌های کاربردی PHP و لاراول رو یاد می‌گیری، با نکات و ترفندهایی آشنا میشی که کمتر بهشون توجه شده.
Download Telegram
🎯 میدونید Laravel Herd چیه و چه امکاناتی داره ؟

من توی کانال تلگرامی کدفیوز : https://t.me/codefuse1 تلاش میکنم جدیدترین مباحث لاراول رو پوشش بدهم

و همچنین به هر چیزی که یک برنامه نویس لاراول نیاز داره اشاره کنم پس در این پست همراه من باشید که قصد دارم در خصوص Laravel Herd صحبت کنیم که چه امکاناتی داره و چه موقع بهتر است

اگر در شروع راه هستید و قصد دارید از WAMP ویا XAMPP استفاده کنید ابزارLaravel Herd برای شما گزینه بهتری هست

چرا ؟

1️⃣ نصب و راه‌اندازی سریع (بدون نیاز به Docker)

برخلاف ابزارهایی مثل Laradock یا Laravel Sail، Herd به Docker متکی نیست؛ بنابراین، فرآیند راه‌اندازی بسیار ساده‌تر میشه.

2️⃣ پشتیبانی از نسخه‌های مختلف PHP

به‌سادگی می‌تونید بین ورژن‌های مختلف PHP سوئیچ کنید و هر پروژه رو با نسخهٔ مناسب خودش اجرا کنید.

3️⃣ وب‌سرور و پایگاه داده آماده

به‌صورت پیش‌فرض از Nginx و MySQL استفاده می‌کنه. همچنین امکان استفاده از phpMyAdmin و Mailhog برای مدیریت دیتابیس و تست ایمیل وجود داره.

4️⃣ ایجاد گواهی SSL

می‌تونید به‌راحتی گواهی SSL برای دامنه‌های لوکال بسازید و با HTTPS کار کنید.

5️⃣ مدیریت لاگ در لحظه

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

6️⃣ پشتیبانی از Queue Worker و Redis

اگر پروژه‌هاتون به صف‌ها و Redis نیاز دارن، Herd از پیش این امکانات رو پیکربندی کرده.

7️⃣ سازگاری با مک و ویندوز

فرقی نداره کاربر macOS هستید یا ویندوز؛ در هر دو سیستم‌عامل می‌تونید از Herd استفاده کنید.

⚠️ اگر به‌صورت حرفه‌ای کار می کنید Herd گزینه خیلی خوبی برایتان نخواهد بود

در عین حال، اگر قصد دارید پروژه‌های سنگین‌تر یا چندنفره رو مدیریت کنید و نیاز به کانتینرهای ایزوله دارید، پیشنهاد می‌شه به ابزارهای Dockerمحور مثل Laradock یا Laravel Sail هم نگاهی بندازید. در پست‌های آینده، این ابزارها رو به‌صورت جدی‌تر با Herd و سایر روش‌ها مقایسه خواهیم کرد.

⁉️ جمع‌بندی

ابزار Laravel Herd با تمرکز بر ساده‌سازی محیط توسعه و رفع دغدغه‌های پیکربندی، می‌تونه ابزار جذابی برای شروع سریع پروژه‌های Laravel باشه. اگر تجربه یا سوالی دربارهٔ Herd دارید، خوشحال می‌شیم بشنویم!

#LaravelHerd #Laravel #PHP #Developer #Windows #MacOS #LocalEnvironment #SSL #MySQL #Redis #MailHog #Laradock #LaravelSail
👍3🔥1👏1
🔒 آموزش رمزنگاری فایل‌های .env در لاراول

🚨 چرا باید فایل‌های .enb را رمزنگاری کنیم؟

فایل‌های محیطی (مانند `.env`) اطلاعات حساسی نظیر کلیدهای API، رمزهای پایگاه داده و سایر اطلاعات مهم را در خود ذخیره می‌کنند. ذخیره این فایل‌ها به‌صورت غیر رمزنگاری‌شده در مخازن گیت یا روی سرور production خطرناک است. اما لاراول به شما امکان می‌دهد این فایل‌ها را رمزنگاری کنید تا با اطمینان بیشتری در مخزن سورس کنترل یا روی سرور production قرار گیرند.

---

🔐 رمزنگاری فایل‌های محیطی

برای رمزنگاری فایل .env، دستور زیر را اجرا کنید:


php artisan env:encrypt


🔑 پس از اجرای دستور، فایل .env شما رمزنگاری شده و به‌صورت یک فایل جدید به نام .env.encrypted ذخیره می‌شود.

کلید رمزنگاری نیز در خروجی این دستور نمایش داده می‌شود؛ این کلید را در یک جای امن ذخیره کنید. برای رمزگشایی .env به آن نیاز خواهید داشت

اگر بخواهید کلید رمزنگاری خود را مشخص کنید، می‌توانید از گزینه --key استفاده کنید:


php artisan env:encrypt --key=3UVsEgGVK36XN82KKeyLFMhvosbZN1aF


💡 توجه داشته باشید که طول کلید ارائه‌شده باید با الگوریتم رمزنگاری مورد استفاده هماهنگ باشد.

کلید رمزنگاری (Encryption Key) بخش مهمی از فرآیند رمزنگاری است. هر الگوریتم رمزنگاری نیاز به طول کلید مشخصی دارد که در صورت عدم تطابق، رمزنگاری یا رمزگشایی کار نخواهد کرد و با خطا روبرو می‌شوید.

مثال در لاراول:

AES-256-CBC:

- نیاز به کلید 32 کاراکتری دارد.

- مثال:

php artisan env:encrypt --key=ABCDEFGHIJKLMNOPQRSTUVWX123456


AES-128-CBC:

- نیاز به کلید 16 کاراکتری دارد.

- مثال:

php artisan env:encrypt --key=ABCDEFGH12345678 --cipher=AES-128-CBC


### چرا طول کلید مهم است؟

- امنیت بیشتر: طول بیشتر کلید باعث افزایش امنیت می‌شود.

- پشتیبانی الگوریتم: هر الگوریتم فقط طول خاصی را می‌پذیرد.

⚠️ اگر طول کلید مناسب نباشد، خطای زیر ظاهر می‌شود:


The key length does not match the requirements of the cipher.


لاراول به‌صورت پیش‌فرض از الگوریتم AES-256-CBC استفاده می‌کند که نیازمند کلیدی به طول 32 کاراکتر است.

برای استفاده از الگوریتم‌های دیگر، گزینه --cipher را اضافه کنید:


php artisan env:encrypt --cipher=AES-128-CBC


🌐 اگر چندین فایل محیطی دارید (مانند .env و .env.staging`)، می‌توانید فایل موردنظر را با استفاده از گزینه `--env مشخص کنید:


php artisan env:encrypt --env=staging


---

🔓 رمزگشایی فایل‌های محیطی

برای رمزگشایی فایل‌های محیطی، از دستور زیر استفاده کنید:


php artisan env:decrypt


🔑 لاراول کلید رمزنگاری را از متغیر محیطی LARAVEL_ENV_ENCRYPTION_KEY دریافت می‌کند.

همچنین می‌توانید کلید را مستقیماً با گزینه --key ارائه دهید:


php artisan env:decrypt --key=3UVsEgGVK36XN82KKeyLFMhvosbZN1aF


با اجرای این دستور، محتوای فایل .env.encrypted رمزگشایی شده و در فایل .env ذخیره می‌شود.

برای استفاده از الگوریتم‌های دیگر در رمزگشایی، می‌توانید گزینه --cipher را اضافه کنید:


php artisan env:decrypt --key=qUWuNRdfuImXcKxZ --cipher=AES-128-CBC


🌐 اگر چندین فایل .env دارید، می‌توانید فایل موردنظر را با گزینه --env مشخص کنید:


php artisan env:decrypt --env=staging


اگر فایل .env موجود باشد و بخواهید آن را بازنویسی کنید، از گزینه --force استفاده کنید:


php artisan env:decrypt --force


---

با استفاده از این قابلیت، امنیت پروژه لاراول خود را به سطح بالاتری ببرید و اطلاعات حساس را با اطمینان مدیریت کنید.

🛡️ رمزنگاری امن، پروژه‌ای امن‌تر!
👍6👌5
🧑‍💻 اهمیت collation در دیتابیس و تفاوت‌های آن در MySQL 📊

در دیتابیس‌ها، collation نحوه مقایسه و ترتیب داده‌های متنی (مثل رشته‌ها) را تعیین می‌کند. هنگام استفاده از دیتابیس‌هایی مثل MySQL، انتخاب collation مناسب می‌تواند تأثیر زیادی بر روی عملکرد، جستجوها و رفتار مقایسه‌ای داده‌ها داشته باشد.

در این پست به Collation های مختلف در MySQL، تفاوت‌ها و اهمیت آن‌ها به خصوص در رابطه با حساسیت به حروف بزرگ و کوچک و چگونگی استفاده از آن‌ها با مثال‌های SQL پرداخته‌ایم. ⚙️

🧐 انواع Collation در MySQL

دیتابیس MySQL از دو نوع اصلی collation پشتیبانی می‌کند:

1.نوع اول : هر نوع Collation که _ci دارد (case-insensitive)مقایسه‌ها بدون توجه به حروف بزرگ و کوچک انجام می‌شود.

2. نوع دوم : هر نوع Collation که _bin دارد (case-sensitive): مقایسه‌ها حساس به حروف بزرگ و کوچک است.

1.نوع اول : هر نوع Collation که _ci دارد (case-insensitive) 🔠

این نوع از collation ها برای مقایسه رشته‌ها حساس به حروف بزرگ و کوچک نیستند. به این معنی که وقتی دو رشته را با این collation مقایسه می‌کنید، تفاوت‌های حروف بزرگ و کوچک در نظر گرفته نمی‌شود.

مثال‌هایی از collation های `*_ci`:
- utf8mb4_unicode_ci
- utf8_general_ci

💡 مثال:

فرض کنید جدول products دارید که در آن یک ستون به نام product_code با collation utf8mb4_unicode_ci داریم و دو کد محصول وارد کرده‌ایم:


INSERT INTO products (product_code, price)
VALUES ('Y1J09bGxwM', 100),
('Y1J09bgXwM', 200);


حالا اگر بخواهیم جستجویی انجام دهیم و رشته‌ای به شکل Y1J09bGxwM را جستجو کنیم:


SELECT * FROM products WHERE product_code = 'Y1J09bGxwM';


نتیجه:
- چون collation utf8mb4_unicode_ci حساس به حروف بزرگ و کوچک نیست، این کوئری هر دو مقدار Y1J09bGxwM و Y1J09bgXwM را به عنوان یکسان می‌بیند و نتیجه یکسان خواهد بود. 👫

2. هر نوع Collation که _bin دارد (case-sensitive) 🔡

در این نوع از collation ها، مقایسه رشته‌ها حساس به حروف بزرگ و کوچک است. به این معنی که A و a به عنوان دو حرف مختلف در نظر گرفته می‌شوند.

مثال‌هایی از collation های `*_bin`:
- utf8mb4_bin
- utf8_bin

💡 مثال:

حال فرض کنید همان جدول products را داریم، اما این بار collation ستون product_code را به utf8mb4_bin تغییر می‌دهیم.


ALTER TABLE products
MODIFY product_code VARCHAR(255) COLLATE utf8mb4_bin;


حالا اگر دوباره دو کد محصول را وارد کنیم:


INSERT INTO products (product_code, price)
VALUES ('Y1J09bGxwM', 100),
('Y1J09bgXwM', 200);


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


SELECT * FROM products WHERE product_code = 'Y1J09bGxwM';


نتیجه:

- در اینجا چون collation utf8mb4_bin حساس به حروف بزرگ و کوچک است، این کوئری فقط رکوردی با product_code = 'Y1J09bGxwM' را برمی‌گرداند و هیچ رکوردی با product_code = 'Y1J09bgXwM' پیدا نمی‌شود، چون حروف بزرگ و کوچک متفاوت هستند. 🔍

تفاوت در عملکرد

-در خوص Performance : زمانی که از utf8mb4_bin استفاده می‌کنید، مقایسه‌ها می‌توانند سریع‌تر انجام شوند چون MySQL به طور مستقیم با بایت‌ها مقایسه می‌کند و نیازی به انجام عملیات پیچیده بر روی رشته‌ها ندارد. در مقابل، در collation های `utf8mb4_unicode_ci`، مقایسه‌ها پیچیده‌تر است و ممکن است کمی زمان‌برتر باشد، زیرا باید تفاوت‌های ظریف را در نظر بگیرد (برای مثال، حروف با توجه به قواعد زبان‌ها مقایسه می‌شوند).

📋 جمع‌بندی

- در نوع اول : هر نوع Collation که _ci دارد مقایسه‌ها حساس به حروف بزرگ و کوچک نیستند. به عنوان مثال در کالکشن utf8mb4_unicode_ci رفتار روی رکورد های `، `Y1J09bGxwM و Y1J09bgXwM مشابه در نظر گرفته می‌شوند. 🔄

- در نوع دوم : هر نوع Collation که _bin دارد مقایسه‌ها حساس به حروف بزرگ و کوچک هستند. به عنوان مثال در کالکشن utf8mb4_bin رفتار روی رکورد های`، `Y1J09bGxwM و Y1J09bgXwM کاملاً متفاوت هستند. 🔎

انتخاب بین این دو نوع collation بستگی به نیاز شما دارد: اگر حساسیت به حروف بزرگ و کوچک برای شما مهم است، از *_bin استفاده کنید، در غیر این صورت، *_ci برای شما مناسب‌تر خواهد بود.
👍8
🌟 معرفی قابلیت جذاب Health Route در لاراول 11 🌟

سلام به همه‌ی توسعه‌دهنده‌های عزیز! 😊

امروز می‌خوایم درباره یه قابلیت خیلی کاربردی توی لاراول 11 صحبت کنیم: Health Route. اگه پروژه‌هایی داری که نیاز به بررسی وضعیت سلامت اپلیکیشن دارن، این ویژگی می‌تونه خیلی کارت رو راحت کنه. 🚀

قابلیت Health Route چیه؟

قابلیت Health Route توی لاراول یه مسیر داخلیه که می‌تونی ازش برای بررسی وضعیت اپلیکیشن استفاده کنی. فرض کن داری از ابزارهایی مثل مانیتورینگ آپ‌تایم (Uptime Monitor) 🖥️، لود بالانسر (Load Balancer) یا سیستم‌هایی مثل Kubernetes استفاده می‌کنی. با این قابلیت، می‌تونی مطمئن بشی اپلیکیشن بدون مشکل داره کار می‌کنه.

به صورت پیش‌فرض، این قابلیت روی مسیر /up در دسترسه. اگه همه چیز درست باشه، یه پاسخ HTTP 200 برمی‌گردونه. ولی اگه مشکلی وجود داشته باشه، جواب HTTP 500 می‌ده.

نکته جالب اینه که می‌تونی مسیر پیش‌فرض رو تغییر بدی و متناسب با نیازت تنظیمش کنی. 🌐

در مسیر

bootstrap/app.php

کدی که به صورت پیشفرض وجود داره :


->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)


میتونی مسیر پیش‌فرض رو تغییر بدی :


->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/status',
)


چک کردن وضعیت خاص‌تر اپلیکیشن 🔍

جالب‌تر اینه که وقتی به مسیر Health Route درخواست می‌دی، یه رویداد به اسم Illuminate\Foundation\Events\DiagnosingHealth اجرا می‌شه.
این یعنی دستت بازه که وضعیت‌های خاص اپلیکیشن، مثل اتصال به دیتابیس یا حتی سرویس‌های دیگه رو چک کنی.

مثال برای بررسی اتصال دیتابیس: 🛠️

فرض کن می‌خوای مطمئن بشی دیتابیس درست کار می‌کنه. می‌تونی یه Listener برای این رویداد تعریف کنی و اتصال به دیتابیس رو بررسی کنی. کد زیر یه نمونه از این کاره:


use Illuminate\Foundation\Events\DiagnosingHealth;

Event::listen(DiagnosingHealth::class, function () {
try {
DB::connection()->getPdo();
} catch (\Exception $e) {
throw new \Exception('Database connection failed!');
}
});


توی این مثال، ما داریم وضعیت دیتابیس رو بررسی می‌کنیم. اگه اتصال برقرار نباشه، لاراول یه ارور مناسب اعلام می‌کنه (مثلاً «Database connection failed!») و درخواست به Health Route، پاسخ HTTP 500 برمی‌گردونه.

💡 چرا این قابلیت مهمه؟ 💡

این قابلیت بهت کمک می‌کنه:

- آپ‌تایم اپلیکیشن رو تضمین کنی. 🔄

- مشکلات احتمالی رو قبل از اینکه کاربرها متوجه بشن پیدا کنی. 🚨

- وضعیت سلامت اپلیکیشن رو به ابزارهای مانیتورینگ یا سیستم‌های هماهنگی اطلاع بدی. 📡

جمع‌بندی 🎯

قابلیت Health Route یه ابزار قدرتمنده که کار توسعه‌دهنده‌ها رو برای بررسی و تضمین پایداری اپلیکیشن خیلی راحت‌تر می‌کنه. با چند خط کد ساده می‌تونی مطمئن بشی همه چیز درست کار می‌کنه و اگه مشکلی باشه، سریع خبردار می‌شی.

حتماً این قابلیت رو توی پروژه‌هات امتحان کن و اگه سوالی داشتی، همینجا بپرس!
👍6
📌 چطور لاراول در روت‌ها از توابع ناشناس (Closure) استفاده می‌کند؟

یکی از سئوالاتی که ممکن است در مصاحبه‌های استخدامی در برندهای معتبر ایرانی یا خارجی با آن روبرو شوید، استفاده از توابع ناشناس (Closure) در لاراول است.

🔹 احتمالاً شما در لاراول بارها از توابع ناشناس استفاده کرده‌اید، اما ممکن است نتوانید به درستی به این سئوال پاسخ دهید. بنابراین، در این پست قصد داریم در خصوص توابع ناشناس (Closure) و استفاده از آن‌ها در روت‌ها صحبت کنیم. 📝

توابع ناشناس (Closure) چیستند؟

توابع ناشناس یا Closureها توابعی هستند که بدون نام تعریف می‌شوند و می‌توانند به متغیرهایی که در محیط خود قرار دارند دسترسی پیدا کنند. این توابع معمولاً برای استفاده در callbackها یا ارسال به متدهای دیگر به کار می‌روند.

مثال:


$discount = 0.2; // تخفیف 20 درصد
$productPrice = 100; // قیمت اولیه محصول

$applyDiscount = function ($price) use ($discount) {
return $price - ($price * $discount);
};

$finalPrice = $applyDiscount($productPrice);

echo "قیمت نهایی محصول: " . $finalPrice;

// خروجی: قیمت نهایی محصول: 80


💡 در این مثال، متغیر $discount از خارج تابع به Closure وارد شده است تا بتوانیم از آن برای محاسبه قیمت نهایی استفاده کنیم.

استفاده از Closure در روت‌های لاراول:

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

مثال از روت لاراول با Closure:


Route::get('greet/{name}', function ($name) {
return "Hello, {$name}! 👋";
});


🔸 وقتی شما از این روش استفاده می‌کنید، در واقع از توابع ناشناس (Closure) در روت‌های لاراول بهره می‌برید. در این حالت، لاراول از Closure برای پردازش درخواست‌های ورودی و بازگشت پاسخ استفاده می‌کند.

چرا این روش مفید است؟

- استفاده از توابع ناشناس در روت‌ها برای پاسخگویی سریع به درخواست‌ها و ساده‌تر کردن کد مفید است.

- در مواردی که نیاز به تعریف عملکرد خاص در روت‌ها دارید و نمی‌خواهید کلاس‌های پیچیده بنویسید، Closureها انتخاب مناسبی هستند.

🔑 نکته: حتی اگر شما بارها از این روش‌ها در لاراول استفاده کرده‌اید، ممکن است در مصاحبه‌های فنی از شما خواسته شود که این مفهوم را توضیح دهید. پس بهتر است با دقت و درک کامل از این ابزار استفاده کنید. 🎯

———————————————————————————

@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه ای php و لاراول
👍4
📌 آیا تا به حال از Contextual Attributes در لاراول استفاده کرده‌اید؟

یکی از سوالات مهم در مصاحبه‌های استخدامی برای توسعه‌دهندگان لاراول این است که: "Contextual Attributes چیست و چگونه در لاراول استفاده می‌شود؟" 🤔

در نسخه 8.x و بعد از آن، لاراول به توسعه‌دهندگان این امکان را می‌دهد که وابستگی‌ها و پیکربندی‌ها را بدون نیاز به تعریف دستی در سرویس‌پروایدرها تزریق کنند. این ویژگی به نام Contextual Attributes شناخته می‌شود.

مزایای این ویژگی:

کاهش پیچیدگی کد: بدون نیاز به نوشتن کد اضافی برای تنظیم bindings.

انعطاف‌پذیری بالا: به‌طور خودکار و بدون نیاز به پیکربندی‌های اضافی می‌توانید دیسک‌ها یا مقادیر مختلف را تزریق کنید.

کاهش خطاهای انسانی: لاراول این تزریق‌ها را به‌طور خودکار مدیریت می‌کند و احتمال بروز اشتباهات را کاهش می‌دهد.


💻 مثال کد:

فرض کنید شما دو دیسک ذخیره‌سازی دارید: یکی برای ذخیره‌سازی عکس‌ها و دیگری برای داکیومنت‌ها. با استفاده از ویژگی **`#[Storage]`**، می‌توانیم به راحتی این دیسک‌ها را به کنترلر تزریق کنیم.


namespace App\Http\Controllers;

use Illuminate\Container\Attributes\Storage;
use Illuminate\Contracts\Filesystem\Filesystem;

class PhotoController extends Controller
{

public function __construct(
#[Storage('local')] protected Filesystem $photoStorage,
#[Storage('documents')] protected Filesystem $documentStorage
)
{
// دیسک‌ها به‌طور خودکار تزریق می‌شوند
}


public function storePhoto()
{
$path = $this->photoStorage->put('user_photo.jpg', file_get_contents('path_to_photo_file'));
return "Photo saved to local storage: $path";
}


public function storeDocument()
{
$path = $this->documentStorage->put('user_document.pdf', file_get_contents('path_to_document_file'));
return "Document saved to documents storage: $path";
}
}


در این مثال، ویژگی #[Storage] به‌طور خودکار دیسک‌های مختلف را به متغیرهای کنترلر تزریق می‌کند. در این حالت، ما از دیسک local برای ذخیره‌سازی عکس‌ها و از دیسک documents برای ذخیره‌سازی داکیومنت‌ها استفاده کرده‌ایم.

🛠️ ویژگی‌های دیگر Contextual Attributes در لاراول:

در کنار ویژگی #[Storage]، لاراول ویژگی‌های دیگری مانند #[Auth]، #[Cache]، #[Config]، #[DB]، #[Log]، #[RouteParameter] و #[Tag] را نیز به‌منظور تزریق مقادیر مختلف به کنترلرها و کلاس‌ها فراهم کرده است.

1. #[Auth]:
با استفاده از ویژگی #[Auth] می‌توانید گاردهای مختلف auth را به‌صورت خودکار به کنترلرها تزریق کنید. این ویژگی به‌ویژه زمانی مفید است که شما نیاز دارید تا در کلاس‌های مختلف به گارد خاصی مانند web یا api دسترسی پیدا کنید.


#[Auth('web')] protected Guard $auth;


در این مثال، گارد web به متغیر $auth تزریق می‌شود.

2. #[Cache]:

این ویژگی به شما امکان می‌دهد تا یک مخزن کش خاص را به‌صورت خودکار تزریق کنید. مثلاً می‌توانید از redis برای کش کردن داده‌ها استفاده کنید.


#[Cache('redis')] protected Repository $cache;


در اینجا، redis به‌عنوان مخزن کش به $cache تزریق می‌شود.


3. #[Config]:

با استفاده از ویژگی #[Config]، می‌توانید مقادیر پیکربندی خاص را از فایل‌های پیکربندی لاراول استخراج کرده و به‌صورت مستقیم در کنترلرها تزریق کنید.


#[Config('app.timezone')] protected string $timezone;

در این مثال، مقدار timezone از فایل پیکربندی app.php به متغیر $timezone تزریق می‌شود.

4. #[DB]:

این ویژگی به شما این امکان را می‌دهد که یک اتصال به پایگاه داده خاص را به‌صورت خودکار تزریق کنید. می‌توانید برای انتخاب اتصال خاص از نام آن استفاده کنید.


#[DB('mysql')] protected Connection $connection;


در اینجا، اتصال به پایگاه داده mysql به $connection تزریق می‌شود.


5. #[CurrentUser]:

ویژگی #[CurrentUser] به شما این امکان را می‌دهد که کاربر جاری (authenticated user) را به‌صورت خودکار به یک مسیر یا کلاس تزریق کنید. این ویژگی به‌ویژه برای دریافت اطلاعات کاربری که در حال حاضر وارد سیستم شده است مفید است.


use App\Models\User;
use Illuminate\Container\Attributes\CurrentUser;

Route::get('/user', function (#[CurrentUser] User $user) {
return $user;
})->middleware('auth');


در این مثال، کاربر جاری به‌صورت خودکار به متغیر $user تزریق می‌شود.

این ویژگی یکی از قابلیت‌های قدرتمند لاراول است که کمک می‌کند تا کد شما مرتب‌تر و ساده‌تر شود.

———————————————————————————

@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه ای php و لاراول
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
🎩 تا حالا از پکیج laravel-hashids استفاده کرده اید ؟

🚀 تا حالا دقت کردید که در برخی سایت‌ها، آدرس‌ها این شکلیه؟

🔴 example.com/user/123

🔴 example.com/post/456

این آیدی‌ها قابل حدس هستن و هر کسی می‌تونه با تغییر عدد، به اطلاعات بقیه‌ی کاربران دسترسی پیدا کنه! 😱

اینجاست که پکیج laravel-hashids به کمکمون میاد! 🎩

💡البته یک نکته ای رو هم جا داره اینجا اضافه کنم که برخی ها همین کارپکیج laravel-hashids رو خودشون بدون پکیج انجام می دهند و روند مشابهی رو داخل پروژه پیاده سازی میکنن که هر دو روش در جای خودش درست هست

🔹 پکیج laravel-hashids چی کار میکنه؟

این پکیج (laravel-hashids) شناسه‌های عددی (ID) رو به رشته‌های تصادفی و غیرقابل حدس تبدیل می‌کنه.

مثال:

🔹 example.com/user/b9iLXiAa

🔹 example.com/post/qW8nG5zK

🛡️ دیگه کسی نمی‌تونه با حدس زدن آیدی‌ها، به اطلاعات کاربران دسترسی پیدا کنه!

🔹 چطور استفاده کنیم؟

🔹 نصب:

composer require vinkla/laravel-hashids


🔹 رمزگذاری شناسه:

$hash = Hashids::encode(123);
echo $hash; // خروجی: b9iLXiAa


🔹 رمزگشایی شناسه:

$id = Hashids::decode($hash)[0] ?? null;


🔹 استفاده در URLها:

Route::get('/user/{hash}', function ($hash) {
$id = Hashids::decode($hash)[0] ?? abort(404);
return view('user.profile', ['user' => User::findOrFail($id)]);
});


📌 فرق laravel-hashids و UUID و کاربردهاشون

🔹 laravel-hashids

پکیج laravel-hashids شناسه‌های عددی (مثل IDهای دیتابیس) رو به رشته‌های غیرقابل حدس و کوتاه تبدیل می‌کنه. مثلاً:

🔴 example.com/user/123example.com/user/b9iLXiAa

💡 این روش برای مخفی‌سازی شناسه‌ها در URLها و جلوگیری از حدس‌ زدن اونها استفاده میشه.

🔹شناسه جهانی یکتا (UUID)

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

مثلاً:
🔴 123e4567-e89b-12d3-a456-426614174000

💡 کاربردش برای شناسه‌های یکتا در سیستم‌هاست، اما چون طولانیه، برای نمایش در URL مناسب نیست.

📢 کدوم روش رو برای مخفی‌سازی شناسه‌ها ترجیح می‌دید؟ نظرتون رو بگید! 💬

🚀 جمع‌بندی:

مخفی کردن شناسه‌های دیتابیس

جلوگیری از دسترسی غیرمجاز به اطلاعات کاربران

ایجاد URLهای کوتاه، امن و زیبا

📢 شما از چه روشی برای مخفی‌سازی شناسه‌ها استفاده می‌کنید؟ نظرتون رو بگید! 💬
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
چطور کوئری‌های کند را در Laravel شناسایی می‌کنید؟ 🤔💡

فرض کنید یک پروژه‌ی Laravel در حال اجرا دارید و کاربران از کندی برخی صفحات شکایت می‌کنند. 🚀 ولی شما نمی‌دانید کدام کوئری‌ها باعث این مشکل شده‌اند! 🤯

شما چطور این مشکل را بررسی می‌کنید؟

🔹 از Laravel Debugbar استفاده می‌کنید؟

🔹 سراغ Slow Query Log در MySQL می‌روید؟

🔹 یا شاید راهکار دیگری دارید؟

جواب‌هایتان را در کامنت‌ها بنویسید! 💬👇

🎯 یکی از روش‌هایی که من استفاده می‌کنم:

یکی از ساده‌ترین راه‌ها برای شناسایی کوئری‌های کند در Laravel، استفاده از DB::listen() در AppServiceProvider است.

با این روش، هر کوئری که بیشتر از ۱ ثانیه طول بکشد، در لاگ ذخیره می‌شود! 🚀


use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

public function boot()
{
DB::listen(function ($query) {
if ($query->time > 1000) { // یک ثانیه
Log::warning('🚨 Slow Query Detected: ' . $query->sql, [
'bindings' => $query->bindings,
'time' => $query->time
]);
}
});
}


🔹 این کد چه کاری انجام می‌دهد؟

همه‌ی کوئری‌های اجرا شده را مانیتور می‌کند
اگر زمان اجرای کوئری بیش از ۱۰۰۰ میلی‌ثانیه (۱ ثانیه) باشد، آن را در لاگ ثبت می‌کند
با استفاده از Log::warning() کوئری را به همراه مقدار بایندینگ‌ها و زمان اجرا ذخیره می‌کند

💡 چرا این روش کاربردی است؟

🚀 بدون نیاز به تغییر در کوئری‌ها یا مدل‌ها، می‌توان مشکلات کندی را شناسایی کرد
🔎 مناسب برای بررسی‌های عملکردی و بهینه‌سازی دیتابیس
📊 ترکیب آن با ابزارهایی مثل Laravel Telescope یا Debugbar، تحلیل بهتری فراهم می‌کند

📢 تجربه‌ی شما چیه؟

💡 آیا تا حالا با کوئری‌های کند در Laravel مواجه شده‌اید؟

شما چه روشی برای شناسایی و بهینه‌سازی آن‌ها استفاده می‌کنید؟

منتظر نظرات ارزشمندتون هستم! 💬👇
👍11
🔥 نظرتون در مورد کنترلرهای تک‌عملکردی (Single Action Controllers) در لاراول چیه؟ 🔥

👨‍💻 به نظرتون استفاده از کنترلرهای تک‌عملکردی روش درستی هست یا باعث پیچیدگی های غیر ضروری میشه ؟ ، نظرتون رو برایم در کامنت ها بنویسید

اما امروز میخواهم در مورد کنترلر های عملکردی invokable و یا (Single Action Controllers) باهم صحبت کنیم

یکی از روش هایی که برخی از برنامه نویس ها انجام میدهند اینه که میان یک روت تعریف میکنند که فقط یک متد داره این جوری تقریبا


Route::post('server', [ProvisionServerController::class, 'createServer']);


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

که از اون به نام های (Single Action Controllers) یا کنترلر های invokable یاد می شود

ممکن در مصاحبه های استخدامی هم سئوالاتی تحت عنوان کنترلر های invokable چی هستند ازتون پرسیده بشه ،‌پس مهم هست که در مورد آن بدانید

در واقع این کنترلر ها به این صورت ساخته می شوند

🚀 مرحله ۱: ایجاد کنترلر تک‌عملکردی


php artisan make:controller ProvisionServer --invokable


🚀 مرحله ۲: تعریف کنترلر

<?php

namespace App\Http\Controllers;

class ProvisionServerController extends Controller
{
public function __invoke()
{
return response()->json(['message' => 'Server provisioned successfully!']);
}
}


🚀 مرحله ۳: ثبت مسیر در `routes/web.php`

در بخش route ها هم مثلا در فایل web.php به این صورت میتونید آنها را تعریف کنید


use App\Http\Controllers\ProvisionServerController;

Route::post('/server', ProvisionServerController::class);


🚀 مرحله ۴: تست API

curl -X POST http://your-app-url/server


حالا هر درخواست POST به مسیر /server مستقیماً متد __invoke در ProvisionServerController را اجرا می‌کند.

شما از این نوع کنترلرها استفاده کردید؟ اگر تجربه‌ای در این مورد دارید، توی نظرات بگید! 💬

————————————————————

@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه ای php و لاراول
👍9
آیا تنظیم worker_processes در Nginx را انجام می‌دید؟ 🤔

اول از همه، worker_processes چیه ؟ 🤷‍♂️

بیاید از ابتدا شروع کنیم! وقتی شما از Nginx برای مدیریت وب‌سایتتون استفاده می‌کنید، یکی از اولین تنظیماتی که باید بهش توجه کنید، worker_processes هست.

این تنظیم مشخص می‌کنه که Nginx چقدر پردازش موازی برای مدیریت درخواست‌ها و ترافیک به وب‌سایت شما ایجاد کنه. به عبارت ساده‌تر، تعداد پردازش‌هایی که Nginx برای پاسخ به درخواست‌های کاربران راه می‌اندازه، به عهده همین تنظیمه.

حالا worker_processes در Nginx را چگونه پیکربندی کنیم ؟

در تنظیمات پیش‌فرض، Nginx معمولاً تعداد worker_processes رو روی ۲ تا ۴ تا تنظیم می‌کنه.

اما حالا فرض کنید که این مقدار رو به حالت auto تنظیم کنید. 🤖

وقتی worker_processes رو روی Auto بذارید چه اتفاقی می‌افته؟ 🔧

خب، وقتی این گزینه رو روی auto بذارید، Nginx خودش به‌طور خودکار تعداد پردازش‌ها رو مطابق با تعداد هسته‌های پردازنده سرور شما تنظیم می‌کنه. اینجوری Nginx به‌طور هوشمندانه از تمام منابع پردازشی سرور استفاده می‌کنه و عملکرد کلی بهتر می‌شه. 🚀

اما سوال اینجاست: آیا همیشه باید از Auto استفاده کنیم؟ 🤔

در حالی که حالت auto برای اکثر سناریوها انتخاب مناسبی است، در بعضی شرایط خاص، تنظیم دستی worker_processes می‌تواند مزایای بیشتری داشته باشد.

1. سرور با تعداد هسته‌های زیاد یا کم:

سرور با هسته‌های زیاد (مثلاً ۱۲ هسته و یا بیشتر): اگر سرور شما ۱۲ هسته دارد و ترافیک کمی دریافت می‌کند، حالت auto ممکن است منابع اضافی مصرف کند. در این صورت، تنظیم دستی تعداد پردازش‌ها (مثلاً روی ۴ یا ۶) می‌تواند مصرف منابع را بهینه‌تر کند.

سرور با هسته‌های کم (مثلاً ۴ هسته): اگر سرور شما ۴ هسته دارد و ترافیک زیادی می‌آید، حالت auto ممکن است باعث مصرف بی‌مورد منابع شود. تنظیم دستی تعداد پردازش‌ها (مثلاً روی ۳ یا ۴) می‌تواند عملکرد را بهبود دهد و از مصرف اضافی منابع جلوگیری کند.

2.پروژه‌های با پردازش‌های سنگین:

برای پروژه‌هایی با پردازش‌های سنگین مانند استریمینگ ویدئو یا بار پردازشی بالا، تنظیم دستی worker_processes کمک می‌کند تا منابع به‌طور دقیق‌تری اختصاص داده شوند و عملکرد بهینه شود. زمانی که تعداد درخواست‌ها زیاد و پردازش‌ها زمان‌بر هستند، تنظیم تعداد پردازش‌ها می‌تواند تاثیر زیادی داشته باشد.

مثال: برای سرویس ویدئو استریمینگ با درخواست‌های همزمان زیاد، تنظیم تعداد پردازش‌ها روی ۸ یا ۱۲ می‌تواند عملکرد و مدیریت منابع را بهبود دهد.

حالا نظر شما چیه؟ 🗣️

تا حالا از گزینه auto استفاده کردید؟ چطور بوده تجربه‌تون؟ خوشحال می‌شیم نظرات و تجربیات شما رو بشنویم! 💬

————————————————————

@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه ای php و لاراول
👍6🔥2
🚀 از Macroable توی لاراول استفاده می کنید ؟

سلام رفقا! 🌱

یه ویژگی باحال توی لاراول هست به اسم Macroable که شاید خیلیا هنوز باهاش آشنا نباشن یا کمتر ازش استفاده می‌کنن.

🧠 اصلاً Macroable چیه؟

لاراول یه trait داره به اسم Macroable که بهت اجازه می‌ده به یه کلاس، بعد از تعریف شدنش، متدهای جدید اضافه کنی — بدون اینکه نیاز باشه اون کلاس رو extend یا دستکاری کنی! 😍

مثلاً به کلاس‌هایی مثل Response، Collection، Str و... میتونیم متدهای خودمون رو اضافه کنیم! 😎
‍‍‍‍‍‍
مثلا فرض کنید میخواهیم به کلاس Response یک متد جدید اضافه کنیم :

use Illuminate\Support\Facades\Response;

Response::macro('apiSuccess', function ($data = [], $message = 'با موفقیت انجام شد') {
return response()->json([
'status' => true,
'message' => $message,
'data' => $data,
]);
});


بعدش می‌تونی راحت استفاده کنی:

return Response::apiSuccess(['user' => $user]);




کجا تعریفش کنیم؟

معمولاً این جور macroها رو توی فایل AppServiceProvider و متد boot() می‌نویسیم، تا با شروع برنامه لود بشن:

public function boot()
{
Response::macro('apiSuccess', function (...) {
// ...
});
}


اگر از Macroable قبلا استفاده کردی بگو کجا اضافه کردی تا بقیه هم با این قابلیت بیشتر آشنا بشن 🔥

————————————————————

@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه ای php و لاراول
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍4
اگه هیچ روتی پیدا نشه، لاراول چی کار می‌کنه؟! 🤔

آیا تا حالا برات پیش اومده که کاربر آدرس اشتباهی رو وارد کنه و با صفحه‌ی خطای زشت 404 روبه‌رو بشه؟ 😩

اگه دوست داری توی چنین مواقعی یک صفحه‌ی اختصاصی، با ظاهر دلخواه خودت نمایش بدی، Route::fallback دقیقاً برای همینه!

🧩می دونید Route::fallback چیه؟

تو لاراول، این روت آخرین تیر ترکش ماست!

وقتی هیچ‌کدوم از مسیرهایی که تعریف کردی با URL درخواستی کاربر جور درنیاد، لاراول میاد سراغ fallback.

چطوری تعریفش کنیم؟

‍‍‍

use Illuminate\Support\Facades\Route;

Route::fallback(function () {
return response()->view('errors.custom-404', [], 404);
});
‍‍‍



در این مثال، اگر مسیر درخواست‌شده پیدا نشه، ویوی errors.custom-404 نمایش داده می‌شه که می‌تونه شامل یه پیام دوستانه، لینک برگشت به صفحه اصلی یا هر چیز دیگه‌ای باشه.

🌟 نکات مهم:

🔹حواستون باشه Route::fallback فقط باید یک بار تعریف بشه و همیشه باید در انتهای فایل route بیاد.
🔹 می‌تونی از کنترلر هم استفاده کنی به‌جای Closure
🔹 و یکی دیگه از خوبی هاش اینه که میتونی تمام ۴۰۴ ها رو هم حتی برای خودت لاگ بندازی



Route::fallback([ErrorController::class, 'notFound']);
‍‍‍


💬 حالا شما بگید:

آیا تا حالا از fallback route استفاده کردید؟ یا همیشه صفحه‌ی 404 پیش‌فرض لاراول رو دیدید؟ 😄

———————————————————————————
@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه‌ای php و لاراول

در کانال تلگرامی CodeFuse من سعی میکنم چالش هایی که باهاش روبرو می شوم رو به اشتراک بگذارم برای این که در کنار ما باشید و به‌روز باشید، به ما بپیوندید! 👇👇

https://t.me/codefuse1
👍14🔥2
🎯 یک قابلیت ناشناخته در لاراول که احتمالاً هیچ‌وقت امتحانش نکردی!

فرض کن دستور php artisan emails:send رو برای ارسال ایمیل اجرا کردی، اما یه نفر دیگه هم دقیقاً همون دستور رو هم‌زمان اجرا می‌کنه...

نتیجه؟ شاید دوبار ایمیل بره، شاید دیتابیس قفل شه، شاید فاجعه‌ای اتفاق بیفته 😬

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

🔐 معرفی Isolatable

با Isolatable می‌تونی مطمئن شی که یه دستور Artisan فقط یک بار در یک زمان اجرا بشه. یعنی اگر یکی در حال اجراست، دومی دیگه اجرا نمیشه.

چجوری استفاده کنیم؟

برای این کار می‌تونیم اینترفیس Illuminate\Contracts\Console\Isolatable رو روی کلاس دستورمون پیاده‌سازی کنیم

به شکل زیر :


use Illuminate\Console\Command;
use Illuminate\Contracts\Console\Isolatable;

class SendEmails extends Command implements Isolatable
{
protected $signature = 'emails:send {user}';

public function handle()
{
// SendEmails ...
}
}



نکته مهم : برای استفاده از این ویژگی، اپلیکیشن شما باید یکی از درایورهای کش زیر را به عنوان درایور پیش‌فرض کش استفاده کند:

memcached، redis، dynamodb، database، file یا array.

مثلا در همین کد که در تصویر پیوست هست

بعد از پیاده سازی کد حالا فقط کافیه دستور رو با --isolated اجرا کنی:


php artisan emails:send 1 --isolated



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


ترفندهای پیشرفته‌تر

🔸 شخصی‌سازی قفل بر اساس پارامتر

مثلاً برای اینکه قفل فقط برای هر کاربر باشه:


public function isolatableId(): string
{
return 'email-user-' . $this->argument('user');
}


🔸 تنظیم زمان پایان قفل:


public function isolationLockExpiresAt(): \DateInterval
{
return new \DateInterval('PT5M'); // قفل بعد از ۵ دقیقه آزاد میشه
}


🔸 تعیین کد خروجی در صورت اجرا نشدن:

با گزینه --isolated=کد

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

مثلاً اینو ببین:

php artisan emails:send 1 --isolated=22
‍‍‍‍
حالا اگه دستور درگیر قفل بود و اجرا نشد، عدد ۲۲ به عنوان نتیجه برمی‌گرده. اینطوری اگه داری با اسکریپت یا ابزار مانیتورینگ کار می‌کنی، راحت‌تر می‌فهمی چی شده

📌 اگه این پست برات مفید بود، بفرست برای دوستات تا اون ها با این قابلیت خفن آشنا بشن

سوالی هم داشتی همینجا بپرس، با کمال میل جواب می‌دم!

———————————————————————————
@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه‌ای php و لاراول

در کانال تلگرامی CodeFuse من سعی میکنم چالش هایی که باهاش روبرو می شوم رو به اشتراک بگذارم برای این که در کنار ما باشید و به‌روز باشید، به ما بپیوندید! 👇👇

https://t.me/codefuse1
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥21👏1👌1
چالش لاراولی : ⏱️ ۳ دقیقه زمان داری! خروجی این کد Laravel چیه؟ (و چرا؟)

سلام رفقا حالتون چطوره ؟

من علیرضام اینجاییم که باهم رشد کنیم، چیزای جدید یادبگیریم، به روز باشیم ، برای این که دلم برای گفتگو با هاتون تنگ شده گفتم بیام یک چالش درست کنم که کمی باهم گپ بزنیم

🎯 بریم سراغ چالش امروز


Route::get('/challenge', function () {
$data = collect([1, 2, 3, 4]);

$result = $data->filter(function ($item) {
return $item % 2 === 0;
})->map(function ($item) {
return $item * 2;
})->reduce(function ($carry, $item) {
return $carry + $item;
});

return $result;
});


✍️ خروجی این کد چیه؟ چرا؟ توی کامنت‌ها بنویس 👇

در کد فوق filter / map / reduce چه کاری رو انجام میدهند ؟

تحلیل این گونه کدها از پاسخ صحیح هم مهم تر است

———————————————————————————
@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه‌ای php و لاراول
👍7
🌍تا حالا با Asymmetric Visibility توی PHP 8.4 کار کردین؟

اگه با PHP کد می‌زنی، این قابلیت جدید توی نسخه 8.4 خیلی به کارت میاد!

یکی از قابلیت‌های جدید و دوست‌داشتنی در PHP 8.4 اینه که می‌تونی سطح دسترسی خواندن (read) و نوشتن (write) روی یک ویژگی (property) رو جدا جدا مشخص کنی.

توی نسخه‌های قبلی PHP فقط می‌تونستی بگی یه پراپرتی public باشه یا private یا protected. یعنی:

اگه public باشه => از بیرون کلاس هم می‌تونن بخونن و هم تغییرش بدن

اگه private باشه => فقط از داخل کلاس قابل دسترسه، حتی خوندنش هم از بیرون ممکن نیست

این موضوع باعث می‌شد اگه بخوای یه پراپرتی فقط قابل خوندن باشه، مجبوری بشی یه متد جداگانه مثل getVersion() بنویسی.

ولی حالا توی PHP 8.4 می‌تونی:

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

و فقط از درون کلاس اجازه‌ی تغییرش وجود داشته باشه.

🧪بزارید با یک مثال واقعی - قبل از PHP 8.4 رو باهم ببینیم :

class PhpVersion

{
private string $version = '8.3';

public function getVersion(): string
{

return $this->version;
}

public function increment(): void

{
[$major, $minor] = explode('.', $this->version);
$minor++;
$this->version = "{$major}.{$minor}";
}

}


که به این صورت هم استفاده میکردیم
‍‍‍
$php = new PhpVersion();

echo $php->getVersion();


و برای گرفتن مقدار version باید حتما از getVersion استفاده میکردیم

و ایجاد این Getter ها حجم کد مون رو زیاد تر میکرد و در php 8.4 یک ویژگی جدید اومده که کدهامون تمیز تر باشه


حالا در PHP 8.4:

class PhpVersion

{

public private(set) string $version = '8.4';

public function increment(): void

{
[$major, $minor] = explode('.', $this->version);
$minor++;
$this->version = "{$major}.{$minor}";
}

}


اینجا داریم یه ویژگی به اسم version تعریف می‌کنیم که:

مقدار public یعنی: از بیرون کلاس دسترسیش باز هست و میتونی بخونیش و بهش دسترسی داشته باشی

و مقدار private(set) یعنی : از بیرون نمی‌تونی مقدارشو تغییر بدی، ولی از داخل کلاس قابل تغییر هست

مثال از استفاده آن :

$php = new PhpVersion();

echo $php->version;


ولی از داخل کلاس هنوز می‌تونه مقداردهی بشه مثل متد increment() بالا

بیرون کلاس اگر تلاش کنید مقدارش رو تغییر بدید مثل زیر :

‍‍‍
php
php
$php = new PhpVersion();
$php->version = 8
‍‍‍‍‍‍‍


خطا دریافت میکنید چون از بیرون کلاس امکان تغییر اون بسته شده است

📌 نتیجه: دیگه لازم نیست برای یه ویژگی فقط-خواندنی، متد getX() بنویسی. کدت هم تمیزتره، هم امن‌تره، هم خواناتر.

❤️ اگه این آموزش برات مفید بود: لایک کن، برای رفقات بفرست

و اگه سوالی داری همینجا بپرس، جواب می‌دم با کمال میل! ✌️

📣 آموزش‌های بیشتر در: @codefuse1 – کُدفیوز | نکات حرفه‌ای PHP و لاراول به زبان ساده
👍12👏1
آیا از ویژگی جدید #[\Deprecated] در PHP 8.4 خبر داری؟ 🚨

تو نسخه‌های قبل از PHP 8.4 فقط می‌تونستیم با کامنت @deprecated هشدار بدیم که یه تابع یا متد دیگه قدیمی شده. ولی هیچ اخطار واقعی موقع اجرا داده نمی‌شد 😐

اما حالا در PHP 8.4 با ویژگی #[\Deprecated] خود PHP این کارو به‌صورت واقعی و قابل اجرا انجام می‌ده 💥

بزارید بایک مثال این رو باهم بررسی کنیم:

فرض کن قبلاً تو یه پروژه‌ی فروشگاه آنلاین، از متدی به اسم applyDiscountManually() استفاده می‌کردی ولی حالا یه سیستم جدید و امن‌تر ساختی به اسم applyDiscountWithRules().

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

📌 کد قبل از PHP 8.4:


class OrderService {
/**
* @deprecated از applyDiscountWithRules استفاده کن
*/
public function applyDiscountManually($amount) {
// منسوخ شده
return $amount - 10000;
}

public function applyDiscountWithRules($amount) {
// منطقی و امن
return $amount * 0.9;
}
}
$order = new OrderService();
echo $order->applyDiscountManually(100000); // اخطاری نمی‌گیری!


📌 حالا در PHP 8.4:


class OrderService {
#[\Deprecated(
message: "از applyDiscountWithRules استفاده کن",
since: "8.4"
)]
public function applyDiscountManually($amount) {
return $amount - 10000;
}

public function applyDiscountWithRules($amount) {
return $amount * 0.9;
}
}
$order = new OrderService();
echo $order->applyDiscountManually(100000);
// ⚠️ Deprecated: Method applyDiscountManually is deprecated since 8.4...


به همین راحتی با #[\Deprecated] هم مستندسازی می‌کنی، هم در زمان اجرا هشدار واقعی می‌دی. این یعنی کد حرفه‌ای‌تر، تیم منسجم‌تر، و کمتر شدن باگ‌هایی که از استفاده از توابع قدیمی به‌وجود میان! 👨‍💻
👍10
چطور جلوی Double Transaction یا Duplicate Payment رو میگیری؟

👀 خیلی کنجکاوم بدونم شما چه راهکاری برای این سناریو پیشنهاد میدید؟

✍🏻 نظرتون رو بنویسید...

💬 حالا تجربه خودم:

ابتدا بزارید یک سناریو رو باهم در نظر داشته باشیم

سناریو اینه که فرض کن توی یه اپلیکیشن کاربر میخواد کیف پول خودش رو شارژ کنه.

مثلاً میخواد ۵۰۰ هزار تومن شارژ کنه. ولی ممکنه این بلاها سر سیستم بیاد:

کاربر دو بار روی دکمه "پرداخت" کلیک کنه ، اینترنت قطع و وصل بشه و کاربر صفحه پرداخت رو دوباره لود کنه.

عمداً درخواست پرداخت رو تو چند تب یا ابزار Postman تکرار کنه.

اگه مراقب نباشیم، همون مبلغ چندبار به کیف پول اضافه میشه!

فاجعه چیه؟ کاربر ۵۰۰ هزار تومن پرداخت کرده ولی موجودیش ۱ میلیون شده! 😵

توی پروژه‌های واقعی که روشون کار کردم، برای جلوگیری از این مشکل معمولاً چند روش ترکیبی استفاده کردم:

ایجاد یک transaction_token یکتا برای هر پرداخت و چک کردن اینکه فقط یکبار مصرف بشه.

قفل کردن ردیف دیتابیس (Row Locking) با lockForUpdate هنگام آپدیت موجودیت حساس (مثل سفارش یا کیف پول).

استفاده از صف (Queue) برای پردازش پرداخت‌ها و جلوگیری از شرایط مسابقه (Race Condition).

و البته، غیرفعال کردن دکمه پرداخت در فرانت‌اند بلافاصله بعد از کلیک (که بیشتر جنبه کمکی داره).

در نهایت همیشه حواسمون هست که هیچ وقت به کاربر اعتماد نکنیم و لایه‌های حفاظتی قوی سمت سرور پیاده کنیم.

یک نمونه کد ساده برای جلوگیری از این مشکل :

‍‍
php
public function rechargeWallet(Request $request)
{
$transactionId = $request->input('transaction_id');
$amount = $request->input('amount');

DB::transaction(function () use ($transactionId, $amount) {
if (WalletTransaction::where('transaction_id', $transactionId)->exists()) {
throw new \Exception('Duplicate transaction detected.');
}

WalletTransaction::create([
'user_id' => auth()->id(),
'transaction_id' => $transactionId,
'amount' => $amount,
'type' => 'recharge',
]);

$wallet = Wallet::where('user_id', auth()->id())
->lockForUpdate()
->firstOrFail();

$wallet->balance += $amount;
$wallet->save();
});

return response()->json(['success' => true]);
}


اما lockForUpdate چی کار میکنه ؟

وقتی توی لاراول (یا کلاً دیتابیس) از lockForUpdate استفاده می‌کنی، داری به دیتابیس میگی:

«این رکوردی که الان دارم میخونم، تا وقتی تراکنشم کامل نشده، هیچ کس دیگه حق نداره تغییرش بده یا حتی بخونه و تغییر بده.»

———————————————————————————
@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه‌ای php و لاراول

در کانال تلگرامی CodeFuse من سعی میکنم چالش هایی که باهاش روبرو می شوم رو به اشتراک بگذارم برای این که در کنار ما باشید و به‌روز باشید، به ما بپیوندید! 👇👇

https://t.me/codefuse1
👍8
🚀 چطور با terminable middleware در لاراول فعالیت‌های کاربران را پیگیری کنیم؟ 🚀


تا حالا با متد terminate در middleware کار کردید ؟ ، اگر کار کردید خوشحال میشوم بگید کجا و چه کاربرد هایی برایتان داشته تا بقیه هم استفاده کنند اما اگر آشنا نیستید با من همراه باشید

فرض کنید در یک وب‌سایت یا برنامه، نیاز دارید که آخرین فعالیت هر کاربر (مثلاً ورود یا خروج از سیستم، بازدید از صفحات خاص و ...) را ذخیره کنید تا بتوانید گزارشاتی از رفتار کاربران در طول روز ایجاد کنید. در این حالت می‌توانیم از terminable middleware برای ثبت فعالیت‌های کاربران پس از هر درخواست استفاده کنیم.


<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;

class TrackUserActivity
{
public function handle(Request $request, Closure $next)
{
return $next($request);
}

public function terminate(Request $request, $response)
{
if (Auth::check()) {
$user = Auth::user();
$user->last_activity_at = now();
$user->save();

Log::info("User {$user->id} activity recorded at {$user->last_activity_at}");
}
}
}



در این مثال، ما یک middleware به نام TrackUserActivity داریم که پس از هر درخواست، آخرین زمان فعالیت کاربر را در دیتابیس به‌روز می‌کند. این کار به شما این امکان را می‌دهد که آخرین زمان فعالیت هر کاربر را ذخیره کنید و از آن برای نمایش گزارشات فعالیت یا مدیریت وضعیت کاربران استفاده کنید.

و بعد میتونید کاری کنید که به صورت عمومی در تمامی route ها اعمال بشه یا این که در route هایی که میخواهید دستی اعمال کنید

این روش به شما کمک می‌کند تا هر بار که کاربر وارد یک صفحه شود، زمان آخرین فعالیت او در سیستم ذخیره شود و شما بتوانید رفتار و فعالیت‌های آن‌ها را پیگیری کنید.

———————————————————————————
@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه‌ای php و لاراول

در کانال تلگرامی CodeFuse من سعی میکنم چالش هایی که باهاش روبرو می شوم رو به اشتراک بگذارم برای این که در کنار ما باشید و به‌روز باشید، به ما بپیوندید! 👇👇

https://t.me/codefuse1
👍62
🧠 وقتی هوش مصنوعی بهتر از من کد می‌نویسه، من باید چیکار کنم؟

📌 تجربه‌ی من از Vibe Coding با Laravel 👇

چند وقتیه با ابزارهایی مثل GPT، Copilot و Cloud.ai کار می‌کنم، و راستش بعضی وقتا حس می‌کنم دارم به یه دستیار خیلی حرفه‌ای تکیه می‌کنم 😅

👨‍💻 یه مثال واقعی از تجربه‌م:

لازم داشتم یه سیستم لاگ‌گیری ساده برای تغییر وضعیت محصولات توی پروژه‌ای با Laravel بنویسم.

📝 فقط اینو برای Cloud.ai نوشتم:

"In Laravel, create a service that logs changes to the is_active field of a product. Include the user ID, previous value, new value, and timestamp."

کمتر از ۳۰ ثانیه بعد بهم تحویل داد:

Service class کامل با dependency injection
Event/Listener برای ProductUpdated
ثبت دقیق تغییرات در یک جدول جداگانه
migration + مدل + حتی تست اولیه با pest!

و حالا سوالی که ذهنم رو درگیر کرد:
اگه AI داره این‌قدر سریع و دقیق کد می‌نویسه، من قراره چه نقشی داشته باشم؟

🧩 جواب من:

من هنوزم اون کسی‌ام که باید منطق مسئله رو بفهمه، تصمیم بگیره چی لازمه، معماری رو بچینه، و خروجی رو validate کنه.

🛠 کدی که AI می‌نویسه، مثل آجره. اما ساختن خونه هنوز با منه.

🎯 الان تمرکز من روی:
– نوشتن Promptهای دقیق و واضح
– Refactor و بهینه‌سازی کدها
– طراحی درست سرویس‌ها و کنترل کیفیت

تو چی فکر می‌کنی؟
🤖 Cloud.ai یا ابزار های هوش مصنوعی کدوم رو تست کردی و نتیجه اش چی بوده؟
🤯 شده یه بار نتیجه‌ای بگیری که خودت باورش نشه؟

منتظرم نظرتو بدونم 👇

(اگه مفید بود بفرست واسه یکی دیگه از رفقا 👨‍💻)

———————————————————————————
@codefuse1 | کُدفیوز :‌ آموزش و نکات حرفه‌ای php و لاراول

در کانال تلگرامی CodeFuse من سعی میکنم چالش هایی که باهاش روبرو می شوم رو به اشتراک بگذارم برای این که در کنار ما باشید و به‌روز باشید، به ما بپیوندید! 👇👇

https://t.me/codefuse1
9👏5👎1
🔥 چرا یکی با هوش مصنوعی چند برابر جلو می‌افته و یکی آخرش میگه «به درد نمی‌خوره»؟

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

توی این مدت مدل‌ها و ابزارهای زیادی رو امتحان کردم، اکانت گرفتم، از API استفاده کردم و یه بخش از چیزهایی که یاد گرفتم هم حاصل آزمون‌وخطا و هزینه واقعی بوده.

بعضی چیزها رو از مستندات یاد گرفتم،
بعضی‌ها رو از تجربه،
و بعضی‌ها رو هم از صورتحساب API! 😅

یکی از مهم‌ترین چیزهایی که فهمیدم اینه:

📌 داشتن بهترین هوش مصنوعی، لزوماً به معنی گرفتن بهترین نتیجه نیست.

هنوز زیاد می‌بینم کسی نتیجه خوبی نمی‌گیره، پرامپتش رو عوض می‌کنه، طولانی‌ترش می‌کنه، توضیح بیشتری می‌ده و در نهایت میگه:

«هوش مصنوعی هنوز به درد کار واقعی نمی‌خوره.»

در حالی که شاید مشکل اصلاً پرامپت نبوده.

شاید از اول مدل اشتباهی رو برای اون کار انتخاب کرده.

پرامپت هنوز مهمه، ولی دیگه تمام بازی نیست.

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

برای همین من این روزها بیشتر از اینکه دنبال «پرامپت جادویی» باشم، به این سؤال‌ها فکر می‌کنم:

🔹 برای این کار چه مدلی مناسبه؟

🔹 چه میزان توان استدلالی یا Effort لازم داره؟

🔹 واقعاً چقدر Context باید در اختیارش بذارم؟

🔹 چه ابزارهایی باید در اختیارش باشه؟

🔹 چه Skillهایی واقعاً لازمه؟

🔹 و اصلاً این کار نیاز به Agent داره یا نه؟

اینجاست که تفاوت نتیجه‌ها شروع میشه.

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

از اون طرف، ارزون‌ترین مدل هم همیشه اقتصادی‌ترین انتخاب نیست.

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

من خودم بخشی از این موضوع رو با تست مدل‌های مختلف و البته سوزوندن چندصد دلار API یاد گرفتم. 😅

احتمالاً خوندن این تجربه خیلی ارزون‌تر از تکرار کردنشه!

⚙️ بعد از انتخاب مدل، بحث Effort میاد وسط.

یه تغییر ساده توی کد با بررسی معماری یک سیستم بزرگ یکی نیست.

قرار نیست برای هر دو، مدل رو با یک تنظیم و یک میزان استدلال اجرا کنیم.

گاهی کیفیت مهم‌تره، گاهی سرعت و گاهی هزینه.

به نظرم انتخاب درست بین این‌ها خودش تبدیل شده به بخشی از مهارت کار با هوش مصنوعی.

🧩 بعد می‌رسیم به Skillها.

به‌جای اینکه هر بار از صفر توضیح بدی:

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

می‌تونی روش انجام اون کار رو تبدیل کنی به یه Skill که دوباره قابل استفاده باشه.

مثلاً برای بازبینی کد، تست، مستندسازی، ساخت API یا حتی قوانین اختصاصی پروژه خودت.

حتی لازم نیست همه‌شون رو از صفر بسازی؛ می‌تونی از Skillهای آماده شروع کنی، تغییرشون بدی و کم‌کم نسخه مخصوص خودت رو بسازی.

اما اینجا یه دام وجود داره:

هرچی Skill بیشتر، بهتر؟

به نظرم نه.

وقتی تعداد Skillها زیادی میشه، یه جایی شبیه وابستگی‌های پروژه میشن؛ اول همه‌شون مفید به نظر می‌رسن، چند ماه بعد هیچ‌کس مطمئن نیست حذف کدوم یکی قراره چه چیزی رو منفجر کنه. 😄

هنر اصلی داشتن Skill زیاد نیست؛ داشتن Skill درست برای کار درسته.

و تازه بعد از این می‌رسیم به قسمت‌های جذاب‌تر:

🤖 عامل‌های هوش مصنوعی (AI Agents)
🧠 حافظه (Memory)
🛠 ابزارها (Tools)
زمان‌بندی (Schedule)
🔄 گردش‌کارهای هوشمند و تصمیم‌گیر (Agentic Workflows)

اینجا دیگه هوش مصنوعی فقط جواب سؤال نمی‌ده؛ می‌تونه کار رو جلو ببره، نتیجه رو بررسی کنه و برای مرحله بعد تصمیم بگیره.

و دقیقاً از همین‌جا سؤال‌های جدی‌تر شروع میشن:

🔹 تفاوت Skill، Agent و Memory دقیقاً چیه؟

🔹 آیا Context بیشتر همیشه نتیجه بهتری می‌ده؟

🔹 عامل هوش مصنوعی چه زمانی واقعاً مفیده و چه زمانی فقط داره توکن مصرف می‌کنه؟ 😅

🔹 وقتی سیستم خودش می‌تونه تصمیم بگیره، ابزارهایی مثل n8n کجای داستان قرار می‌گیرن؟

این سری قراره بیشتر از جنس تجربه باشه تا ترجمه مستندات.

📌 توی قسمت‌های بعد می‌ریم سراغ:

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

🔹 تنظیم درست Effort و کنترل هزینه

🔹 ساخت و انتخاب Skillهای خوب

🔹 تفاوت Skill، Agent و Memory

🔹 مدیریت درست Context

🔹 اینکه Agent دقیقاً کجا ارزش استفاده داره

🔹 مقایسه n8n با گردش‌کارهای Agentic

🔹 و در نهایت ترکیبی که خودم برای کارهای مختلف استفاده می‌کنم

و شاید سؤال اصلی کل این سری همین باشه:

👀 چرا دو نفر که به یک هوش مصنوعی دسترسی دارن، می‌تونن دو نتیجه کاملاً متفاوت بگیرن؟
6