37
تشکر

توابع ناشناخته در PHP

anonymous functions

anonymous functions

نیمه دوم سال 2009 بود که PHP با ورژن 5.3 با ویژگی‌های زیاد جدیدی که برای برنامه نویسان جذاب بود، انتشار یافت. یکی از ویژگی‌هایی که به PHP در این نسخه اضافه شد، تابع بی‌نام بود.

تابع بی‌نام (anonymous function)

توابع ناشناخته که اصطلاحا به آن‌ها تابع روی هوا (on the fly) گفته می شود، به طور ساده تابعی است بدون‌نام. مانند مثال زیر:

این مفهوم در PHP تحت قالب Lambda  وClosures پیاده سازی شده است. در ادامه مطلب بیشتر به این مورد خواهیم پرداخت.

Lambada

یک Lambada تابع ناشناخته‌ای است که به یک متغیر انتساب داده می شود و یا به عنوان پارامتر به تابع دیگر انتساب داده می‌شود.

استفاده از Lambada

از آن جا که این مدل از تابع‌ها نام ندارند، پس شما نمی‌توانید مثل تابع‌های معمولی آن‌ها را صدا بزنید.

بلکه باید همینطور که قبلا به آن اشاره شد، تابع را به یک متغیر انتساب بدهید و یا به عنوان پارامتر به تابع دیگری ارسال کنید.

نکته: همینطور که در کد بالا هم مشاهده می کنید، سمی کالن (;) را بعد از اتمام تابع قرار می‌دهیم.

نکته: همینطور که در کد بالا هم مشاهده می کنید، می‌توانیم پارامتر به صورت دلخواه به تابع بدهیم (world$).

به منظور استفاده از تابع ناشناخته، ما این تابع را به یک متغیر انتساب میدهیم و سپس متغیر را به عنوان یک تابع، Call یا صدا میزنیم.

شما همچنین می‌توانید Lambadaایی که تعریف کرده‌اید را به عنوان پارامتر به تابع دیگر بفرستید:

برای چی من باید از Lambada استفاده کنم؟

شاید الان با خودتان گفتید که این تابع بدون اسم چه زمانی کارایی دارد؟

Lambada از تعریف تابع هایی که معمولا کد کوچک و مختصری دارند و ممکن است شما در طول اجرای برنامه، مثلا، فقط یکبار صدا بزنید، خودداری می کند. اغلب شما، به تابعی نیاز دارید که کاری را برای شما انجام دهد، اما این نیاز را پیدا نمی کنید که آن را داخل global scope برنامه یا حتی به عنوان بخشی از بقیه کدها اضافه کنید.

به جای اینکه تابعی داشته باشید که یک بار استفاده و بعد هم رها شود، میتوانید از Lambada استفاده کنید.

یک مورد پر استفاده دیگر توابع ناشناخته درfunction callbackها است.

اگر مفهوم توابع  callback در PHP را نمی‌دانید، یک جستجو راجع به آن انجام دهید، چرا که شرح کامل آن در این بحث نمی گنجد. اما یک نگاه سطحی با یک مثال به آن می‌اندازیم تا بحث بیشتر برایتان روشن شود.

Callback هر تابعی که صدا زده شده است توسط تابع دیگری که البته آن تابع دیگر، تابع اول را به عنوان پارامتر میگیرد و Call می‌کند. معمولا callback تابعی است که زمانی صدا زده می‌شود که اتفاقی رخ داده باشد، که در دنیای برنامه نویسی به آن اتفاق، رویداد یا event گفته میشود.

مثال زیر یک مثال پایه‌ایی از تابع‌های callback است:

شما می‌توانید تابعی که نامش در یک متغیر ذخیره شده است را call کنید. فقط کافیست به انتهای نام متغیر، پرانتز باز و بسته () اضافه کنید. مثل ()variable$

خب در مثال بالا، ما نام تابع thisFuncGetsCalled را به تابع ()thisFuncTakesACallback ارسال کردیم که سپس این تابع، تابعی که به آن فرستاده شده بود رو صدا زد.

از توابع ناشناخته در توابع بومی PHP استفاده شده، که مثال‌های فوق العاده‌ای در این زمینه هستند، از جمله array_walk, array_map, array_reduce و array_filter usort.

در مثال زیر نمونه‌ایی از callback function را مشاهده می‌کنید که با Lambada و در تابع array_filter پیاده سازی شده است.

نکته: کار array_filter به این صورت است که پارامتر اول یک آرایه مثلا input$ را می‌گیرد و در یک Loop قرار می‌دهد و هر دفعه مقدار فعلی آرایه را به function callback ارسال یا pass میکند. اگرfunction callback مقدار true برگرداند، value جاری خانه مورد نظر از آرایه برگردانده می‌شود. در ضمن keyهای آرایه هم تغییری نمی‌کنند.

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

در مثال بالا، عبارت { ;function ($v) { return $v > 2 یک Lambada است، که اگر میخواهید قابل استفاده مجدد باشد باید آن را داخل یک متغیر ذخیره کنید.

اطلاعات بیشتر:  پیشتر می‌توانستید از create_function در PHP استفاده کنید که اساسا همین کار را انجام میدهد.

Closure

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

همان طور که در بالا می بینید Closure می‌تواند به متغیر user$ دسترسی داشته باشد، به این دلیل که در عبارت use، تعریف تابع Closure آورده شده است.

همچنین اگر می‌خواهید مقدار متغیر user$ را داخل Closure تغییر بدهید و بیرون آن هم این تغییر از بین نرود، باید حتما قبل از متغیر داخل عبارت use یک & (امپرسند) قرار بدهید تا متغیر به صورت ارسال با مرجع فرستاده شود.

بیایید مثال array_filter را نیز با Closure انجام بدهیم.

در مثال بالا دو نکته را دیدید که یکی استفاده از توابع ناشناخته بصورت تودرتو و دیگری اینکه max$ به عنوان یک متغیر خارج از محدوده closure داخلی، مورد استفاده قرار گرفت.

مثالی از Closure در array_walk:

در مثال بالا تقریبا این نیاز احساس نمی‌شود که یک تابع بسازید که 2 عدد را در هم ضرب کند در حالی که فقط در یک جا مورد استفاده قرار میگیرد. با استفاده از یک Closure به عنوان callback، ما می‌توانیم تابع را یکبار استفاده کنیم و دیگر آن را فراموش کنیم.

استفاده از this$ در توابع ناشناخته

در نیمه اول سال 2012، یعنی زمانی که PHP به نسخه 5.4 خودش رسید، قابلیت جدیدی به توابع ناشناخته اضافه شد. بوسیله این قابلیت قادر هستید به راحتی با استفاده از this$ داخل تابع ناشناخته، به یک نمونه Object دسترسی داشته باشید.

استفاده در دنیای واقعی

یک مثال معروف از استفاده از این نوع توابع در routing درخواست ها در فریم ورک های مدرن است.

به عنوان مثال Laravel، به شما اجازه میده که مثل زیر عمل کنید:

کد بالا به سادگی با URLایی مثل user/Philip/، تطبیق داده می‌شود.

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

در دیگر زبان ها چطور؟

توابع ناشناخته در خیلی از زبانهای برنامه نویسی وجود دارند (از جمله پایتون، دلفی، جاوا، C و …) و اگر Ruby و Javascript کار کرده باشید حتما به آن‌ها برخوردید، چون در این زبان‌ها بسیار متداول هستند.

البته این نکته نیز ناگفته نماند که کاربرد آن در PHP، دقیقا همان کاربردی نیست که بقیه زبان ها از آن دارند.

نمونه‌ایی از تابع ناشناخته در jQuery:

jQuery callback

jQuery callback

امیدوارم از این مطلب استفاده و لذت کافی را برده باشید.

  • رهگذر می‌گه:

    احسنت. بسیار عالی بود. با سپاس فراوان

  • mohammad می‌گه:

    سلام جایی پیدا نکردم سوالمو مطرح کنم گفتم همینجا بگم
    میخوام چند مقدار به صورت مخفی ارسال کنم به این شکل انجام دادم ایا درسته

    <input type="hidden" value="” name=”select[]” />

    اینجا به هم ریخنه نشون میده ولی خودتون مرتبشو در نظر بگیرید
    نامشم بصورت ارایست select[] به همین شکل فقط نمیدونم موقع فرم ارسال میشه چطوری مقدارشو بخونم با فریچ نشد هر کاری کردم نشد مقداری رو که میخوام ازش در بیارم.
    لطفا راهنماییم کنید؟!

  • سلام به منم سر بزنید.
    این توابع رو توابع بی نام می نامند همچنین یه کاربرد دیگه ای هم که دارند این هست که میتونیم توابع رو به صورت ورودی توابع دیگر ارسال کرد.

  • جواد کاهن می‌گه:

    بابا این چقدر وسیع و عالی کار شده، خیلی جالب بود، من که عاشق پی اچ پی ام، اصن همچیش عالیه!

  • جالب بود، مرسی
    من اولای پست رو که داشتم میخوندم یه لحظه فکر کردم این همون چیزیه که توی جاوا اسکریپت هم هست، ولی جلوتر که رفتم دیدم خیلی وسیع تر کار شده 😉

  • آروین می‌گه:

    سلام.

    خیلی ممنون؛ نمی دونستم php هم از اینا داره :)

  • وحید می‌گه:

    خیلی عالی بود.
    باز هم از اینجور مطالب و در مورد لاراول بنویس آقا آرمان…

  • میثم می‌گه:

    سلام
    احسنت بسیار عالی توضیح دادید

    • محمود می‌گه:

      ممنون آرمان جان بابت این مطالبت!
      من استفاده از use رو بلد نبودم فقط و از global استفاده میکردم.

      شما آقای میثم محمودی نیستی احیاناً رزومه فرستاده بودید برای وب افروز؟

      که اینقدر دیر و زود کردید آخرشم نیومدید!!!

      اگه درست گفته باشم باید به حافظم امیدوار بشم :)


  • نظرات این مطلب بسته است.