<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های آرش فدائی</title><link>https://virgool.ir/feed/@m_28031645</link><description>توسعه‌دهنده ارشد وب و متخصص PHP</description><language>fa</language><pubDate>2026-11-11 18:50:07</pubDate><image><url>https://files.virgool.ir/upload/users/3359958/avatar/RgzQr1.png</url><title>آرش فدائی</title><link>https://virgool.ir/@m_28031645</link></image><item><title>چگونه در Cursor یک Skill تعریف کنیم؟</title><link>https://virgool.ir/@m_28031645/چگونه-در-cursor-یک-skill-تعریف-کنیم-omxpltsdqhnr</link><description>Skill چیست؟Skill یک راهنمای Markdown است که Agent می‌تواند آن را پیدا کرده و در صورت نیاز اجرا کند.Skillها کاربردهای مختلفی دارند، از جمله:Workflowهای پروژه: مانند /article، چک‌لیست Deploy یا Release Notesفرآیندهای مربوط به ابزارها: مانند Figma MCP، اسکریپت‌های CLI یا APIهای داخلیاستانداردهای تیم: مانند قوانین Commit، Code Review و بررسی‌های امنیتیSkillها معمولاً در یکی از این مسیرها قرار می‌گیرند:.cursor/skills/&#xA;در این حالت Skill داخل خود پروژه قرار دارد و همراه Repository با سایر اعضای تیم به اشتراک گذاشته می‌شود.یا در Personal Cursor Skills Directory قرار می‌گیرند که در پروژه‌های مختلف برای خود شما قابل استفاده هستند.ساختار فایل SKILL.mdهر Skill به یک YAML Frontmatter در ابتدای فایل و مجموعه‌ای از دستورالعمل‌ها نیاز دارد.برای مثال:---&#xA;name: blog-pro-content-automation&#xA;description: &gt;-&#xA;  Draft-first English content automation for Blog Pro via WordPress REST API.&#xA;  Use when the user runs /article, /prompt, /tutorial, or asks to create drafts.&#xA;---&#xA;&#xA;# Blog Pro Content Automation&#xA;&#xA;Hard rules:&#xA;1. Default status is always draft.&#xA;2. Never publish unless the user runs /publish-now.&#xA;&#xA;## Workflow&#xA;1. Generate English JSON&#xA;2. Validate with the CLI&#xA;3. Create a WordPress draft&#xA;در ادامه اجزای اصلی را بررسی می‌کنیم.nameنام Skill یک شناسه کوتاه و با فرمت kebab-case است.بهتر است نام آن پایدار و مشخص باشد، چون ممکن است فایل‌ها یا مستندات دیگر پروژه به آن ارجاع دهند.برای مثال:name: blog-pro-content-automation&#xA;یا:name: my-release-checklist&#xA;descriptiondescription در واقع نقش Trigger یا محرک Skill را دارد.Cursor از این توضیحات استفاده می‌کند تا تشخیص دهد چه زمانی باید Skill موردنظر را فعال کند.بنابراین Description باید مشخص کند:این Skill چه کاری انجام می‌دهد؟چه زمانی باید استفاده شود؟کاربر معمولاً چه عبارت‌ها یا Commandهایی را وارد می‌کند؟برای مثال:description: &gt;-&#xA;  Run the project release checklist before tagging a version.&#xA;  Use when the user says release, ship, tag, or prepare a production deploy.&#xA;این توضیح بسیار بهتر از یک عبارت کلی مانند «کمک به Release پروژه» است.آموزش مرحله‌به‌مرحله: اولین Skill خود را بسازیدمرحله ۱: ساخت پوشهابتدا پوشه مربوط به Skill را ایجاد کنید:mkdir -p .cursor/skills/my-release-checklist&#xA;ساختار پروژه شما در این مرحله چیزی شبیه این خواهد بود:.cursor/&#xA;└── skills/&#xA;    └── my-release-checklist/&#xA;مرحله ۲: ایجاد SKILL.mdحالا داخل پوشه Skill یک فایل به نام SKILL.md ایجاد کنید.محتوای اولیه می‌تواند به شکل زیر باشد:---&#xA;name: my-release-checklist&#xA;description: &gt;-&#xA;  Run the project release checklist before tagging a version.&#xA;  Use when the user says release, ship, tag, or prepare a production deploy.&#xA;---&#xA;&#xA;# Release checklist&#xA;&#xA;1. Confirm main is green.&#xA;2. Update CHANGELOG.&#xA;3. Bump version in package/theme metadata.&#xA;4. Do not push tags unless the user asks.&#xA;در این مثال، Skill به Cursor می‌گوید قبل از آماده‌سازی Release چه مراحلی باید انجام شود.مرحله ۳: Description را دقیق بنویسیدیکی از مهم‌ترین بخش‌های یک Skill، Description آن است.ضعیف:Helps with releases.&#xA;این توضیح بیش از حد کلی است و اطلاعات کافی برای تشخیص زمان استفاده از Skill به Cursor نمی‌دهد.قوی:Run the project release checklist before tagging a version.&#xA;Use when the user says release, ship, tag, or prepare a production deploy.&#xA;در این نسخه مشخص شده:Skill چه کاری انجام می‌دهد.چه زمانی باید فعال شود.چه عباراتی می‌توانند باعث فعال شدن آن شوند.مرحله ۴: قوانین قابل اجرا بنویسیدقوانین Skill باید Actionable باشند؛ یعنی Agent بتواند بر اساس آن‌ها یک اقدام مشخص انجام دهد.به‌جای جملات کلی، از فعل و Constraint استفاده کنید.مثلاً:«همیشه Draft ایجاد کن و هرگز Publish نکن.»«قبل از اجرای CLI، فایل workflow.md را بخوان.»«اگر Duplicate Detection هشدار داد، متوقف شو و از کاربر سؤال کن.»برای مثال:Always create drafts, never publish.&#xA;یا:Read workflow.md before calling the CLI.&#xA;از متن‌های انگیزشی یا توضیحات غیرضروری خودداری کنید.Agent به Procedure و Constraint نیاز دارد، نه جملات انگیزشی.مرحله ۵: به فایل‌های پشتیبان ارجاع دهیدبهتر است فایل SKILL.md بیش از حد طولانی نشود.اگر دستورالعمل‌ها و جزئیات پروژه زیاد هستند، آن‌ها را در فایل‌های جداگانه قرار دهید.برای مثال:.cursor/skills/blog-pro-content-automation/&#xA;  SKILL.md&#xA;  workflow.md&#xA;  content-types.md&#xA;  templates/&#xA;سپس داخل SKILL.md مشخص کنید Agent در هر مرحله باید کدام فایل را باز کند.برای مثال:Before generating content, read content-types.md.&#xA;Before calling the WordPress CLI, read workflow.md.&#xA;این ساختار باعث می‌شود Skill اصلی کوتاه، قابل نگهداری و قابل فهم باقی بماند.الگوهای مناسب برای ساخت Skillچند الگوی کاربردی وجود دارد که می‌توانند کیفیت Skillهای شما را بهتر کنند.۱. Command Mapیک جدول برای مشخص کردن Commandهای مختلف ایجاد کنید.برای مثال:Commandکاربرد/articleایجاد پیش‌نویس مقاله/promptایجاد محتوای Prompt/tutorialایجاد آموزش/publish-nowانتشار محتوا۲. Hard Rulesقوانینی را که تحت هیچ شرایطی نباید نقض شوند، به‌صورت واضح و شماره‌گذاری‌شده بنویسید.مثلاً:1. Never publish automatically.&#xA;2. Always validate generated JSON.&#xA;3. Never overwrite existing content without confirmation.&#xA;۳. Short Pathمسیر اصلی انجام کار را کوتاه و مرحله‌به‌مرحله مشخص کنید.مثلاً:1. Read the content type.&#xA;2. Generate the content.&#xA;3. Validate the output.&#xA;4. Create a draft.&#xA;5. Return the draft ID.&#xA;۴. Failure Policyمشخص کنید اگر مشکلی اتفاق افتاد Agent چه کاری باید انجام دهد.مثلاً:If authentication fails, stop and ask the user to reconnect WordPress.&#xA;یا:If validation fails, do not create the draft.&#xA;۵. Output Formatمشخص کنید Agent در پایان کار دقیقاً چه اطلاعاتی را باید به کاربر نمایش دهد.مثلاً:At the end, report:&#xA;- Content type&#xA;- Draft ID&#xA;- WordPress URL&#xA;- Validation status&#xA;این کار باعث می‌شود خروجی Skillها همیشه قابل پیش‌بینی و یکدست باشد.اشتباهات رایجDescription بیش از حد کلیاگر Description مبهم باشد، ممکن است Skill در زمان مناسب فعال نشود.قرار دادن کل مستندات شرکت در یک SKILL.mdفایل SKILL.md نباید تبدیل به یک Wiki چندصدصفحه‌ای شود.دستورالعمل‌های مرتبط را در فایل‌های جداگانه نگهداری کنید.وجود قوانین متناقضبرای مثال:Always commit changes.&#xA;در حالی که جای دیگری نوشته‌اید:Never commit unless the user asks.&#xA;این تضاد باعث رفتار غیرقابل پیش‌بینی Agent می‌شود.ننوشتن نمونه‌هایی از عبارت‌های کاربراگر انتظار دارید Skill با عباراتی مثل:release&#xA;ship&#xA;prepare production deploy&#xA;فعال شود، بهتر است این عبارات را در Description مشخص کنید.ایجاد معماری جدید توسط SkillSkill نباید صرفاً به این دلیل که Agent یک روش را بهتر می‌داند، معماری جدیدی برای پروژه ایجاد کند.اولویت باید همیشه دنبال کردن ساختار و معماری موجود Repository باشد.Skill خود را تست کنیدبعد از ساخت Skill، آن را آزمایش کنید.۱. یک Chat جدید در پروژه باز کنیدبهتر است تست را در یک Session جدید انجام دهید.۲. از عبارتی که در Description نوشته‌اید استفاده کنیدمثلاً:Prepare the project for release.&#xA;۳. بررسی کنید Agent فایل SKILL.md را می‌خواندقبل از اجرای Workflow، مطمئن شوید Cursor Skill مربوطه را پیدا کرده و دستورالعمل‌های آن را دنبال می‌کند.۴. اگر Skill فعال نشد، Description را اصلاح کنیدDescription را دقیق‌تر کنید و Triggerهای واقعی که کاربران استفاده می‌کنند به آن اضافه کنید.</description><category>آرش فدائی</category><author>آرش فدائی</author><pubDate>Sun, 30 Aug 2026 23:14:47 +0330</pubDate></item><item><title>چگونه Cursor را به Figma متصل کنیم!</title><link>https://virgool.ir/@m_28031645/چگونه-cursor-را-به-figma-متصل-کنیم-ut2sickszfwt</link><description>چگونه Cursor را به Figma متصل کنیم!چه چیزهایی نیاز دارید؟برای شروع به موارد زیر نیاز دارید:Cursor با فعال بودن پلاگین Figma یا سرور MCP مربوط به Figmaیک حساب Figma با دسترسی به فایل طراحی موردنظریک پروژه محلی؛ برای مثال WordPress Theme، پروژه Laravel/Vue/React یا HTML/CSS سادهآدرس فایل Figma؛ اگر قصد دارید یک فریم مشخص را انتخاب کنید، بهتر است URL شامل node-id باشد.مرحله ۱: احراز هویت Figma در Cursorابتدا باید اتصال Figma را در Cursor برقرار کنید.Cursor را باز کنید و مطمئن شوید Figma MCP Server در دسترس است.اگر ابزارها با خطای احراز هویت مواجه شدند، فرایند Authentication مربوط به Figma را که نمایش داده می‌شود تکمیل کنید.دسترسی را با یک بررسی ساده تأیید کنید؛ برای مثال از Cursor بخواهید حساب Figma متصل‌شده را بررسی و تأیید کند.بدون انجام احراز هویت، حتی اگر Promptهای شما کاملاً صحیح باشند، عملیات خواندن یا نوشتن اطلاعات طراحی با خطا مواجه خواهد شد.مرحله ۲: دو مسیر اصلی اتصال Figma و Cursor را بشناسیدبه‌طور کلی دو گردش‌کار مهم وجود دارد:Design → Code: گرفتن یک فریم از Figma و پیاده‌سازی آن در پروژهCode → Design: ارسال ساختار یک صفحه یا کامپوننت از کد به Figma برای بررسی و بازبینیدر بیشتر پروژه‌های طراحی وب، معمولاً کار را با مسیر Design → Code شروع می‌کنید.مرحله ۳: پیاده‌سازی Design → Code به روش صحیحزمانی که URL مربوط به یک فایل Figma را در Cursor قرار می‌دهید، باید اطلاعات زیر را از آن استخراج کنید:مقدار fileKey از بخش /design/:fileKey/...مقدار nodeId از پارامتر node-id=1-2در node-id باید خط تیره (-) را به دونقطه (:) تبدیل کنید؛ بنابراین:1-2&#xA;به:1:2&#xA;تبدیل می‌شود.سپس می‌توانید از Cursor بخواهید همان Node را در پروژه پیاده‌سازی کند.یک Prompt مناسب می‌تواند چیزی شبیه این باشد:Implement this Figma frame in our existing project.&#xA;URL: https://www.figma.com/design/FILE_KEY/Name?node-id=12-34&#xA;&#xA;Rules:&#xA;- Reuse existing components and CSS variables&#xA;- Match spacing and typography from the design&#xA;- Do not invent a parallel design system&#xA;- Keep the change limited to the landing hero section&#xA;در پشت صحنه، Cursor باید ابتدا Skill مربوط به Design-to-Code را بارگذاری کند و سپس ابزارهای دریافت Design Context را برای Node موردنظر اجرا کند.نکته مهم این است که Markup و کدی که از طراحی دریافت می‌کنید را به‌عنوان Reference در نظر بگیرید، نه کدی که بدون بررسی مستقیماً وارد Production کنید.مرحله ۴: از Design Tokenها و Componentهای موجود پروژه استفاده کنیداگر وب‌سایت یا اپلیکیشن شما از قبل دارای موارد زیر است:متغیرهای CSS مانند:--color-accent&#xA;کامپوننت‌های آماده مانند Button، Card و Sectionسیستم Grid و Layout مشخصبه Cursor بگویید استایل‌های Figma را با همین Primitiveهای موجود در پروژه تطبیق دهد.این کار اهمیت زیادی دارد؛ چون از ایجاد یک Design System جداگانه و یک‌بارمصرف توسط AI جلوگیری می‌کند؛ سیستمی که بعداً ممکن است با ساختار اصلی Theme یا پروژه شما تداخل داشته باشد.مرحله ۵: پروژه را بخش‌به‌بخش پیاده‌سازی کنیدبهتر است از Cursor نخواهید کل یک وب‌سایت مارکتینگ را در یک مرحله پیاده‌سازی کند.به‌جای آن، پروژه را به بخش‌های کوچک‌تر تقسیم کنید:HeroFeature GridPricingFooterبعد از پیاده‌سازی هر بخش، موارد زیر را بررسی کنید:رفتار Responsiveدسترسی‌پذیری (Accessibility)سازگاری با ساختار فعلی پروژهنام‌گذاری Classها مطابق Convention پروژهاستفاده صحیح از Componentهای موجوداین روش باعث می‌شود کنترل بیشتری روی خروجی AI داشته باشید و پیدا کردن مشکلات نیز بسیار ساده‌تر شود.مرحله ۶: همگام‌سازی اختیاری Code → Figmaگاهی اوقات اعضای تیم یا Stakeholderها ترجیح می‌دهند طراحی را به‌جای محیط Staging، مستقیماً در Figma بررسی کنند.در چنین شرایطی می‌توانید از Cursor بخواهید:ابتدا Design System موجود را جست‌وجو و بررسی کند.بر اساس صفحه فعلی پروژه، یک Screen در Figma ایجاد یا به‌روزرسانی کند.به‌جای ایجاد عناصر کاملاً جدید، از Library Components و Variables موجود استفاده کند.این روش به‌خصوص قبل از یک Redesign بزرگ یا هنگام آماده‌سازی برای تحویل پروژه به تیم طراحی بسیار کاربردی است.بهترین روش‌هابرای اینکه اتصال Cursor و Figma بهترین نتیجه را داشته باشد، این نکات را رعایت کنید:همیشه URL دقیق فریم موردنظر را همراه با node-id ارائه کنید.Stack پروژه را مشخص کنید؛ مثلاً WordPress Theme، React، Blade و غیره.از Cursor بخواهید Tokenها و Componentهای موجود پروژه را مجدداً استفاده کند.بررسی نسخه Desktop و Mobile را به‌صورت صریح درخواست کنید.Assetهای تولیدشده و CSSهای یک‌بارمصرف را بدون دلیل وارد Global Styles نکنید.اشتباهات رایج۱. اتصال Figma بدون انجام Authenticationممکن است Figma به Cursor متصل شده باشد، اما تا زمانی که احراز هویت انجام نشود، ابزارهای MCP نمی‌توانند اطلاعات طراحی را به‌درستی دریافت کنند.۲. استفاده از کل صفحه به‌جای یک فریم مشخصاگر فقط به پیاده‌سازی Hero Section نیاز دارید، بهتر است Node مربوط به همان بخش را در اختیار Cursor قرار دهید، نه کل صفحه.۳. اجازه دادن به Cursor برای ساخت Design System جدیداگر پروژه شما از قبل رنگ‌ها، Typography، Buttonها و Componentهای مشخصی دارد، اجازه ندهید Cursor برای هر صفحه یک سیستم طراحی جدید ایجاد کند.۴. تبدیل مستقیم Prototype به CSSPrototypeهای Figma همیشه قرار نیست دقیقاً همان‌طور که طراحی شده‌اند در CSS پیاده‌سازی شوند.گاهی یک تعامل پیچیده در Prototype را می‌توان با یک ساختار ساده‌تر و استاندارد HTML/CSS/JavaScript پیاده‌سازی کرد.۵. نادیده گرفتن Accessibilityفقط شبیه بودن خروجی به Figma کافی نیست.مواردی مانند:Focus StateContrastSemantic HTMLHeading StructureKeyboard Navigationهم باید بررسی شوند.برای گرفتن بهترین نتیجه:یک‌بار احراز هویت کنید، فریم‌های مشخص را از Figma دریافت کنید، آن‌ها را با Design System واقعی پروژه تطبیق دهید و رابط کاربری را بخش‌به‌بخش پیاده‌سازی کنید.این روش باعث می‌شود استفاده از AI در فرآیند Design-to-Code به‌جای ایجاد کدهای شلوغ و غیرقابل‌کنترل، واقعاً به توسعه سریع‌تر و باکیفیت‌تر کمک کند.</description><category>آرش فدائی</category><author>آرش فدائی</author><pubDate>Sun, 30 Aug 2026 23:11:24 +0330</pubDate></item><item><title>نحوه استفاده از یک AI SDK در Laravel</title><link>https://virgool.ir/@m_28031645/نحوه-استفاده-از-یک-ai-sdk-در-laravel-fcnkkblixdzx</link><description>Laravel محیط بسیار مناسبی برای پیاده‌سازی قابلیت‌های هوش مصنوعی است؛ از تولید پیش‌نویس و خلاصه‌سازی تیکت‌ها گرفته تا دسته‌بندی پیام‌های پشتیبانی یا ساخت یک دستیار داخلی.اما چالش اصلی صرفاً ارسال یک درخواست به مدل هوش مصنوعی نیست. مسئله مهم این است که SDK را به شکلی در Laravel پیاده‌سازی کنیم که:کلیدهای API امن باقی بمانند.درخواست‌های طولانی باعث مسدود شدن کاربران نشوند.خروجی مدل قبل از استفاده یا ذخیره‌سازی اعتبارسنجی شود.خطاها و عملکرد درخواست‌ها به‌درستی ثبت و مدیریت شوند.در این آموزش، یک الگوی عملی برای استفاده از یک AI SDK در پروژه Laravel پیاده‌سازی می‌کنیم.چیزی که در این آموزش می‌سازیددر پایان، موارد زیر را خواهید داشت:یک AI Client که در Service Container لاراول ثبت شده است.یک سرویس سبک برای Chat و تولید متن.یک Job در Queue برای درخواست‌های زمان‌بر.اعتبارسنجی و Logging پایه برای خروجی مدل هوش مصنوعی.پیش‌نیازهابرای اجرای این مثال‌ها به موارد زیر نیاز دارید:Laravel 10 یا 11PHP 8.1 یا بالاترAPI Key از ارائه‌دهنده سرویس هوش مصنوعییک Queue Driver برای محیط Production مانند database یا redisمرحله ۱: ذخیره صحیح Secretهاهرگز API Key را مستقیماً داخل کد قرار ندهید.کلیدهای API باید در فایل .env قرار بگیرند و سپس از طریق فایل‌های config/ در اختیار برنامه قرار داده شوند:AI_API_KEY=&#xA;AI_BASE_URL=https://api.openai.com/v1&#xA;AI_MODEL=gpt-4.1-mini&#xA;AI_TIMEOUT=30&#xA;سپس در فایل config/services.php تنظیمات مربوط به سرویس AI را اضافه کنید:&#39;ai&#39; =&gt; [&#xA;    &#39;key&#39; =&gt; env(&#39;AI_API_KEY&#39;),&#xA;    &#39;base_url&#39; =&gt; env(&#39;AI_BASE_URL&#39;),&#xA;    &#39;model&#39; =&gt; env(&#39;AI_MODEL&#39;, &#39;gpt-4.1-mini&#39;),&#xA;    &#39;timeout&#39; =&gt; (int) env(&#39;AI_TIMEOUT&#39;, 30),&#xA;],&#xA;به این ترتیب، اطلاعات حساس مستقیماً داخل سورس‌کد قرار نمی‌گیرند و می‌توانید تنظیمات مربوط به مدل، آدرس API و Timeout را از طریق Environment مدیریت کنید.مرحله ۲: نصب و ثبت SDKنام دقیق پکیج‌ها بسته به Provider مورد استفاده شما متفاوت است. نکته مهم این است که یک Application Service واحد داشته باشید که Client مربوط به Vendor را در خود قرار دهد.برای مثال، برای SDK مربوط به OpenAI می‌توانید از دستورهای زیر استفاده کنید:composer require openai-php/laravel&#xA;php artisan vendor:publish --provider=&#34;OpenAI\Laravel\ServiceProvider&#34;&#xA;سپس یک سرویس برای تولید متن ایجاد کنید:namespace App\Services\AI;&#xA;&#xA;use OpenAI\Client;&#xA;&#xA;class TextGenerator&#xA;{&#xA;    public function __construct(&#xA;        private Client $client,&#xA;        private string $model&#xA;    ) {}&#xA;&#xA;    public function complete(string $system, string $user): string&#xA;    {&#xA;        $response = $this-&gt;client-&gt;chat()-&gt;create([&#xA;            &#39;model&#39; =&gt; $this-&gt;model,&#xA;            &#39;messages&#39; =&gt; [&#xA;                [&#39;role&#39; =&gt; &#39;system&#39;, &#39;content&#39; =&gt; $system],&#xA;                [&#39;role&#39; =&gt; &#39;user&#39;, &#39;content&#39; =&gt; $user],&#xA;            ],&#xA;            &#39;temperature&#39; =&gt; 0.3,&#xA;        ]);&#xA;&#xA;        return trim((string) ($response-&gt;choices[0]-&gt;message-&gt;content ?? &#39;&#39;));&#xA;    }&#xA;}&#xA;حالا در AppServiceProvider این سرویس را در Service Container ثبت کنید:$this-&gt;app-&gt;singleton(TextGenerator::class, function () {&#xA;    return new TextGenerator(&#xA;        client: \OpenAI::client(config(&#39;services.ai.key&#39;)),&#xA;        model: config(&#39;services.ai.model&#39;),&#xA;    );&#xA;});&#xA;ساخت Client را متناسب با SDK انتخابی خود تنظیم کنید.نکته مهم این است که فقط یک Binding برای این سرویس داشته باشید تا Controllerها مجبور نباشند هر بار به‌صورت دستی Client مربوط به AI را ایجاد کنند.این کار باعث می‌شود ساختار برنامه تمیزتر و تغییر Provider یا SDK در آینده بسیار ساده‌تر شود.مرحله ۳: فراخوانی AI از Controllerبرای درخواست‌های کوتاه و سریع می‌توانید مستقیماً از Controller با سرویس AI ارتباط برقرار کنید.به عنوان مثال، یک Endpoint برای خلاصه‌سازی متن:use App\Services\AI\TextGenerator;&#xA;use Illuminate\Http\Request;&#xA;&#xA;public function summarize(Request $request, TextGenerator $ai)&#xA;{&#xA;    $data = $request-&gt;validate([&#xA;        &#39;text&#39; =&gt; [&#39;required&#39;, &#39;string&#39;, &#39;max:8000&#39;],&#xA;    ]);&#xA;&#xA;    $summary = $ai-&gt;complete(&#xA;        &#39;Summarize the text in 3 bullet points. No fluff.&#39;,&#xA;        $data[&#39;text&#39;]&#xA;    );&#xA;&#xA;    abort_if($summary === &#39;&#39;, 502, &#39;Empty model response&#39;);&#xA;&#xA;    return response()-&gt;json([&#39;summary&#39; =&gt; $summary]);&#xA;}&#xA;در این مثال ابتدا ورودی کاربر اعتبارسنجی می‌شود.سپس متن به مدل ارسال شده و نتیجه دریافت می‌شود.در نهایت نیز بررسی می‌کنیم که مدل پاسخ خالی برنگردانده باشد.چه زمانی از درخواست مستقیم استفاده کنیم؟فقط زمانی از درخواست Synchronous استفاده کنید که زمان پاسخ قابل قبول باشد.اگر درخواست ممکن است چند ثانیه یا بیشتر طول بکشد، بهتر است آن را به Queue منتقل کنید.مرحله ۴: انتقال عملیات طولانی به Jobبرای عملیات زمان‌بر بهتر است از Laravel Queue استفاده کنید.ابتدا یک Job ایجاد کنید:php artisan make:job GenerateArticleDraft&#xA;سپس Job را به شکل زیر پیاده‌سازی کنید:namespace App\Jobs;&#xA;&#xA;use App\Models\Post;&#xA;use App\Services\AI\TextGenerator;&#xA;use Illuminate\Bus\Queueable;&#xA;use Illuminate\Contracts\Queue\ShouldQueue;&#xA;use Illuminate\Foundation\Bus\Dispatchable;&#xA;use Illuminate\Queue\InteractsWithQueue;&#xA;use Illuminate\Queue\SerializesModels;&#xA;&#xA;class GenerateArticleDraft implements ShouldQueue&#xA;{&#xA;    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;&#xA;&#xA;    public int $tries = 3;&#xA;    public int $timeout = 90;&#xA;&#xA;    public function __construct(public Post $post) {}&#xA;&#xA;    public function handle(TextGenerator $ai): void&#xA;    {&#xA;        $draft = $ai-&gt;complete(&#xA;            &#39;Write a clear technical article draft in Markdown.&#39;,&#xA;            &#39;Topic: &#39; . $this-&gt;post-&gt;title&#xA;        );&#xA;&#xA;        $this-&gt;post-&gt;update([&#xA;            &#39;content&#39; =&gt; $draft,&#xA;            &#39;status&#39; =&gt; &#39;draft&#39;,&#xA;        ]);&#xA;    }&#xA;}&#xA;حالا می‌توانید Job را Dispatch کنید:GenerateArticleDraft::dispatch($post);&#xA;در این حالت، کاربر مجبور نیست منتظر پاسخ AI بماند.Laravel عملیات تولید محتوا را در Queue قرار می‌دهد و Worker در پس‌زمینه آن را اجرا می‌کند.این روش برای مواردی مانند:تولید مقالهخلاصه‌سازی تعداد زیادی متنپردازش فایل‌هاتولید توضیحات محصولاتتحلیل داده‌هاپردازش گروهی درخواست‌های AIمناسب‌تر است.مرحله ۵: اعتبارسنجی خروجی مدلیکی از نکات بسیار مهم این است که خروجی LLM را ورودی قابل اعتماد در نظر نگیرید.مدل هوش مصنوعی ممکن است خروجی ناقص، اشتباه یا حتی با فرمت غیرمنتظره تولید کند.بنابراین قبل از ذخیره یا استفاده از خروجی، آن را اعتبارسنجی کنید.حداقل اقدامات پیشنهادی:پاسخ خالی را رد کنید.حداکثر طول خروجی را محدود کنید.اگر خروجی قرار است در HTML نمایش داده شود، HTML را Sanitize یا Escape کنید.برای وظایف ساختاریافته، از JSON استفاده کرده و آن را اعتبارسنجی کنید.برای مثال:$json = $ai-&gt;complete(&#xA;    &#39;Return JSON only with keys title and outline (array of strings).&#39;,&#xA;    $topic&#xA;);&#xA;&#xA;$data = json_decode($json, true);&#xA;&#xA;abort_if(! is_array($data), 422, &#39;Invalid AI JSON&#39;);&#xA;&#xA;$validated = validator($data, [&#xA;    &#39;title&#39; =&gt; [&#39;required&#39;, &#39;string&#39;, &#39;max:160&#39;],&#xA;    &#39;outline&#39; =&gt; [&#39;required&#39;, &#39;array&#39;, &#39;min:3&#39;],&#xA;    &#39;outline.*&#39; =&gt; [&#39;string&#39;, &#39;max:200&#39;],&#xA;])-&gt;validate();&#xA;در اینجا از مدل خواسته‌ایم فقط JSON برگرداند.سپس:JSON Decode می‌شود.بررسی می‌کنیم که خروجی واقعاً یک Array باشد.ساختار داده با Laravel Validator اعتبارسنجی می‌شود.فقط در صورت معتبر بودن، می‌توانیم از داده استفاده یا آن را ذخیره کنیم.بهترین روش‌هاهنگام ساخت قابلیت‌های AI در Laravel، نکات زیر را رعایت کنید:۱. Promptها را متمرکز نگه داریدPromptها را در Controllerهای مختلف پراکنده نکنید.بهتر است آن‌ها را در:ServiceهاClassهای اختصاصیفایل‌های Configurationقرار دهید.این کار مدیریت و تغییر Promptها را ساده‌تر می‌کند.۲. Logging داشته باشیدمواردی مانند:نام مدلزمان پاسخوضعیت درخواستدلیل خطاتعداد Retryهارا Log کنید.اما هرگز Secretها و API Keyها را در Log ذخیره نکنید.۳. برای Endpointهای عمومی Rate Limit قرار دهیداگر قابلیت AI از طریق API عمومی در اختیار کاربران قرار دارد، حتماً Rate Limiting اضافه کنید.در غیر این صورت ممکن است یک کاربر با ارسال تعداد زیادی درخواست، هزینه API شما را به‌شدت افزایش دهد.۴. ابتدا Draft تولید کنیدبرای محتوای تولیدشده توسط AI بهتر است ابتدا آن را به‌صورت Draft ذخیره کنید.سپس کاربر یا ادمین بتواند آن را بررسی و تأیید کند.۵. برای تست از Fake Client استفاده کنیددر تست‌های CI نباید هر بار واقعاً به API سرویس AI متصل شوید.بهتر است Client مربوط به AI را Fake کنید تا تست‌ها:سریع‌تر باشند.هزینه API ایجاد نکنند.به اینترنت وابسته نباشند.نتایج قابل پیش‌بینی داشته باشند.اشتباهات رایجقرار دادن API Key در Repositoryقرار دادن API Key در سورس‌کد یا Git Repository یک اشتباه امنیتی جدی است.کلیدهای API را در .env قرار دهید و مطمئن شوید .env در Git Commit نمی‌شود.اجرای مستقیم مدل داخل Web Requestاگر مدل چندین ثانیه زمان نیاز دارد، نباید کاربر را مجبور کنید تا پایان درخواست منتظر بماند.در این شرایط از Queue استفاده کنید.ذخیره HTML خام تولیدشده توسط AIاگر مدل HTML تولید می‌کند، نباید آن را بدون بررسی مستقیماً در سایت نمایش دهید.ابتدا باید خروجی را Sanitize یا Escape کنید تا از مشکلات امنیتی جلوگیری شود.نداشتن Timeout و Retryارتباط با سرویس‌های خارجی همیشه ممکن است با خطا یا Timeout مواجه شود.بنابراین باید برای درخواست‌ها Timeout و در صورت نیاز Retry Strategy مناسب داشته باشید.استفاده از یک Prompt بسیار بزرگبه جای ساخت یک Prompt عظیم که قرار است «همه کارها» را انجام دهد، بهتر است وظایف را به عملیات کوچک‌تر تقسیم کنید.برای مثال:Generate Title&#xA;        ↓&#xA;Generate Outline&#xA;        ↓&#xA;Generate Content&#xA;        ↓&#xA;Validate&#xA;        ↓&#xA;Save Draft&#xA;این ساختار معمولاً قابل کنترل‌تر، قابل تست‌تر و قابل نگهداری‌تر است.جمع‌بندیاستفاده از یک AI SDK در Laravel بیشتر از آنکه یک مسئله پیچیده مربوط به هوش مصنوعی باشد، یک مسئله مربوط به مهندسی نرم‌افزار صحیح است.یک معماری مناسب باید شامل موارد زیر باشد:Config برای مدیریت SecretهاService Boundary برای جدا کردن Vendor SDKQueue برای عملیات زمان‌برValidation برای بررسی خروجی مدلبا ایجاد این ساختار پایه، اضافه کردن قابلیت‌های مختلف هوش مصنوعی بسیار ساده‌تر می‌شود.همچنین اگر در آینده تصمیم بگیرید مدل یا Provider خود را تغییر دهید، به جای بازنویسی کل پروژه، فقط بخش کوچکی از سیستم را تغییر خواهید داد.سوالات متداولکدام AI SDK را انتخاب کنم؟بهتر است از SDK رسمی یا یک Client معتبر و به‌خوبی نگهداری‌شده برای Provider مورد نظر خود استفاده کنید.با این حال، توصیه می‌شود برنامه شما مستقیماً به کلاس‌های Vendor وابسته نباشد.به جای آن، یک Abstraction مانند:TextGenerator&#xA;ایجاد کنید و Controllerها و سایر بخش‌های برنامه را به این سرویس وابسته کنید.در این صورت تغییر Provider یا مدل در آینده بسیار ساده‌تر خواهد بود.آیا می‌توانم در Laravel پاسخ‌های AI را Stream کنم؟بله.بسیاری از SDKها از Streaming پشتیبانی می‌کنند.Streaming برای رابط‌های Chat بسیار مناسب است، زیرا کاربر می‌تواند پاسخ را هم‌زمان با تولید شدن مشاهده کند.اما برای پردازش‌های گروهی و Batch Generation همچنان بهتر است از Queue و Job استفاده کنید.آیا حتماً به Redis نیاز دارم؟خیر.برای شروع می‌توانید از Queue مبتنی بر database استفاده کنید.با افزایش تعداد درخواست‌های AI، حجم پردازش و تعداد Retryها، Redis می‌تواند انتخاب مناسب‌تری برای Queue باشد.در نتیجه، می‌توانید با Database Queue شروع کنید و در صورت افزایش بار سیستم، زیرساخت Queue را به Redis منتقل کنید.</description><category>آرش فدائی</category><author>آرش فدائی</author><pubDate>Fri, 28 Aug 2026 11:01:20 +0330</pubDate></item><item><title>راهنمای جامع آپگرید لاراول ۱۳ | تمام تغییرات و نکات</title><link>https://virgool.ir/@m_28031645/راهنمای-جامع-آپگرید-لاراول-۱۳-تمام-تغییرات-و-نکات-ll3iqubo6bcf</link><description>راهنمای جامع آپگرید لاراول ۱۳ | تمام تغییرات و نکات✨ چرا این آپگرید مهم است؟بهبود‌های امنیتی: حفاظت CSRF و سریالایزیشن بهترویژگی‌های جدید: PHP Attributes، Cache::touch() و موارد دیگربهینه‌سازی عملکرد: سرعت و کارایی بیشترSyntax و API جدید: کد تمیزتر و خوانایی بهتر🎯 ویژگی‌های جدید لاراول ۱۳🏷️ ۱. PHP Attributes Support (ویژگی‌های PHP)لاراول ۱۳ از PHP 8 Attributes به عنوان جایگزینی برای property‌های کلاس برای پیکربندی اجزاء Laravel استفاده می‌کند. این یک تغییر غیرشکست‌پذیر است — پیکربندی مبتنی بر property‌های قدیمی همچنان کار می‌کند.📚 Eloquent Modelsاکنون می‌توانید از Attributes استفاده کنید تا نیازی به تعریف کردن $table، $hidden، $fillable و دیگر properties نباشد:#[Table(&#39;users&#39;, key: &#39;user_id&#39;, keyType: &#39;string&#39;, incrementing: false)]&#xA;#[Hidden([&#39;password&#39;])]&#xA;#[Fillable([&#39;name&#39;, &#39;email&#39;])]&#xA;class User extends Model {}کپیAttributes دستیاب برای Models:Attributeتوضیح#[Appends]ویژگی‌های بیشتری را append کنید#[Connection]اتصال دیتابیس را تنظیم کنید#[Fillable]فیلدهای قابل پُر‌کردن#[Guarded]فیلدهای محافظت‌شده#[Hidden]فیلدهای مخفی در خروجی#[Table]نام جدول دیتابیس#[Touches]رابطه‌های جدید شامل#[Unguarded]تمام فیلدها قابل اختصاص هستند#[Visible]فیلدهای نمایشی📋 Queue Jobsاکنون می‌توانید پیکربندی Queue را مستقیماً روی کلاس Job تعریف کنید:#[Connection(&#39;redis&#39;)]&#xA;#[Queue(&#39;podcasts&#39;)]&#xA;#[Tries(3)]&#xA;#[Timeout(120)]&#xA;class ProcessPodcast implements ShouldQueue {}کپیAttributes دستیاب برای Queue:#[Backoff]#[Connection]#[FailOnTimeout]#[MaxExceptions]#[Queue]#[Timeout]#[Tries]#[UniqueFor]این Attributes همچنین برای Listeners، Notifications، Mailables و Broadcast Events قابل استفاده هستند.🖥️ Console CommandsCommands می‌توانند signature و description خود را با Attributes به جای class properties تعریف کنند:#[Signature(&#39;mail:send {user} {--queue}&#39;)]&#xA;#[Description(&#39;Send a marketing email to a user&#39;)]&#xA;class SendMailCommand extends Command {}کپی🎁 اجزای دیگرAttributes همچنین برای موارد زیر قابل دسترس هستند:Form Requests: #[RedirectTo]، #[StopOnFirstFailure]API Resources: #[Collects]، #[PreserveKeys]Factories: #[UseModel]Test Seeders: #[Seed]، #[Seeder]⏱️ ۲. Cache::touch() - تمدید TTL بدون دریافت مقدارPR #55954 یک متد Cache::touch() اضافه می‌کند که TTL یک آیتم کش‌شده را بدون دریافت یا بازذخیره کردن مقدار تمدید می‌کند:// Extend by seconds&#xA;Cache::touch(&#39;user_session:123&#39;, 3600);&#xA; &#xA;// Extend with a DateTime&#xA;Cache::touch(&#39;analytics_data&#39;, now()-&gt;addHours(6));&#xA; &#xA;// Extend indefinitely&#xA;Cache::touch(&#39;report_cache&#39;, null);کپیچرا این مهم است؟ قبلاً، تمدید TTL نیاز به get و سپس put داشت، که نیاز به انتقال مقدار کش‌شده بر روی سیم داشت. Cache::touch() این مرحله را رد می‌کند:Redis: یک فرمان EXPIRE استفاده می‌کندMemcached: TOUCH استفاده می‌کندDatabase: یک UPDATE صادر می‌کندمتد true در صورت موفقیت و false در صورتی که کلید موجود نباشد برمی‌گرداند.✅ پشتیبانی: روش Cache::touch() در تمام drivers کش پیاده‌سازی شده است: Array، APC، Database، DynamoDB، File، Memcached، Memoized، Null، و Redis.🐍 ۳. نسخه PHP مورد نیازلاراول ۱۳ نیاز به PHP 8.3 به عنوان حداقل نسخه دارد. این نمایندگی یک افزایش از نسخه ۱۲ (PHP 8.2) است.نسخه Laravelنسخه PHPتاریخ انتشاررفع باگ تاپشتیبانی امنیتی تا108.1 - 8.314 فوریه 20236 اگست 20244 فوریه 2025118.2 - 8.412 مارس 20243 سپتامبر 202512 مارس 2026128.2 - 8.524 فوریه 202513 اگست 202624 فوریه 2027138.3 - 8.5Q1 2026 (مارس)Q3 2027Q1 2028📦 بروزرسانی وابستگی‌هااولین و مهم‌ترین گام، بروزرسانی فایل composer.json است:{&#xA;  &#34;require&#34;: {&#xA;    &#34;php&#34;: &#34;^8.3&#34;,&#xA;    &#34;laravel/framework&#34;: &#34;^13.0&#34;,&#xA;    &#34;laravel/tinker&#34;: &#34;^3.0&#34;,&#xA;    &#34;laravel/sanctum&#34;: &#34;^4.0&#34;&#xA;  },&#xA;  &#34;require-dev&#34;: {&#xA;    &#34;phpunit/phpunit&#34;: &#34;^12.0&#34;,&#xA;    &#34;laravel/pint&#34;: &#34;^1.17&#34;,&#xA;    &#34;laravel/sail&#34;: &#34;^1.30&#34;&#xA;  }&#xA;}کپیسپس این دستورات را اجرا کنید:rm -rf vendor composer.lock&#xA;composer install&#xA;composer dump-autoloadکپی🛡️ تغییرات Middleware و CSRFتغییر نام VerifyCsrfTokenیکی از مهم‌ترین تغییرات در لاراول ۱۳:❌ قدیمیIlluminate\Foundation\Http\Middleware\VerifyCsrfToken✅ جدیدIlluminate\Foundation\Http\Middleware\PreventRequestForgeryمراحل انتقال:use Illuminate\Foundation\Http\Middleware\PreventRequestForgery;&#xA;&#xA;-&gt;withoutMiddleware([PreventRequestForgery::class])کپی⚙️ تنظیمات کَش و Serializationگزینه جدیدی به نام serializable_classes به کانفیگ کش اضافه شده که به طور پیش‌فرض false است. این کار جلوی حملات deserialization gadget chain را می‌گیره.// config/cache.php&#xA;return [&#xA;    &#39;serializable_classes&#39; =&gt; [&#xA;        App\Models\User::class,&#xA;        App\Data\CachedDashboardStats::class,&#xA;    ],&#xA;];کپی🗄️ تغییرات Eloquent و دیتابیسمتد upsert() - اعتبارسنجی اجباریحالا متد upsert حتماً نیاز به یک مقدار غیرتهی برای uniqueBy دارد.User::upsert(&#xA;    [&#xA;        [&#39;email&#39; =&gt; &#39;john@example.com&#39;, &#39;name&#39; =&gt; &#39;John&#39;],&#xA;        [&#39;email&#39; =&gt; &#39;jane@example.com&#39;, &#39;name&#39; =&gt; &#39;Jane&#39;],&#xA;    ],&#xA;    &#39;email&#39;,  // uniqueBy - اجباری&#xA;    [&#39;name&#39;, &#39;updated_at&#39;]  // updateFields&#xA;);کپی🔄 Queue و Event‌های جدیدJobAttempted Eventخاصیت exceptionOccurred حذف و با $event-&gt;exception جایگزین شد.use Illuminate\Queue\Events\JobAttempted;&#xA;&#xA;Queue::listen(JobAttempted::class, function (JobAttempted $event) {&#xA;    if ($event-&gt;exception !== null) {&#xA;        Log::error(&#39;Job failed&#39;, [&#39;exception&#39; =&gt; $event-&gt;exception]);&#xA;    }&#xA;});کپیQueueBusy Eventخاصیت $connection به $connectionName تغییر نام داد.use Illuminate\Queue\Events\QueueBusy;&#xA;&#xA;class ListenerQueueBusy&#xA;{&#xA;    public function handle(QueueBusy $event)&#xA;    {&#xA;        Log::info(&#34;Queue busy: {$event-&gt;connectionName}&#34;);&#xA;    }&#xA;}کپی🌐 مسیریابی و Routingتغییر الویت Routeالویت تطابق مسیرها عوض شده: مسیرهایی که دامنه (domain) مشخص دارند، اولویت بیشتری نسبت به مسیرهای بدون دامنه دارند.// الویت 1 - Domain مشخص&#xA;Route::domain(&#39;api.example.com&#39;)-&gt;group(function () {&#xA;    Route::get(&#39;/users&#39;, &#39;UserController@index&#39;);&#xA;});&#xA;&#xA;// الویت 2 - بدون Domain&#xA;Route::get(&#39;/users&#39;, &#39;UserController@index&#39;);کپی🧪 تغییرات TestingString Factories - Reset بین تست‌هاکارخانه‌های UUID و string دیگر بین تست‌ها ریست می‌شوند. اگر در تست‌های مختلف به persist شدن این فیکسچرها تکیه کرده بودید، باید در هر تست یا در متد setUp دوباره مقداردهی کنید.public function setUp(): void&#xA;{&#xA;    parent::setUp();&#xA;    &#xA;    Str::createUuidsUsing(function () {&#xA;        return Str::uuid();&#xA;    });&#xA;}کپیJs::from() - Unicode Unescapingحالا به طور پیش‌فرض از JSON_UNESCAPED_UNICODE استفاده می‌کند.✅ بهترین روش‌های آپگرید📋 چک‌لیست پیش آپگریدBackup دیتابیس و فایل‌های پروژهgit commit -am &#34;Pre-upgrade backup&#34;&#xA;mysqldump -u user -p database &gt; backup.sqlکپیبررسی نسخه PHP (باید 8.3+ باشد)php -vکپیاجرای تست‌های موجودphp artisan test --stop-on-failureکپی🐛 Troubleshooting❌ مشکل: &#34;Class not found&#34; برای PreventRequestForgery✅ حل: از Illuminate\Foundation\Http\Middleware\PreventRequestForgery استفاده کنید❌ مشکل: &#34;Serializable classes not found&#34;✅ حل: کلاس‌های استفاده‌شده را به config/cache.php اضافه کنید❌ مشکل: &#34;upsert() requires uniqueBy parameter&#34;✅ حل: پارامتر uniqueBy را تنظیم کنید🎯 نتیجه‌گیریلاراول ۱۳ آپگرید سرمایه‌گذاری ارزشمندی برای امنیت و عملکرد است. ویژگی‌های جدید مثل PHP Attributes و Cache::touch() توسعه را آسان‌تر می‌کنند.✅ توصیه‌های خلاصه:Backup بگیریدبه‌ترتیب پیش برویدتست‌ها را اجرا کنیداز ابزارهای خودکار استفاده کنید (Laravel Shift)Logs را نظارت کنید</description><category>آرش فدائی</category><author>آرش فدائی</author><pubDate>Fri, 28 Aug 2026 02:40:04 +0330</pubDate></item><item><title>چگونه در لاراول Job بنویسیم؟ راهنمای عملی Queue</title><link>https://virgool.ir/@m_28031645/laravel-jobs-queue-guide-cepaqrip6nsq</link><description>چگونه در لاراول Job بنویسیم؟در خیلی از اپلیکیشن‌های Laravel، بخشی از کارها نباید هم‌زمان با پاسخ HTTP انجام شوند؛ مثل ارسال ایمیل، پردازش تصویر، همگام‌سازی با API خارجی یا ساخت گزارش. اگر این کارها را داخل Controller نگه دارید، کاربر منتظر می‌ماند و احتمال Timeout بالا می‌رود.Laravel برای همین سناریو، سیستم Queue و کلاس‌های Job را فراهم کرده است. در این مقاله قدم‌به‌قدم می‌بینیم Job چیست، چطور ساخته می‌شود، چطور Dispatch می‌شود و چه نکاتی را در Production باید رعایت کنید.Job در Laravel چیست؟یک Job واحد کاری است که می‌تواند بلافاصله یا با تأخیر، در پس‌زمینه اجرا شود. معمولاً منطق سنگین یا وابسته به سرویس خارجی را داخل Job می‌گذارید و از Request فقط آن را Dispatch می‌کنید.مزیت اصلی این الگو:پاسخ سریع‌تر به کاربرامکان Retry هنگام خطاجدا کردن منطق سنگین از لایه HTTPکنترل بهتر Rate Limit و بار سرورپیش‌نیازهاقبل از شروع مطمئن شوید:یک پروژه Laravel (نسخه ۸ به بالا پیشنهاد می‌شود) داریددر .env درایور Queue را مشخص کرده‌ایدبرای محیط واقعی، یک Worker در حال اجرا داریدانتخاب Queue Connectionدر فایل .env معمولاً یکی از این گزینه‌ها را می‌بینید:QUEUE_CONNECTION=database&#xA;# یا&#xA;QUEUE_CONNECTION=redis&#xA;# برای تست سریع محلی:&#xA;QUEUE_CONNECTION=syncsync یعنی Job همان لحظه در همان Process اجرا می‌شود و برای Production مناسب نیست. برای شروع توسعه، database یا redis گزینه‌های رایج‌اند.اگر از database استفاده می‌کنید، جدول jobs را بسازید:php artisan queue:table&#xA;php artisan migrateساخت اولین Jobبا Artisan یک Job بسازید:php artisan make:job SendWelcomeEmailفایل معمولاً در مسیر app/Jobs/SendWelcomeEmail.php ساخته می‌شود. ساختار پایه چیزی شبیه این است:&lt;?php&#xA;&#xA;namespace App\Jobs;&#xA;&#xA;use App\Models\User;&#xA;use Illuminate\Bus\Queueable;&#xA;use Illuminate\Contracts\Queue\ShouldQueue;&#xA;use Illuminate\Foundation\Bus\Dispatchable;&#xA;use Illuminate\Queue\InteractsWithQueue;&#xA;use Illuminate\Queue\SerializesModels;&#xA;use Illuminate\Support\Facades\Mail;&#xA;use App\Mail\WelcomeMail;&#xA;&#xA;class SendWelcomeEmail implements ShouldQueue&#xA;{&#xA;    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;&#xA;&#xA;    public function __construct(&#xA;        public User $user&#xA;    ) {}&#xA;&#xA;    public function handle(): void&#xA;    {&#xA;        Mail::to($this-&gt;user-&gt;email)-&gt;send(new WelcomeMail($this-&gt;user));&#xA;    }&#xA;}نکته مهم: ShouldQueueاگر کلاس Job اینترفیس ShouldQueue را پیاده‌سازی کند، Laravel آن را به Queue می‌فرستد. بدون این اینترفیس، Job به‌صورت همزمان (Synchronous) اجرا می‌شود.ارسال (Dispatch) کردن Jobاز Controller، Listener یا Service می‌توانید Job را Dispatch کنید:use App\Jobs\SendWelcomeEmail;&#xA;&#xA;public function store(Request $request)&#xA;{&#xA;    $user = User::create($request-&gt;validated());&#xA;&#xA;    SendWelcomeEmail::dispatch($user);&#xA;&#xA;    return response()-&gt;json([&#xA;        &#39;message&#39; =&gt; &#39;ثبت‌نام انجام شد&#39;,&#xA;    ], 201);&#xA;}تأخیر، صف مشخص و اولویتSendWelcomeEmail::dispatch($user)&#xA;    -&gt;delay(now()-&gt;addMinutes(5));&#xA;&#xA;SendWelcomeEmail::dispatch($user)&#xA;    -&gt;onQueue(&#39;emails&#39;);&#xA;&#xA;SendWelcomeEmail::dispatch($user)&#xA;    -&gt;onConnection(&#39;redis&#39;);جدا کردن صف‌ها (مثلاً emails، reports، default) کمک می‌کند کارهای سنگین، کارهای سبک را بلوکه نکنند.اجرای WorkerJob فقط وقتی اجرا می‌شود که Worker در حال گوش‌دادن به Queue باشد:php artisan queue:work&#xA;&#xA;# صف مشخص:&#xA;php artisan queue:work --queue=emails,default&#xA;&#xA;# با محدودیت تلاش مجدد:&#xA;php artisan queue:work --tries=3در Production معمولاً از Supervisor یا systemd استفاده می‌شود تا Worker بعد از Crash دوباره بالا بیاید و بعد از Deploy ری‌استارت شود.کنترل Retry، Timeout و Failureداخل خود Job می‌توانید رفتار خطا را دقیق‌تر تعریف کنید:class SendWelcomeEmail implements ShouldQueue&#xA;{&#xA;    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;&#xA;&#xA;    public int $tries = 3;&#xA;    public int $timeout = 60;&#xA;&#xA;    public function backoff(): array&#xA;    {&#xA;        return [10, 30, 60];&#xA;    }&#xA;&#xA;    public function handle(): void&#xA;    {&#xA;        // ...&#xA;    }&#xA;&#xA;    public function failed(\Throwable $exception): void&#xA;    {&#xA;        // لاگ، اعلان به تیم، یا علامت‌گذاری کاربر&#xA;        logger()-&gt;error(&#39;SendWelcomeEmail failed&#39;, [&#xA;            &#39;user_id&#39; =&gt; $this-&gt;user-&gt;id,&#xA;            &#39;error&#39; =&gt; $exception-&gt;getMessage(),&#xA;        ]);&#xA;    }&#xA;}برای دیدن Jobهای شکست‌خورده، جدول failed jobs را بسازید:php artisan queue:failed-table&#xA;php artisan migrate&#xA;php artisan queue:failed&#xA;php artisan queue:retry allیک مثال واقعی‌تر: پردازش گزارش&lt;?php&#xA;&#xA;namespace App\Jobs;&#xA;&#xA;use App\Models\Report;&#xA;use App\Services\ReportGenerator;&#xA;use Illuminate\Bus\Queueable;&#xA;use Illuminate\Contracts\Queue\ShouldQueue;&#xA;use Illuminate\Foundation\Bus\Dispatchable;&#xA;use Illuminate\Queue\InteractsWithQueue;&#xA;use Illuminate\Queue\SerializesModels;&#xA;&#xA;class GenerateUserReport implements ShouldQueue&#xA;{&#xA;    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;&#xA;&#xA;    public int $tries = 2;&#xA;    public int $timeout = 120;&#xA;&#xA;    public function __construct(&#xA;        public Report $report&#xA;    ) {}&#xA;&#xA;    public function handle(ReportGenerator $generator): void&#xA;    {&#xA;        $path = $generator-&gt;generate($this-&gt;report);&#xA;&#xA;        $this-&gt;report-&gt;update([&#xA;            &#39;status&#39; =&gt; &#39;ready&#39;,&#xA;            &#39;file_path&#39; =&gt; $path,&#xA;        ]);&#xA;    }&#xA;}اینجا منطق ساخت گزارش داخل Service است و Job فقط orchestration می‌کند؛ این جداسازی تست‌پذیری و خوانایی را بهتر می‌کند.بهترین روش‌هاJob را کوچک نگه دارید: یک مسئولیت مشخص داشته باشد.Model را با SerializesModels پاس بدهید: Laravel فقط ID را در Queue ذخیره می‌کند و هنگام اجرا دوباره Model را می‌خواند.داده‌های حساس را در Payload نگذارید: رمز عبور، توکن خام یا اطلاعات محرمانه را Serialize نکنید.Idempotent بنویسید: اگر Job دوباره اجرا شد، نتیجه تکراری یا خراب نسازد.صف‌ها را جدا کنید: ایمیل، گزارش و کارهای سنگین را در Queueهای مجزا بگذارید.لاگ و Monitoring داشته باشید: Horizon (برای Redis)، failed jobs و لاگ اپلیکیشن را جدی بگیرید.اشتباهات رایجاستفاده از QUEUE_CONNECTION=sync در Production و فکر کردن که Queue داریدفراموش کردن اجرای queue:work یا Supervisorگذاشتن منطق خیلی سنگین داخل Controller به‌جای JobPass کردن Objectهای غیرقابل Serializeنداشتن استراتژی Retry و متد failed()یک صف واحد برای همه کارها و ایجاد گلوگاهجمع‌بندیبرای نوشتن Job در Laravel این مسیر کافی است: Job بسازید، ShouldQueue را پیاده‌سازی کنید، منطق را در handle() بنویسید، با dispatch() ارسال کنید و Worker را اجرا نگه دارید. اگر کارهای پس‌زمینه را از Request جدا کنید، اپلیکیشن سریع‌تر، پایدارتر و مقیاس‌پذیرتر می‌شود.سوالات متداولتفاوت Job و Listener چیست؟Listener به Event واکنش نشان می‌دهد. اگر Listener اینترفیس ShouldQueue داشته باشد، خودش مثل یک Job صف می‌شود. Job را معمولاً مستقیم Dispatch می‌کنید؛ Listener را با Fire شدن Event.کی از Bus::batch استفاده کنیم؟وقتی چند Job مرتبط دارید و می‌خواهید پیشرفت، تکمیل یا شکست کل مجموعه را یکجا مدیریت کنید، Batch مناسب است.آیا بدون Redis می‌توان Queue داشت؟بله. درایور database برای شروع کاملاً قابل استفاده است. برای حجم بالاتر، Redis معمولاً عملکرد بهتری می‌دهد.</description><category>آرش فدائی</category><author>آرش فدائی</author><pubDate>Fri, 28 Aug 2026 02:37:59 +0330</pubDate></item><item><title>یک نصحیت به کارفرمایان عزیز</title><link>https://virgool.ir/@m_28031645/یک-نصحیت-به-کارفرمایان-عزیز-p1dsyzbkgyau</link><description>اگر پولی ندارید و یا خساست به خرج میدید برای پرداخت وقت سنیور جماعت رو نگیرید برید با یک تازه کار یا کار آموز کار کنید اینجوری هم پروداکتتون میره روی هوا هم لذت میبرید ۱۰ برابر بیشتر هزینه میکنیدبالای ۲۰ تماس داشتم همه این تماس ها خلاصش این بود :بیا درصدی کار کنیم سودش تقسیم میشه برای یک تقویم انقدر هزینه میگیری چه خبره اتوماسیون رو با ۵ تومن از راست چین میخرم (منظورش اسکریپت آمادست که حتی ۱ درصد هم به فیچر هایی که میخواد نزدیک نیست)خودم با هوش مصنوعی میزنم افزونه رو مگه چقدر هزینه اشتراکشه (۵ روز بعد مطمعن باشید سایتش پایینه)من چقدر مگه فروش دارم که انقدر هزینه کنم ؟( تو که فروش نداری به نظرم روی فروشت کار کن تا اسخدام سنیور )همه این دوستان دوراشون رو میزنن و وقتی بیزینسشون نابود شد دنبال یک متخصص میگردن#برنامه_نویسی #توسعه_وب #مدیریت_پروژه #کسب_و_کار #لینکدین #تجربه_کاری #وردپرس</description><category>آرش فدائی</category><author>آرش فدائی</author><pubDate>Mon, 15 Jun 2026 14:35:27 +0330</pubDate></item><item><title>انواع مختلف سیستم ذخیره سازی-مزایا و معایب</title><link>https://virgool.ir/@m_28031645/انواع-مختلف-سیستم-ذخیره-سازی-مزایا-و-معایب-jlre9wrqcfnh</link><description>📷انواع مختلف سیستم ذخیره سازی:1. Direct Attached Storage (DAS)2. Network Attached Storage (NAS)3. Storage Area Network(SAN)Direct Attached Storage یا DAS:یکی از ساده ترین روش های ذخیره سازی اطلاعات Direct Attached Storage یا DAS میباشد که در این روش ، یک دستگاه ذخیره سازی مستقیم به کامپیوتر یا سرور متصل میگردد.یکی از نمونه های استفاده از  DAS، دستگاه های ذخیره سازی خارجی یا external storage‌ هست که به کامپیوتر یا سرور متصل میشوندیک نمونه از external storage‌ :در واقع یک DASمیتواند ترکیبی از چندین هارد دیسک در یک محفظه واحد باشد که به شبکه متصل نیست.اتصالات پشتیبانی شده سیستم های ذخیره سازی DAS:Universal Serial      Bus     یا USBSerial Advanced      Technology Attached یا SATAExternal Serial      Advanced Technology Attachment یا eSATASerial Attached      SCSI     یا SASمزایای استفاده از DAS:مزیت اصلی سیستم ذخیره سازی DAS ، کارایی بالای آنهاست. در انواع مختلف سیستم های ذخیره سازی، DAS  به دلیل اتصال مستقیم به سیستم‌های میزبان، بیشترین کارایی و کمترین تاخیر را دارد.چند نمونه از مزایای DAS :هزینه پایین: در بین سیستم‌های      ذخیره سازی، DAS‌ها کمترین هزینه را      دارند. دلیل این ارزانی نیز عدم نیاز به تجهیزات ارتباط با شبکه است. DAS‌ها نیازی به سخت      افزار ایجاد ارتباط با شبکه یا اتصال به فیبر نوری ندارند.مدیریت ساده: به پروتکل خاصی      جهت مدیریت، راه اندازی و پیکربندی DAS نیاز نمی باشد. راه اندازی DAS ساده بوده و نیازی به آموزش نحوه مدیریت آن نیست.فضای ذخیره سازی      قابل ارتقا: بدون استفاده از هیچ سیستم گران قیمتی، می‌توان هارد اضافی را      به DAS‌ها اضافه نمود. درست      مانند افزودن RAM بیشتر به کامپیوتر‌ها، می‌توان هارد اضافی را به DAS اضافه کرد.معایب استفاده از DAS:در سیستم های DAS قابلیت اتصال به شبکه وجود ندارد و به همین دلیل جهت ارائه فضای ذخیره سازی به چند کاربر مناسب نیستند. همچنین در این سیستم قابلیت گسترش محدودی دارند. این محدودیت بابت تعداد درگاه های اتصال کم یک سیستم کامپیوتری یا محدودیت تعداد درایور های پشتیبانی شده در  DAS به وجود می آید.Network Attached Storage(NAS):یکی از معروف ترین سیستم های ذخیره سازی NAS یا Network Attached Storage نام دارد. این شهرت به دلیل سهولت استفاده از سمت کاربران و سازمان ها به وجود آمده.NAS یک نوع سیستم ذخیره سازی داده در سطح فایل می باشد. این روش میتواند ذخیره سازی از طریق شبکه را فراهم کند و همچنین قابلیت اتصال هم زمان چندین کاربر را بدون کاهش کارایی را دارد.اکثر دستگاه های NAS شامل چند HDD  یا SSD  در محفظه ای واحد هستند.دیسک های موجود در NAS  معمولا به صورت واحد و تحت RAID  یا Synology Hybrid RAID مدیریت میشوند.نکته: البته شرکت ارائه دهنده NAS  میتواند ویژگی های RAID را در برخی از محصولات خود قرار دهد و در برخی از دستگاه ها این قابلیت وجود نداشته باشد.مزایای استفاده از NAS:دستگاه های NAS  امکان برقراری ارتباط با تحت شبکه را دارد و صرفا به یک سرویس میزبانی متصل نیستند.فضای ذخیره سازی NAS  ها میتواند به صورت مجازی تعداد نامحدودی از میزبان ها اختصاص داده شود.این سیستم ذخیره سازی به راحتی قابل افزایش است و امکان افزودن دیسک‌های بیشتر را نیز دارد.چند نمونه از مزایای استفاده از NAS :· استفاده از RAID : NAS‌ها به دلیل پشتیبانی از RAID‌ها کارایی بالایی دارند· سهولت در پیکر بندی: پیکربندی دستگاه‌های NAS ساده بوده و به کمترین تجهیزات برای تعمیر و نگهداری نیاز دارند.· استفاده از سیستم عامل: سیستم عامل‌های تعبیه شده در NAS‌های شرکت‌های QNAP وSynology عملکرد‌هایی مانند راه اندازی سرور ایمیل و مجازی سازی را نیز پشتیبانی می‌کنند.معایب استفاده از  NAS :کارایی دستگاه‌های NAS وابسته به شبکه ای خواهد بود که به آن متصل می‌شوند. هرگونه کندی در شبکه می‌تواند روی دسترسی به NAS تاثیر منفی داشته باشد. پس باید توجه داشته باشیم که در در زمان پیاده سازی NAS به سرعت شبکه و میزان تاخیر آن توجه داشته باشیمعلاوه بر این، دستگاه‌های NAS قابلیت‌های محدودی جهت ارتقا CPU ،RAM و غیره دارند. به همین دلیل در زمان مشاهده کاهش کارایی دستگاه، گزینه‌های متعددی جهت ارتقا سخت افزار آن وجود نخواهد داشت.Storage Area Network  (SAN):سیستم ذخیره سازی Storage Area Network یا به اختصار SAN، روشی اختصاصی جهت ذخیره سازی اطلاعات در سازمان‌ها و دیتاسنترها است و همچنین SAN‌ها کارایی بالایی دارند و امکان ذخیره سازی در سطح بلاک‌ها (block-level storage) را برای سیستم‌های میزبان فراهم می‌سازندمنظور از block-level storage چیست؟در تکنولوژی Block storage یا همان block-level storage، داده‌ها به بلاک‌های جداگانه تقسیم شده و هرکدام با یک شناسه منحصر به فرد ذخیره می‌گردند. در واقع SAN ‌ها در جهت ارائه ذخیره سازی سطح بلاک با قابلیت اطمینان و گسترش پذیری بالا، تکامل یافته اند.SAN‌ ها برای ایجاد ارتباط تحت شبکه، از پروتکل‌های زیر استفاده می‌کنند:Small Computer      Systems Interface یا به اختصار SCSIInternet Small      Computer Systems Interface یا به اختصار ISCSIکانال فیبر یا همان Fiber Channelشرکت هایی که از SAN برای ذخیره سازی استفاده میکند میتوان به l EMC، HPE  و NetApp  اشاره کردمزایای استفاده از SAN:SAN‌ها برای استفاده در سازمان‌های مهم و با حجم کاری بالا توسعه داده شده اند.و به همین خاطر بهترین کارایی،اطمینان پذیری و گسترش پذیری را در مقایسه با انواع مختلف سیستم ذخیره سازی ارائه می دهند.چند مورد از مزایای SAN :· وجود دسترسی سطح بلاک، سازمان‌ها را از تهیه سیستم‌های ذخیره ساز محلی بی نیاز می‌کند.· SAN‌ها فراخوانی از طریق شبکه را برای محیط‌های کاری تسهیل می‌نمایند.· سیستم‌های میزبان موجود در شبکه، می‌توانند به همه نیاز‌های خود از طریق SAN دستیابی پیدا کنند· SAN‌ها حتی دسترسی به سیستم عامل را نیز تحت شبکه ممکن و تسهیل می‌نمایند.معایب استفاده از SAN:بزرگترین ایراد SAN‌ها، پیچیدگی بالای آنها است. به نحوی که پیاده سازی و نگهداری یک SAN ساده نیز می‌تواند بسیار پیچیده باشد. از طرفی برای دستیابی به کارایی بالا، باید شبکه مورد استفاده نیز به بهترین شکل ممکن بهینه شود.توجه این مقاله توسط تیم آریاس کد نوشته شده </description><category>آرش فدائی</category><author>آرش فدائی</author><pubDate>Mon, 02 Sep 2024 12:07:37 +0330</pubDate></item><item><title>تفاوت و کاربرد بین واقعیت مجازی و واقعیت افزوده به زبان ساده</title><link>https://virgool.ir/@m_28031645/تفاوت-و-کاربرد-بین-واقعیت-مجازی-و-واقعیت-افزوده-به-زبان-ساده-nprp3ojoyop8</link><description>واقعیت افزوده چیست؟واقعیت افزوده یا  AR  به تکنولوژی گفته میشود که عناصری  از دنیای دیجیتال را با دنیای واقعی ترکیب میکند.ما میتوانیم از ابزار هایی مانند تلفن همراه و تبلت و لپ تاپ و عینک های هوشمند که از اصلی ترین و شناخته شده ترین ابزار ها هستند برای واقعیت افزوده استفاده کنیم.درواقع ابزار های AR با استفاده از الگو های محاسبه کننده موقعیت و جهت المان ها و اطلاعات مجازی را روی اشیائ دنیای واقعی سوار کرده یا با آن ها ترکیب میکنند.نمونه هایی از کاربرد واقعیت افزوده:· فیلتر های اپلیکیشن اسنپ چت· برنامه های دکوراسیون داخلی مانند 3D Max· نمای خیابانی گوگل یا Street Viewواقعیت مجازی چیست؟واقعیت مجازی یا VR  مخفف  Virtual Realityدنیای مجازی را با دنیای واقعی نه تنها ترکیب بلکه جایگزین میکند.در واقع کاربران با استفاده از VR در یک محیط شبیه سازی شده از دنیای واقعی با ویژگی های افزوده وارد میشوند و میتوانند بسیاری از امور و فعالیت های روزمره خود را به شکل مجازی انجام دهند.تفاوت بین واقعیت مجازی و واقعیت افزودهواقعیت افزوده:همانطور که متوجه شدیم تکنولوژی واقعیت افزوده عناصر دنیای واقعی را با عناصر دنیای دیجیتال ترکیب میکند و کاربر متوجه دنیای واقعی نیز هست و درواقع عناسر دیجیتالی را در دنیای واقعی مشاهده میکندنکته:درواقع کاربران واقعیت افزوده به عناصر دنیای واقعی کاملا دسترسی دارند و تنها عناصر دیجیتال را در دنیای واقعی میتوانند تماشا کنندتجهیزات مورد استفاده در واقعیت افزوده:برای تجربه کردن واقعیت افزوده تنها نیاز به دستگاه های تلفن همراه هوشمند , تبلت یا لپ تاپ و نرم افزارها و یا تجهیزاتی مانند عینک و ..هستشواقعیت مجازی:در تکنولوژی واقعیت مجازی کاربر به هیچ عنوان متوجه حضور خود در دنیای واقعی را ندارد و به عناصر دنیای دیجیتال دسترسی داردنکته:در واقع کاربران واقعیت مجازی در یک دنیای کاملا خیالی و از پیش تعریف‌شده زندگی می‌کنند. آن‌ها تماس چندانی با واقعیت نداشته و تنها می‌توانند تجربه‌ای شبیه‌سازی‌شده از آن داشته باشند.تجهیزات مورد استفاده در واقعیت مجازی:برای تجربه کردن واقعیت مجازی نیاز به کنسول های مخصوص و یا حداقل هدست های VR  نیز و علاوه بر آن به تجهیزات AR نیاز دارد که قطعا هزینه های بیشتری نسب به تکنولوژی  AR خواهد داشتکاربرد های واقعیت مجازی و واقعیت افزوده:صنعت گردشگری:یکی بارزترین نمونه های واقعیت مجازی که در صنعت گردشکری به شدت محبوب شده امکان نمایش ویدیو های 360 درجه با کیفیت از مکان های شهر ها و کشور های مختلف هست که به شدت به توریسم و گردشکری در دنیا کمک می کند.یکی از نمونه شرکت هایی که از واقعیت مجازی استفاده میکند شرکت جهانگردی ماریوت ترول برلیانتلی هست که تنها با یک اپلیکیشن به صورت مجازی طی 90 ثانیه میتوانید از هرجایی که نیاز دارید دیدن کنیدبنگاه یا املاک:یکی از مشکلات کاربران برای جستجوی آپارتمان یا ساختمان در شهر های بزرگ صرف کردن انرژی و هزینه بالا می باشد چون کاربران برای انتخاب بهتر باید تک به تک مکان ها را از نزدیک مشاهده کنندبرخی از بنگاه ها یا املاک ها با استفاده از این تکنولوژی به مشتریان یا کاربران این امکان را میدهند تا از فضای داخلی و اتاق های ساختمان بازدید کنند بدون آنکه در آنجا حضور داشته باشندبهداشت و درمان:یکی از مشکلات تلفات بیش از حد و اشتباهات در پزشکی بابت تشخیص خطای بیماری و شناسایی محل درد هست که در سرتاسر جهان روزانه افرادی بابت این مشکل جان خود را از دست میدهند.با استفاده از ابن تکنولوژی در حوزه پزشکی پیشرفت های زیادی در امکان تشخیص صحیح اسکن و مدل های سه بعدی اندام بیماری را برای پزشک انجام شده. این مدل ها به پزشکان کمک میکنند تا به تجربه خود و اعتماد کردن به این تکنولوژی بهترین و موثر ترین روش های درمانی را بیابند و ارائه کنند.</description><category>آرش فدائی</category><author>آرش فدائی</author><pubDate>Mon, 02 Sep 2024 11:49:41 +0330</pubDate></item></channel></rss>