<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های پوریا انوری</title>
        <link>https://virgool.io/feed/@pooriaanv</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-04-15 03:14:52</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/9979/avatar/xz9a9L.png?height=120&amp;width=120</url>
            <title>پوریا انوری</title>
            <link>https://virgool.io/@pooriaanv</link>
        </image>

                    <item>
                <title>آشنایی با PHP Generators</title>
                <link>https://virgool.io/@pooriaanv/php-generator-xu0et4sc9jxj</link>
                <description>نمونه ای از استفاده PHP Generatorخب PHP Generator چی هست ؟‍ این امکان رو به ما میدن، بدون اینکه کل داده ها رو داخل حافظه نگه داریم به کمک یک Loop پیمایش کنیم. در واقع به کمک Generator ها میتونیم توابعی بنویسیم که چندین مقدار مختلف رو به عنوان خروجی برگردونن، برخلاف return که فقط یک مقدار رو برمیگردونه.بخوام توی یک جمله خلاصه کنم این میشه : تابعی که خروجی iterable ارائه میده بدون اینکه کل داده ها رو یکجا برگردونه.  خب Generator وجود نداره!بیاین اول اینجوری پیش بریم که انگار همچین امکانی وجود نداره.ما میخوایم ابتدا آرایه ای از 0 تا بزرگترین عدد php یعنی PHP_INT_MAX داشته باشیم و بعد همه اعضای این آرایه رو چاپ کنیم. بریم ببینیم کدش چطوریه اگر این کد رو اجرا کنیم چی میشه؟ بله با این اررور مواجه می شیم :Allowed memory size of 134217728 bytes exhausted (tried to allocate 134217736 bytes)مشخصه که حافظه ای که در اختیار PHP بوده کاملا پر شده و دلیلش هم اینه که تابع makeArray کل اعداد بین 0 تا PHP_INT_MAX رو داخل حافظه نگه میداره.پس راه حل چیه؟ بله Generator هاهمونطور که گفتم، Generator ها این امکان رو میدن تا بتونیم داده رو پیمایش کنیم بدون اینکه کل اون رو داخل حافظه ذخیر کنیم . دقیقا چطوری میشه؟کد چه تغییری کرده؟ توجهتون رو به این قسمت جلب میکنم :بجای اینکه بیایم هر عدد رو داخل ارایه بریزیم اومدیم yield کردیمش. همونطور که بالاتر گفتم Generatorها به کمک yield این امکان رو میدن تا یک تابع چند خروجی داشته باشه. حالا اینجا چه اتفاقی افتاده؟توی این کد وقتی وارد حلقه for میشیم، مقدار اولیه i$ که 0 هست yield میشه و به عنوان یکی از خروجی ها برگردونده و کد متوقف میشه، دیگه ادامه پیدا نمیکنه تا زمانی که دوباره اجرای Generator ادامه پیدا کنه.چون داخل foreach به پیمایش Generator داریم ادامه میدیم پس مقادیر بعدی هم به ترتیب yield میشن.خروجی کد ما این میشه :result =&gt; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 ...راه حل ما جواب داد، حالا بریم ببینیم چه اتفاقی افتاده و yield چه کاری انجام داده.معجزه yield همون قطعه کد بالا رو با عدد کمتر، مثلا 5 پیش میبریم تا بشه خوب نشون داد چه اتفاقی میوفتهخب اگر ما تابع makeArray رو var_dump کنیم خروجیمون این میشه :object(Generator)#507 (0) { }میبینیم که یک object از نوع Generator هست و هیچ عددی داخلش نیست .حالا اگر خروجی MakeArray رو به کمک foreach پیمایش کنیم چه اتفاقی میوفته؟ خروجی کد بالا اعداد 0 تا 4 رو چاپ کرده،حالا سوال پیش میاد که چرا موقعی که که var_dump کردیم هیچ عددی رو نشون نداده و فقط یک object بود؟ اینجا مشخص میشه که yield مقادیر رو به ترتیب و یکی یکی برمیگردونه و تا زمانی که به پیمایش object خروجی که یک Generator هست ادامه ندیم ، مقادیر بعدی رو برنمیگردونه و اینجوری دیگه کل داده داخل حافظه قرار داده نمیشه و در هر فراخوانی یکی یکی تولید و برگردونده میشن . Generatorها چند متد دارن که اینجا باهاشون آشنا میشیم.متد Currentبا کمک این متد به مقدار فعلی که yield شده دسترسی پیدا میکنیم، اینطوری :خروج فعلی ما عدد 0 هست چرا که مقدار اولیه i$ داخل حلقه 0 هست . پس از اینکه مقدار 0 yield شد حلقه ادامه پیدا نمیکنه و اجرای  Generator نگه داشته میشه.هرچقدر هم تابع current رو صدا بزنیم باز هم خروجی 0 هست.خب اگر بخوابم مقدار بعدی رو چاپ کنیم چیکار کنیم؟ تابع بعدی جواب سوال ما هستمتد Nextبه کمک این متد میتونیم اجرای Generator رو از جای قبلی که متوقف شده بود ادامه بدیم.مقدار اولیه i$ عدد 0 بود با متد current مقدار فعلی یعنی 0 چاپ میشه و با متد next پیمایش Generator رو ادامه میدیم تا yield بعدی و زمانی که دوباره متد current رو صدا میزنیم عدد 1 چاپ میشه چون مقدار بعدی i$ هستش.متد getReturn اگر بخوایم پس از اتمام  اجرا Generator  مقدار return شده ی تابع رو برگردونیم، از این متد استفاده میکنیم.میبینیم که حلقه foreach که وظیفه iterate کردن Generator رو برعهده داره فقط اعداد 1 و 2 رو که yield شدن چاپ کرده، پس اگر بخوایم به مقدار return شده دسترسی پیدا کنیم باید متد getReturn رو صدا بزنیم.فقط دقت کنید اگر قبل از تموم شدن اجرای Generator، متد getReturn رو صدا بزنید با اررور مواجه می شید.متد Sendبه کمک این متد میتونیم مقداری رو به عنوان نتیجه yield به Generator بفرستیم و اجرای Generator رو ادامه بدیم. چندتا مثال :خروجی current خالی هست، چراکه تابع myGen تا جایی که yield هست اجرا شده و چون هیچ مقداری yield نشده ، مقدار فعلی وجود نداره تا current بخواد بهمون نشون بده. همونطور که گفتم در اینجا اجرای Generator متوقف میشه تا دوباره بخوایم اجراش رو به کمک راه های بالا ادامه بدیم. حالا اگر ما به کمک متد send یک مقدار رو به داخل Generator بفرستیم چی میشه؟اولین بار که به yield میرسه چون هیچ مقداری yield نشده متوقف میشه و منتظر ادامه اجرا میمونه ،با متد send اجرا رو ادامه میدیم و میبینیم که مقدار فرستاده شده ما، یعنی &quot;hello&quot; به عنوان مقدار فعلی yield برگردونه میشه و اجرای Generator ما یک گام ادامه پیدا میکنه و چون اخرین yield ما بود، اجراش پایان پیدا میکنه.توی مثال بعدی Generator مقدار اول رو yield میکنه :چون رشته &quot;bye&quot; در داخل تابع yield شده ، متد current مقدار اون رو به ما میده و اجرای Generator در همونجا puase میشه. وقتی با متد send رشته &quot;hello&quot; رو به داخل Generator میفرستیم مقدار فعلی Generator به &quot;hello&quot; تغییر پیدا میکنه و به کمک echo چاپ میشه. توی مرحله اول yield مقدار &quot;bye&quot; رو برگردونده و در مرحله دوم مثل یک متغیر عمل کرده که میتونیم مقداری رو بهش نسبت بدیم.اگر داخل کد بالا اول متد current رو صدا نزنیم و مستقیم از متد send استفاده کنیم، &quot;bye&quot; برگردونه نمیشه و مستقیم مرحله که yield به عنوان یک متغییر استفاده شده اجرا میشه. نتیجه گیری :به کمک Generator ها میتونیم استفاده از حافظه رو بهینه کنیم ، در استفاده از داده های سنگین دیتابیس ها و یا خوندن یک فایل حجیم به ما کمک میکنن .حتی میتونیم یک تابع رو تا یک جای مشخص اجرا کنیم و بقیه اون رو در زمان دیگه ای اجرا کنیم . Generator ها توی Multitasking و Scheduling هم کارآیی دارن.امیداورم به خوبی تونسته باشم مفهموم Generator ها رو براتون جا انداخته باشم .</description>
                <category>پوریا انوری</category>
                <author>پوریا انوری</author>
                <pubDate>Wed, 18 Mar 2020 23:46:48 +0330</pubDate>
            </item>
                    <item>
                <title>دیزاین پترن Adapter و bridge در php</title>
                <link>https://virgool.io/Software/bridge-and-adapter-design-pattern-php-jgiuygjhfdsj</link>
                <description>هر دو این دیزاین پترن ها جزء &quot;الگو های ساختاری&quot; هستند.دیزاین پترن Adapterابتدا به دیزاین پترن Adapter می پردازیم ،دیزاین پترن آداپتور زمانی به کار میرود که ما از یک API خارجی و یا از یک کلاسی استفاده میکنیم که مرتبا در حال تغییر  است . فرض کنید ما یک bot برای تلگرام نوشته ایم و در آن از API تلگرام استفاده میکنیم. در API تلگرام برای ارسال پیام از متود sendMessage استفاده میکنیم ، پس مشخصا ما در ربات خود چندین بار از این متود برای ارسال پیام به کاربران استفاده میکنیم ، حالا فرض کنیم تلگرام در API خود تغییر ایجاد کند و از متود sendMsg بجای sendMessage استفاده کنیم ، در این صورت ما باید زمان زیادی را بسته به تعداد دفعات استفاده از این متود صرف تغیییر کد کنیم و خود این تغییر هم به تنهایی کافی نیست و زمانی هم برای تست نیاز داریم .حال با استفاده از دیزاین پترن Adapter این مشکل حل میشود. راه حل موجود به این صورت هست که ما برای ارسال پیام یک اینترفیس به نام sendMessageInterface ایجاد میکنیم.class telegram { 
 
   public function __construct() {
   // Your Code here //
    }
    public function sendMessage($message) {
    // send message //
     }
}
interface sendMessageInterface  {
       public function send($message);
}
و کلاس telegramAdapter را از آن اینترفیس implements میکنیم. حالا میتونیم متود ارسال پیام خودمان را در این کلاس telegramAdapter تعریف کنیم.class telegramAdapter  implements sendMessageInterface {

    private $telegram;
    
    public function __construct(telegram $telegram) {
        $this-&gt;telegram = $telegram;
    }
    public function send($amount) {
        $this-&gt;telegram-&gt;sendMessage($message);
     }
} حال اگر تلگرام API خود را تغییر دهد ، تنها کافیست که در کلاس telegramAdapter   و متود send نام sendMessage را با نامی که تلگرام تعیین کرده است (که در سناریوی اول ما sendMsg است ) جایگزین کنیم. دیزاین پترن Bridgeخب حالا دیزاین پترن Bridge ، این دیزان پترن تعریف های گوناگونی دارد برای همین سعی میکنم با مثال توضیح بدم.ما برای ارسال یک پیام از دستگاه ها و پیام رسان های مختلفی استفاده میکنیم ، فرض کنید ما برنامه ای نوشته ایم که از API های واس آپ ، تلگرام و اسکایپ برای ارسال پیام کاربران بین دستگاه های مختلف استفاده میکنیم. خب اگر ما بخوایم برای هر دستگاه و پیام رسان کد جداگانه بنویسیم ، بیشتر کdدهای ما تکراری هستن و با کلی کد روبه رو میشیم ، اینجاست که دیزاین پترن Bridge به کمک ما میاد.میریم سراغ کد این سناریو :&lt;?php

interface deviceInterface
{
        public function setSender(massaging $sender);
        public function send($body);
}
abstract class device implements deviceInterface
{
	protected $sender;	
	public function setSender(massaging $sender){
		$this-&gt;sender = $sender;
	}
}
class phone extends device
{
	public function send($body)
	{
		$this-&gt;sender-&gt;send($body.&quot; send by phone&quot;);
	}
}

class tablet extends device
{
	public function send($body)
	{
		$this-&gt;sender-&gt;send($body.&quot; send by tablet&quot;);
	}
}

interface massaging {
 	public function send($body);
}

class telegram implements massaging
{
	public function send($body) {
		echo $body;
	}
}

$phone = new phone;
$phone-&gt;setSender(new telegram);
$phone-&gt;send(&quot;hello&quot;);
همونطور که میبینید ما یک اینترفیس به نام deviceInterface ایجاد کردیم که دارای متودهای setSenderو send هستند ، سپس یک کلاس abstract به نام device ایجاد کردیم که از deviceInterface implements  میشود (دلیل این کار رو میشه اینجوری توضیح داد که ما دیگه متود setSender رو توی کلاس های phone , tablet باز تکرار نکنیم). سپس کلاس های phone و tablet رو ایجاد میکنیم و متود send را متناسب با هرکدوم تعریف میکنیم، برای مسنجر ها هم به صورت دیوایس ها عمل میکنیم.در نهایت مشاهده میکنید که با ساختن یه نمونه جدید از دستگاه مورد نظر و فرستادن یک نمونه ساخته شده از مسنجر مورد نظر در قالب آگومان به متود setSender ، به راحتی یه پیام را از طریق گوشی و پیام رسان تلگرام منتقل کردیم.منابع : https://code.tutsplus.com/tutorials/design-patterns-the-adapter-pattern--cms-22262https://www.jakowicz.com/bridge-pattern-in-php/</description>
                <category>پوریا انوری</category>
                <author>پوریا انوری</author>
                <pubDate>Fri, 01 Jun 2018 20:38:49 +0430</pubDate>
            </item>
            </channel>
</rss>