| کانال توسعه‌دهندگان PHP |
1.72K subscribers
17 photos
36 links
⭕️ کانال توسعه‌دهندگان پی‌اچ‌پی (PHP) دولوپیکس

💠 دولوپیکس | جامعه توسعه‌دهندگان ایرانی

💎 @Developix
🚀 Developix.ir

📌 پشتیبانی و تبلیغات:
@DevelopixSupport
Download Telegram
یه مورد جذاب توی php رو باهم یاد بگیریم :)

توی php 8 به بعد یه ویژگی اضافه شده که شما میتونید هر کدوم از پارامتر فانکشن رو مقدار دهی کنید بزارید از روی تصویر و مثال بگم که بهتر متوجه بشید

ما یه function login داریم که چند تا ورودی میپذیره و دوتا از ورودی ها اپشنال هستن و مقدار دیفالت دارن حالا ما شاید میخوایم به اخرین مورد که مقدار دیفالت داره یه مقداری بدیم اون موقع چی؟

توی php های ورژن قبل مجبور بودیم همه رو مقدار دهی کنیم که به اون مورد برسیم یا که همون مقدار دیفالت رو بهشون بدیم (لاین 8)

اما توی php 8 یه فیچر اضافه شده که شما میتونید با زدن اسم متغییر و یک دو نقطه جلوش مقدار دهی کنید
جوری که توی لاین 14 میبینید

چند تا نکته داره
اگه از این مدل مقدار دهی استفاده کنید باید از اون به بعد رو هم به همین شکل مقدار دهی کنید
همون اسم متغییر رو میزنیم فقط بدون $
** توی فانکشن های خود php هم میتونید از این مورد استفاده کنید و لذت ببرید :))

👤 Matin Soleymani

💎 Channel: @DevelopixPHP
👍25🔥9
Forwarded from Developix Support
🔴 شتابان هاست 🔴

🔰 تخفیف ویژه 12 درصدی برای
خرید انواع🔹هاست🔹سرور
در شتابان هاست به مناسبت فرا رسیدن عید نوروز 🥳:


https://shetabanhost.com/
🌟 کد تخفیف اختصاصی:
shetabanhost


🔗 https://shetabanhost.com/

🌐 پشتیبانی ۲۴ ساعته شتابان هاست👇👇

☎️ 024-91311031
💎 Channel: @shetabanhostcom
31👍26🔥13
💢 آموزش‌ View Composer

یکی از نکاتی که باعث بهینه شدن پروژه می‌شود این است که درخواست‌های‌مان را به سمت سرور برای گرفتن اطلاعات از دیتابیس کم‌تر کنیم؛ موقعیتی را در نظر بگیرید که نیاز است یک سری اطلاعات از جدول مشخصی را به چندین ویو پاس بدهیم در این شرایط راحت‌ترین کاری که می‌شود کرد این است که در روت مربوط به همه ویو‌ها یک فانکشن ایجاد کنیم و برای هر کدام عمل کوئری انتخاب از دیتابیس را انجام دهیم و در نهایت داده دریافتی را به ویو‌های مربوطه Compact کنیم.

در این شرایط علاوه بر ارسال درخواست تکراری به سمت دیتابیس ما با کدهای تکراری روبه‌رو هستیم که از بهینه و تمیز بودن کدها کم می‌کند؛ مورد دومی که شاید به ذهن‌تان برسد این است که یک متغیر پابلیک ایجاد کنیم و یک بار درخواست ارسال کنیم و چندین جا از آن استفاده کنیم ولی عیبی که این روش دارد این است که این متغیر داخل همه ویوها/کلاس‌هایی که نیاز به آن متغیر ندارند هم قابل دسترس است و نمی‌توان به راحتی مشخص کرد که به کدام ویو‌ها این متغیر ارسال شود.

برای حل چنین عیب‌هایی می‌توان از View Composer ها استفاده کنیم با استفاده از این ویژگی لاراول می‌توانیم یک کلاس یا یک تابع Callback به پروژه‌ شناسایی کنیم و مشخص کنیم هر موقع یک View خاصی در حال رندر شدن بود آن کلاس یا تابع که به آن View Composer گفته می‌شود اجرا شود ( می‌توانید نتیجه اجرای ویو کامپوزر و ویوتان هم برای بهینه شدن بیشتر پروژه‌تان کش کنید تا LCP سایت‌تان کم‌تر هم شود )

🔺نوشتن View Composer

ویوکامپوزرها معمولا در Service Provider ها تعریف می‌شوند که بهتر است یک سرویس پرووایدر اختصاصی ایجاد کنیم و درنهایت آن را به لیست مربوطه اضافه کنیم، برای ایجاد یک سرویس پرووایدر اختصاصی از کد زیر استفاده کنید:
php artisan make:provider ViewServiceProvider

با زدن این دستور یک فایل با نام ViewServiceProvider در مسیر زیر ایجاد می‌شود:
app/providers

بعد از ساخت فایل مربوطه باید سرویس پرووایدر مان را به لاراول شناسایی کنیم برای این کار تنها کافی است که به فایل config/app.php برید و سرویس پرووایدر تان را به آرایه Providers اضافه کنید با این کار سرویس پرووایدر مربوطه به پروژه شناسایی می‌شود و وقت آن است که ویو کامپوزر دلخواه‌مان را ایجاد کنیم.

🔺ایجاد View Composer

برای ایجاد یک ویو کامپوزر تنها کافی است به ViewServiceProvider که در مرحله قبلی ایجاد کردیم برویم و در متد boot این فایل از متد composer که در کلاس view قرار دارد استفاده کنیم:

View::composer('header',
funcation($view) {

$Categories = Category::all();

$view->with([
'category' => $Categories
]);

});


🔺بررسی کد بالا

داخل پارامتر اول متد composer اسم ویو‌هایی که می‌خواهیم این دیتا را داشته باشند می‌نویسم لازم به ذکر است که می‌توان در این قسمت یک آرایه بنویسم و یا مشخص کنیم به کل ویو‌های یک پوشه این دیتا ارسال شود برای مثال:

View::composer(['panel.*', 'users.header'], ... )

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

🔗 اطلاعات بیشتر و داکیومنت مربوطه

👤 Maryam

💎 Channel: @DevelopixLaravel
👍7
💢 آدرس‌های امضاء شده در لاراول

فرض کنید یک سیستم خبرنامه دارید و کاربری درخواست لغو اشتراک خبرنامه را دارد، URL مربوطه می‌تواند به شکل زیر باشد:

example.com/unsubscribe/4

وقتی کاربری این URL را باز می‌کند اشتراک خبرنامه کاربری با آیدی 4 لغو خواهد شد، حالا فرض کنید کاربری از روی عمد آیدی 4 را به 60 تغییر بدهد، در این صورت اشتراک خبرنامه کاربری با آیدی 60 هم بدون اطلاع خودش لغو خواهد شد. این سناریو می‌تواند به مرور باعث لغو اشتراک خبرنامه کلیه کاربران شود؛ یکی از ویژگی‌هایی که لاراول برای جلوگیری از این خراب‌کاری دارد، آدرس‌های امضاء شده است؛ با استفاده از URL های امضا شده، می‌توان تا حدودی از درخواست‌های ایجاد شده با URL های اصلاح شده و همچنین از خراب‌کاری‌های احتمالی جلوگیری کرد.

🔺ساختن یک Signed URL

در مثال بالا فرض کردیم URL لغو اشتراک خبرنامه به شکل زیر است:

example.com/unsubscribe/4

در نتیجه روت آن به این شکل خواهد بود:

Route::get('unsubscribe/{user_id}', '...')->name('unsubscribe');

برای امضاء و امن کردن این URL باید از متد signedRoute که در کلاس URL قرار دارد استفاده کنیم:


$url = URL::signedRoute('unsubscribe', ['user_id' => 1]);


نتیجه کد بالا به شکل زیر خواهد داشت:

example.com/unsubcribe/1/?signature=f834ed8570e05de6c50ad10bd6abcf71e9867fcb14bdf2670b4bf572ce346f3b

و اگر کاربری این URL را تغییر داد به هیچ‌وجه معتبر نخواهد بود و می‌توان این‌گونه از خراب‌ کاری‌های احتمالی جلوگیری کرد؛ همچنین لازم به ذکر است که با متد temporarySignedRoute می‌توان یک تاریخ انقضاء برای URL مان مشخص کنیم و تعیین کنیم URL مربوطه تا چه زمانی می‌تواند معتبر باشد:

$url = URL::temporarySignedRoute(

'unsubscribe',

now()->addMinutes(60), ['user' => 1]

);


🔺 اعتبار سنجی‌ آدرس‌های امضاء شده

برای اعتبار سنجی آدرس‌های مربوطه می‌توانید از متد hasValidSignature که در کلاس Request قرار دارد استفاده کنید و بررسی کنید که URL مربوطه معتبر است یا خیر:

Route::get('unsubscribe/{user_id}/', function (Request $request) {

if (! $request->hasValidSignature()) {
abort(401);
}

// ...
});


همچنین می‌توانید از میدل‌ور ValidateSignature استفاده کنید تا عملیات اعتبارسنجی خودکار انجام برای استفاده کردن از این میدل‌ور فقط کافی است که به فایل Kernel.php بروید و کد زیر را اضافه کنید:

protected $routeMiddleware = [
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
....
];


و در نتیجه این میدلور را به روت‌تان اضافه کنید:

Route::get('unsubscribe/{user_id}', '...')->name('unsubscribe')->middleware('signed');

از حالا به بعد این روت زمانی به درستی کار خواهد کرد که مقدار پارامتر signature معتبر باشید در غیر این صورت خطای 403 به کاربر نمایش داده می‌شود.

📍همچنین یک نمونه بسیار ساده از آدرس‌های امضاء شده در این مخزن ایجاد کرده‌ام که طبق نیاز می‌توانید آن را تغییر داده و استفاده کنید

🔗 اطلاعات بیشتر و داکیومنت مربوطه

👤 Maryam

💎 Channel: @DevelopixLaravel
👍14🔥1
❇️ صد درصد در پروژه هایی که کار میکنید میخواید قیمت ها رو به فرمت درست نمایش بدید به عبارت دیگه میخوایم که سه رقم سه رقم جدا کنیم

✳️ برای این که با php فقط کافیه از یک تابع درونی خود php استفاده کنید به شرح زیر :
$price = 500000;
number_format($price);
# 500,000


⚜️ ممکنه بعضی مواقع قیمت به صورت string یا همون متنی در دیتابیس یا به نحو های دیگر قرار گرفته باشه برای استفاده از این تابعه نیاز هست که string رو به number تبدیل کنید که مثال این رو هم باهم خواهیم داشت:
$price = "500000";
number_format((int)$price)
# 500,000


برای مطالعه بیشتر لینک 📕

👤 Matin Soleymani

💎 Channel: @DevelopixPHP
👍171👎1
کلاس‌های انتزاعی (Abstract Classes) در PHP یکی از مفاهیم پایه‌ای در برنامه‌نویسی شی‌گرا هستند.
این کلاس‌ها به عنوان قالبی برای سایر کلاس‌ها عمل می‌کنند و نمی‌توان از آن‌ها به طور مستقیم نمونه‌سازی (Instantiate) کرد.
به بیان دیگر، شما نمی‌توانید یک شی مستقیم از یک کلاس انتزاعی ایجاد کنید.
هدف از کلاس‌های انتزاعی، تعریف یک قرارداد برای کلاس‌های وراثتی است تا اطمینان حاصل شود که تمام کلاس‌های فرزند، روش‌های خاصی را پیاده‌سازی می‌کنند.

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

مثال:

فرض کنید می‌خواهیم یک سیستم برای مدیریت حیوانات در یک باغ وحش ایجاد کنیم.
ما می‌توانیم یک کلاس انتزاعی به نام Animal داشته باشیم که توابع انتزاعی مانند makeSound را تعریف می‌کند. سپس، کلاس‌های فرزند می‌توانند این تابع را بر اساس نوع حیوان پیاده‌سازی کنند.

abstract class Animal {
protected $name;

public function __construct($name) {
$this->name = $name;
}

// تابع انتزاعی
abstract public function makeSound();

public function getName() {
return $this->name;
}
}

class Dog extends Animal {
public function makeSound() {
return "Woof";
}
}

class Cat extends Animal {
public function makeSound() {
return "Meow";
}
}

$dog = new Dog("Sag");
echo $dog->getName() . " says " . $dog->makeSound(); // Sag says Woof

$cat = new Cat("Goorbe");
echo $cat->getName() . " says " . $cat->makeSound(); // Goorbe says Meow
در این مثال، Animal یک کلاس انتزاعی است که نمی‌توان از آن نمونه‌سازی کرد. این کلاس یک تابع انتزاعی به نام makeSound تعریف می‌کند که هر کلاس فرزند باید آن را پیاده‌سازی کند. Dog و Cat دو کلاس فرزند هستند که از Animal ارث‌بری می‌کنند و تابع makeSound را پیاده‌سازی می‌کنند.


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

👤 AmirHossein

💎 Channel: @DevelopixPHP
🔥10👍32
اینترفیس‌ها (Interfaces) یکی دیگر از مفاهیم مهم برنامه نویسی شی‌گرا هستند. آنها به عنوان قراردادی بین کلاس‌ها عمل می‌کنند و تعیین می‌کنند که کلاس‌هایی که این اینترفیس‌ها را پیاده‌سازی می‌کنند، باید چه متدهایی را ارائه دهند، و اطمینان می‌دهند که کلاس‌های پیاده‌سازی‌کننده، تمام متدهای مورد نیاز را پیاده‌سازی کنند.

تفاوت با کلاس‌های انتزاعی:
یک کلاس می‌تواند چندین اینترفیس را پیاده‌سازی کند، در حالی که فقط می‌تواند از یک کلاس انتزاعی ارث‌بری کند.
اینترفیس‌ها فقط تعریف متدها را ارائه می‌دهند و هیچ پیاده‌سازی متدی ندارند، در حالی که کلاس‌های انتزاعی می‌توانند شامل پیاده‌سازی متدها باشند.
اینترفیس‌ها نمی‌توانند حاوی پراپرتی ها باشند و فقط میتواند ثابت هارا تعریف کند.

مثال:
فرض کنید می‌خواهیم یک سیستم برای مدیریت وسایل نقلیه ایجاد کنیم. ما می‌توانیم یک اینترفیس به نام VehicleInterface داشته باشیم که توابعی مانند start و stop را تعریف می‌کند. سپس، کلاس‌های مختلف وسایل نقلیه می‌توانند این اینترفیس را پیاده‌سازی کنند.

interface VehicleInterface {
public function start();
public function stop();
}

class Car implements VehicleInterface {
public function start() {
echo "Car started\n";
}

public function stop() {
echo "Car stopped\n";
}
}

class Bike implements VehicleInterface {
public function start() {
echo "Bike started\n";
}

public function stop() {
echo "Bike stopped\n";
}
}

$car = new Car();
$car->start(); // Car started
$car->stop(); // Car stopped

$bike = new Bike();
$bike->start(); // Bike started
$bike->stop(); // Bike stopped


در این مثال، VehicleInterface یک اینترفیس است که تعریف می‌کند هر وسیله نقلیه‌ای که آن را پیاده‌سازی می‌کند باید دارای متدهای start و stop باشد. کلاس‌های Car و Bike هر دو این اینترفیس را پیاده‌سازی می‌کنند و متدهای مورد نظر را ارائه می‌دهند. این ساختار اطمینان می‌دهد که هر وسیله نقلیه‌ای که از این اینترفیس پیروی می‌کند، قابلیت‌های اساسی مشترکی دارد.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍7🔥3
تریت‌ها (Traits) در PHP، مکانیزمی انعطاف‌پذیر برای اشتراک‌گذاری متدها بین کلاس‌ها هستند. تریت‌ها به شما اجازه می‌دهند کد های مشترک را به اشتراک بگذارید، بدون آنکه محدودیت‌های ارث‌بری را به همراه داشته باشند.

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

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

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

trait LoggerTrait {
public function log($message) {
echo "Log: $message\n";
}
}

trait HistoryTrait {
protected $history = [];

public function addHistory($event) {
$this->history[] = $event;
}

public function getHistory() {
return $this->history;
}
}

class UserActivity {
use LoggerTrait, HistoryTrait;

public function login($username) {
$this->log("User logged in: $username");
$this->addHistory("Login at " . date('Y-m-d H:i:s'));
}
}
// Other Classses ...

$userActivity = new UserActivity();
$userActivity->login('JohnDoe');
print_r($userActivity->getHistory());

Log: User logged in: JohnDoe

Array
(
[0] => Login at 2024-03-30 14:26:04
)


در این مثال، ما دو تریت LoggerTrait و HistoryTrait را تعریف کرده‌ایم. سپس، در کلاس UserActivity، از هر دو تریت با استفاده از کلمه کلیدی use استفاده کرده‌ایم. این کار به UserActivity امکان می‌دهد که هم از متدهای لاگ کردن و هم از قابلیت‌های مربوط به ثبت تاریخچه استفاده کند.

استفاده از تریت‌ها با حل تعارض:
گاهی اوقات، دو تریت ممکن است متدهایی با نام یکسان داشته باشند. PHP امکان مدیریت این تعارض‌ها را با استفاده از عبارت insteadof فراهم می‌آورد. همچنین، می‌توانید با استفاده از عبارت as نام یک متد را در کلاس استفاده‌کننده تغییر دهید.
trait A {
public function doSomething() {
echo "Doing something from A\n";
}
}

trait B {
public function doSomething() {
echo "Doing something from B\n";
}
}

class SampleClass {
use A, B {
A::doSomething insteadof B;
// استفاده از متد doSomething از تریت A و نادیده گرفتن آن از تریت B
B::doSomething as doSomethingFromB;
// تغییر نام متد doSomething از تریت B به doSomethingFromB
}
}

$sample = new SampleClass();
$sample->doSomething();
// Doing something from A
$sample->doSomethingFromB();
// Doing something from B

در این مثال، کلاس SampleClass هر دو تریت A و B را استفاده می‌کند. از آنجا که هر دو تریت متدی با نام doSomething دارند، ما با یک تعارض مواجه هستیم.
برای حل این تعارض، ما از عبارت insteadof استفاده می‌کنیم تا مشخص کنیم که می‌خواهیم از پیاده‌سازی متد doSomething در تریت A استفاده کنیم و پیاده‌سازی آن در تریت B را نادیده بگیریم.
همچنین، با استفاده از عبارت as، متد doSomething از تریت B را به doSomethingFromB تغییر نام می‌دهیم تا همچنان بتوانیم به آن دسترسی داشته باشیم، اما با نام جدید.

👤 AmirHossein

💎 Channel: @DevelopixPHP
🔥9👍2
‏Enum‌ها، که مخفف Enumerations هستند، در PHP 8.1 به عنوان یک ویژگی جدید معرفی شدند. Enum‌ها به شما امکان می‌دهند یک مجموعه محدود از مقادیر ممکن را برای یک متغیر تعریف کنید. این امر به تسهیل خوانایی کد، جلوگیری از خطاها و افزایش امنیت نوع داده‌ها کمک می‌کند.

نحوه تعریف:
برای
تعریف یک Enum در PHP، از کلمه کلیدی enum استفاده می‌کنیم. می‌توانیم مقادیر مختلفی را به عنوان بخشی از Enum تعریف کنیم:
enum Status: string {
case Pending = 'pending';
case Processing = 'processing';
case Complete = 'complete';
case Cancelled = 'cancelled';
}

در این مثال، یک Enum به نام Status با چهار حالت مختلف تعریف شده است. هر کیس (case) در Enum یک مقدار ثابت را نمایندگی می‌کند.

کاربردها:
ز
مانی که می‌خواهید متغیرهایی داشته باشید که فقط می‌توانند از میان یک مجموعه محدود از مقادیر انتخاب شوند میتوانید از enum ها استفاده کنید.

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

از آنجا که Enum‌ها فقط مقادیر مشخصی را می‌پذیرند، احتمال خطا در انتخاب مقادیر نامعتبر کاهش می‌یابد.

مثال:
enum Status: string {
case Pending = 'pending';
case Processing = 'processing';
case Complete = 'complete';
case Cancelled = 'cancelled';
}

function updateOrderStatus(Status $status) {
echo "Order status: " . $status->value . PHP_EOL;
}

updateOrderStatus(Status::Processing);


در این مثال، تابع updateOrderStatus یک پارامتر از نوع Status می‌پذیرد و مقدار آن را چاپ می‌کند.

استفاده در سوئیچ کیس‌ها:
‏Enum
‌ها را می‌توان به راحتی در ساختارهایی مانند سوئیچ (switch) استفاده کرد:
enum Status: string {
case Pending = 'pending';
case Processing = 'processing';
case Complete = 'complete';
case Cancelled = 'cancelled';
}

$status = Status::Cancelled;

switch ($status) {
case Status::Pending:
echo "Order is pending.";
break;
case Status::Processing:
echo "Order is being processed.";
break;
case Status::Complete:
echo "Order is complete.";
break;
case Status::Cancelled:
echo "Order has been cancelled.";
break;
}

در این مثال، بر اساس مقدار Status، پیام متفاوتی چاپ می‌شود. استفاده از Enum‌ها در سوئیچ کیس‌ها به کد شما اجازه می‌دهد تا به صورت واضح و مطمئن شرایط مختلف را بررسی کند.

‏Enum‌ها، ابزار قدرتمندی برای مدیریت مجموعه‌های محدود از مقادیر هستند و به توسعه‌دهندگان کمک می‌کنند تا کدی ایمن‌تر، خواناتر و قابل نگهداری‌تر بنویسند.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍15🔥1
کلاس‌های final در PHP امکانی را فراهم می‌کنند که از ارث‌بری یک کلاس جلوگیری شود. این ویژگی برای طراحی دقیق‌تر و کنترل شده‌تر ارث‌بری در برنامه‌های شی‌گرا استفاده می‌شود.

نحوه تعریف:
یک
کلاس final با استفاده از کلمه کلیدی final قبل از کلمه class در تعریف کلاس ایجاد می‌شود:

final class MyClass {
// تعاریف و متدهای کلاس
}


کاربردها:
زمانی که نمی‌خواهید کلاس‌های دیگر بتوانند از کلاس مورد نظر ارث‌بری کنند. این امر می‌تواند برای حفظ امنیت، استقرار یک API ثابت، یا جلوگیری از استفاده نادرست از کلاس در زیرکلاس‌ها مفید باشد.

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

تفاوت‌ها با کلاس‌های عادی:
تفاوت
اصلی بین کلاس‌های final و کلاس‌های عادی در قابلیت ارث‌بری آن‌ها است. در حالی که کلاس‌های عادی می‌توانند به عنوان پایه برای کلاس‌های دیگر استفاده شوند، کلاس‌های final این قابلیت را ندارند. این محدودیت به شما کمک می‌کند تا اطمینان حاصل کنید که کلاس‌هایتان به شیوه‌ای که مد نظر دارید استفاده می‌شوند و نباید تغییر کنند یا گسترش یابند.

در برخی موارد، موتور Zend Engine که PHP بر روی آن اجرا می‌شود، می‌تواند کلاس‌های final را بهینه‌تر اجرا کند، زیرا نیازی به جستجو برای متدهای override شده در کلاس‌های فرزند نیست.

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

final class DatabaseConnection {
private $connection;
private $host = 'localhost';
private $username = 'root';
private $password = 'password';
private $database = 'my_database';

public function __construct() {
$this->connection = new mysqli($this->host, $this->username, $this->password, $this->database);

if ($this->connection->connect_error) {
die("Connection failed: " . $this->connection->connect_error);
}
}

public function getConnection() {
return $this->connection;
}

// دیگر متدهای مربوط به اتصال به پایگاه داده...
}

در این مثال، کلاس DatabaseConnection به عنوان یک کلاس final تعریف شده است. این بدان معناست که هیچ کلاس دیگری نمی‌تواند از این کلاس ارث‌بری کند. این امر اطمینان می‌دهد که روش اتصال به پایگاه داده در سراسر برنامه ثابت و قابل اعتماد باقی می‌ماند و از تغییرات ناخواسته جلوگیری می‌کند.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍142
کلاس های readonly در PHP به شما اجازه می‌دهد ویژگی‌هایی در کلاس‌ها تعریف کنید که فقط می‌توانند در زمان ساخت شیء مقداردهی اولیه شوند و پس از آن، تغییرناپذیر هستند. این ویژگی برای تعریف کلاس‌هایی که داده‌های آن‌ها نباید تغییر کنند، بسیار مفید است. به این ترتیب، readonly در PHP، شما را قادر می‌سازد تا ویژگی‌های فقط‌خواندنی در کلاس‌هایتان داشته باشید.

نحوه تعریف:
یک کلاس readonly با استفاده از کلمه کلیدی readonly قبل از کلمه class در تعریف کلاس ایجاد می‌شود:
readonly class MyClass
{

}

کاربردها:
کلاس
‌های Read-Only به شما اجازه می‌دهند که اشیاء‌ای با ویژگی‌هایی که فقط برای خواندن هستند، ایجاد کنید. این ویژگی به ویژه برای مواردی مفید است که می‌خواهید اطمینان حاصل کنید داده‌های یک شیء پس از ایجاد آن، تغییر نکنند. این موضوع می‌تواند در برنامه‌نویسی نرم‌افزار برای محافظت از داده‌ها و جلوگیری از تغییرات ناخواسته مفید باشد.

تفاوت ها با کلاس عادی:
1- پراپرتی ها در کلاس های readonly نمیتوانند مقداردهی شوند یا مقدار انها را حذف کرد:
 readonly class MyClass { /* … */ }

$myClass = new MyClass(/* … */);

// Error :Cannot declare dynamic properties in 'readonly' class
$myClass->title = 'other';
unset($myClass->title);


2- تعریف پراپرتی ها در کلاس readonly تنها با تعریف تایپ آنها امکان پذیر است:
readonly class MyClass
{
public string $title;

// Error: 'readonly' property must have type specified
public $mixed;
}


3- از آنجایی که ویژگی های readonly نمی توانند static باشند، کلاس های readonly نمی توانند هیچ ویژگی static داشته باشند:
readonly class MyClass
{
// Error: Cannot declare 'static' properties in 'readonly' class
public static string $title;
}


4- ویژگی‌های یک کلاس readonly نمی‌توانند مقدار پیش‌فرض داشته باشند مگر اینکه از promoted properties استفاده کنید:
readonly class MyClass
{
// Error: 'readonly' property cannot have default value
public string $title = 'default';
}

// promoted properties:
readonly class MyClass
{
public function __construct(
public string $title = 'default', // This works
) {}
}


5- نمیتوان یک کلاس عادی را با readonly ادغام (extends) کرد مگر هر دو کلاس readonly باشند:
readonly class MyClass { /* … */ }

// Error: Non-'readonly' class cannot extend readonly class 'MyClass'
class OtherClass extends MyClass { /* … */ }


مثال:
فرض کنید یک کلاس برای مدیریت توکن ها دارید، و نمیخواید توکن ها تغییر کنند.
در این صورت میتوانید از readonly class استفاده کنید تا اطمینان داشته باشید در طول اجرای برنامه توکن تغییر نمیکند:
readonly class Token
{
public string $token;
public function __construct()
{
$this->token = 'ASDHAJKSHJDKHAJKSDHKAJSDJKADJKKJHDKJ';
}
}
echo (new Token())->token;


👤 AmirHossein

💎 Channel: @DevelopixPHP
8👍1
کلاس‌های ناشناس یا انانیموس در PHP، امکان تعریف کلاس‌هایی را می‌دهند که نام خاصی ندارند و بلافاصله پس از تعریف، نمونه‌سازی می‌شوند. این قابلیت اولین بار در PHP 7 معرفی شد و به توسعه‌دهندگان اجازه می‌دهد برای استفاده‌های یک‌باره یا محدود، سریع‌تر و منعطف‌تر کلاس تعریف کنند.

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

یک نمونه کلاس بی نام در زیر آماده هست:
$class = new class {

}

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

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

در زمان تعریف کلاس نمونه‌سازی می‌شوند و نمی‌توانند مجدداً نمونه‌سازی شوند مگر اینکه تعریف کلاس مجدداً انجام شود.

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

interface Greeting {
public function sayHello();
}

// استفاده از کلاس ناشناس که اینترفیس Greeting را پیاده‌سازی می‌کند
$greeting = new class implements Greeting {
public function sayHello() {
return "Hello, Anonymous Class!";
}
};

echo $greeting->sayHello();

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

در مثال دیگر میتوانیم یک کلاس ناشناس را به عنوان ورودی به یک تابع بدهیم:

my_function(new class {

});

عملکرد آنها دقیقا مشابه تابع های ناشناس (Anonymous function) یا (closure) می باشد.

اگر با Anonymous function ها آشنایی ندارید یا آشنایی کمی دارید در کامنت ها اطلاع دهید تا یک پست برای آنها نیز آماده کنیم.

👤 AmirHossein

💎 Channel: @DevelopixPHP
5
کلوژرها در PHP یکی از انواع مفید و قدرتمند توابع ناشناس هستند. کلوژرها به شما امکان می‌دهند توابعی بنویسید که می‌توانند متغیرهای خارجی از دامنه‌ی تعریف شده خود را "بگیرند" یا استفاده کنند، حتی اگر این متغیرها در دامنه‌ی global تعریف نشده باشند.

نحوه تعریف:
یک
کلوژر در PHP با استفاده از کلمه کلیدی function بدون نام فانکشن تعریف می‌شود. می‌توان آن را به یک متغیر اختصاص داد و مانند هر فانکشن دیگری، با فراخوانی نام متغیر می‌توان آن را اجرا کرد.

$my_function = function () {
// Code
};


تفاوت با توابع عادی:
تفاوت
اصلی کلوژرها با توابع عادی در این است که کلوژرها می‌توانند متغیرهای خارج از دامنه‌ی تعریف شده‌ی خود را با استفاده از کلیدواژه use "بگیرند". این امر باعث می‌شود کلوژرها برای پیاده‌سازی پترن‌های طراحی خاص و برای مواردی که نیاز به حفظ حالت بین اجراها است، مناسب باشند.

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

آرگومان های ورودی‌ها و کلمه کلیدی use:
مانند
توابع عادی، کلوژرها می‌توانند پارامترهای ورودی داشته باشند. این پارامترها در زمان فراخوانی کلوژر به آن ارسال می‌شوند.
$my_function = function ($text) {
echo $text
};
$my_function('hello');
// hello


برای دسترسی به متغیرهای خارج از دامنه‌ی کلوژر، از کلمه کلیدی use استفاده می‌شود. این متغیرها در زمان تعریف کلوژر به آن "بسته" می‌شوند و مقادیر آنها حفظ می‌شود، حتی اگر بعداً تغییر کنند.
$text  = 'hello',
$my_function = function () use ($text) {
echo $text
};
$my_function();
// hello


مثال:
فرض کنید می‌خواهیم یک کلوژر بنویسیم که یک عدد را به عنوان ورودی گرفته و آن را با عدد دیگری که در زمان تعریف کلوژر مشخص شده، جمع کند.

$anotherNumber = 5;
$addition = function ($number) use ($anotherNumber) {
return $number + $anotherNumber;
};

echo $addition(3); // 8


کلوژ هارا میتوان به عنوان ورودی به متد ها یا توابع دیگر ارسال کرد:
function execute($action) {
$action();
}

execute(function () {
echo 'hello';
});

———
‏Arrow functions، یک قابلیت نوین و ساده‌تر برای نوشتن توابع ناشناس (Anonymous functions) هستند. این توابع به خصوص برای تعریف توابع کوچک و کاربردی طراحی شده‌اند که می‌توانند بلافاصله اجرا شوند.

نحوه تعریف:
‏Arrow
functions با استفاده از کلمه کلیدی fn به جای کلمه‌کلیدی function تعریف می‌شوند. ساختار کلی آنها به این شکل است:
$function = fn($arg1, $arg2, ...) => expression;


بدنه‌ی arrow function تنها شامل یک عبارت (expression) است و نیازی به استفاده از return برای برگرداندن نتیجه نیست. نتیجه‌ی این عبارت به طور خودکار برگردانده می‌شود.

تفاوت با فانکشن‌های عادی:
‏Arrow
functions بر خلاف توابع عادی، همیشه ناشناس هستند.
نتیجه به طور خودکار برگردانده می‌شود، بدون نیاز به استفاده از return.

تفاوت با کلوژرها:
‏Arrow functions به طور خودکار تمام متغیرهای مورد استفاده را از دامنه‌ی بیرونی "می‌گیرند"، بنابراین نیازی به استفاده از کلمه‌کلیدی use نیست.
کوتاه‌تر و مختصرتر از کلوژرها هستند و برای تعاریف تک خطی بهینه شده‌اند.

مثال :
فرض
کنید می‌خواهیم یک آرایه از اعداد را دو برابر کنیم. می‌توانیم از arrow function در تابع array_map استفاده کنیم:
$numbers = [1, 2, 3, 4];
$doubled = array_map(fn($number) => $number * 2, $numbers);

print_r($doubled);
//Array ( [0] => 2 [1] => 4 [2] => 6 [3] => 8 )


در این مثال، ما از یک arrow function به عنوان callback در array_map استفاده کردیم تا هر عنصر آرایه را دو برابر کنیم. این نمونه نشان دهنده‌ی سادگی و کارایی بالای arrow functions در PHP برای انجام عملیات‌های مختصر و مفید است. Arrow functions به ویژه هنگام کار با آرایه‌ها، کالکشن‌ها و دیتا استراکچرهایی که نیاز به ترانسفورمیشن دارند، مفید هستند.

👤 AmirHossein

💎 Channel: @DevelopixPHP
🔥42👍1
در‏ ‏PHP‏، parent, static, self‏, و $this کلیدواژه‌هایی هستند که برای دسترسی به ویژگی‌ها و متدهای مختلف کلاس‌ها استفاده می‌شوند. در اینجا توضیح و مثالی برای هر یک ارائه داده شده:

‏$this:
کلیدواژه $this به نمونه فعلی کلاس اشاره دارد. از این برای دسترسی به ویژگی‌ها و متدهای غیر استاتیک درون یک کلاس استفاده می‌شود.

مثال:
class Car {
public $color;

public function setColor($color) {
$this->color = $color;
}

public function getColor() {
return $this->color;
}
}

$car = new Car();
$car->setColor('blue');
echo $car->getColor(); // خروجی: blue

------
‏self:
کلیدواژه self به کلاسی اشاره دارد که در آن استفاده شده است. برای دسترسی به ویژگی‌ها و متدهای استاتیک کلاس مورد استفاده قرار می‌گیرد.

مثال:
class Car {
public static $number_of_cars = 0;

public function __construct() {
self::$number_of_cars++;
}

public static function getNumberOfCars() {
return self::$number_of_cars;
}
}

new Car();
new Car();
echo Car::getNumberOfCars(); // خروجی: 2

------

parent:
کلیدواژه parent برای دسترسی به ویژگی‌ها و متدهای کلاس والد استفاده می‌شود. معمولاً در زمینه‌هایی به کار می‌رود که وراثت مطرح است و می‌خواهیم به یک متد یا ویژگی در کلاس والد دسترسی داشته باشیم که در کلاس فرزند override شده است.

مثال:
class Vehicle {
protected function startEngine() {
echo "Engine started";
}
}

class Car extends Vehicle {
public function startEngine() {
parent::startEngine();
echo " and Car is ready!";
}
}

$car = new Car();
$car->startEngine(); // خروجی: Engine started and Car is ready!

------
‏static:
کلیدواژه static در جایی استفاده می‌شود که می‌خواهیم به ویژگی‌ها و متدهای استاتیک کلاس در حال اجرا دسترسی داشته باشیم، به ویژه در زمینه‌های وراثت که ممکن است نوع کلاس فرزند متفاوت باشد. static در زمان اجرا حل می‌شود و به کلاسی اشاره دارد که متد را فراخوانی کرده است.

مثال:
class Vehicle {
public static function who() {
echo "I am a Vehicle";
}

public static function test() {
static::who(); // دیر حل‌شدن: اینجا به "Vehicle" اشاره دارد
}
}

class Car extends Vehicle {
public static function who() {
echo "I am a Car";
}
}

Car::test(); // خروجی: I am a Car

در مثال بالا، با استفاده از static::who(), کلاس Car به جای Vehicle تشخیص داده شده است زیرا static به کلاسی اشاره دارد که متد در آن فراخوانی شده است. این مکانیزم به عنوان "Late Static Binding" شناخته می‌شود و به PHP اجازه می‌دهد که در زمان اجرا تصمیم بگیرد که کدام ورژن از متد باید استفاده شود، بر اساس کلاسی که متد را فراخوانی کرده، نه بر اساس کلاسی که متد در آن تعریف شده است.

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

برای درک بهتر static و self را در کنار هم میگذاریم:
class BaseClass {
public static function who() {
echo "I am a BaseClass";
}

public static function test() {
self::who(); // این همیشه به BaseClass اشاره دارد.
static::who(); // این می‌تواند به کلاس فرزند اشاره داشته باشد اگر override شده باشد.
}
}

class ChildClass extends BaseClass {
public static function who() {
echo "I am a ChildClass";
}
}

ChildClass::test();

خروجی این کد:
I am a BaseClass
I am a ChildClass

اولین خط با استفاده از self::who() همیشه به متد who() در BaseClass اشاره دارد، در حالی که دومین خط با استفاده از static::who() به متد who() در ChildClass اشاره دارد زیرا این متد در کلاس فرزند override شده است. این مثال نشان می‌دهد که چگونه self و static می‌توانند به طور متفاوتی عمل کنند و چرا static در موارد وراثت بسیار مفید است.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍94🔥2
کلون کردن (cloning) به روندی اشاره دارد که در آن یک نسخه دقیق از یک شیء موجود ایجاد می‌شود.
زمانی که یک شیء کلون می‌شود، یک شیء جدید با مقادیر خصوصیت‌های یکسان ایجاد می‌شود، اما این شیء جدید و اصلی در دو آدرس مموری مختلف قرار دارند، به این معنی که تغییرات بعدی در هر شیء تأثیری بر دیگری نخواهد داشت، مگر اینکه خصوصیات مرجع به اشتراک گذاشته شده باشند (مانند شیء‌هایی که از کلاس‌های دیگر، آرایه‌ها یا شیء‌های استاندارد تشکیل شده‌اند).

برای کلون کردن یک شیء در PHP، کلمه کلیدی clone استفاده می‌شود.
$object = new MyClass();
$cloned_object = clone $object;

کاربرد ها:
ایجاد نسخه‌های مستقل برای انجام عملیات‌هایی که نباید تأثیری بر نسخه اصلی داشته باشند.

جلوگیری از تغییرات ناخواسته در شیء اصلی زمانی که آن را به یک تابع می‌فرستید که ممکن است خصوصیات آن را تغییر دهد.

ساده‌سازی ایجاد نمونه‌های مشابه با خصوصیات مشترک به جای ایجاد دستی آن‌ها.

مثال کاربردی:
class Car {
public $model;
public $color;

public function __construct($model, $color) {
$this->model = $model;
$this->color = $color;
}
}

$originalCar = new Car('Ford', 'Red');
$clonedCar = clone $originalCar;
$clonedCar->color = 'Blue';

echo $originalCar->color; // خروجی: Red
echo $clonedCar->color; // خروجی: Blue

در این مثال، ما یک نمونه از کلاس Car ایجاد کردیم و آن را کلون کردیم. هر شیء حالا مستقل است و تغییر رنگ در $clonedCar تأثیری بر $originalCar ندارد.

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

کلون بصورت پیش‌فرض یک کپی سطحی است، ویژگی‌های پریمیتیو (مانند اعداد و رشته‌ها) به طور مستقل کپی می‌شوند، اما ویژگی‌هایی که به اشیاء یا آرایه‌های دیگر اشاره می‌کنند، به همان مراجع اصلی اشاره خواهند داشت.
کپی سطحی می‌تواند به مشکلاتی منجر شود اگر شما تغییراتی در یک شیء کلون شده ایجاد کنید که مراجع مشترک با شیء اصلی دارد؛ تغییرات می‌تواند بر شیء اصلی تأثیر بگذارد.
برای جلوگیری از این موضوع، ممکن است لازم باشد که یک کپی عمیق از شیء ایجاد کنید، به این معنی که هر شیء داخلی نیز به طور مستقل کپی می‌شود.در PHP، اگر می‌خواهید رفتار کلون کردن را کنترل کنید یا کپی عمیق را انجام دهید، می‌توانید از مجیک متد clone استفاده کنید. وقتی شما یک شیء را کلون می‌کنید، اگر مجیک متد clone در کلاس آن شیء تعریف شده باشد، به طور خودکار فراخوانی می‌شود. شما می‌توانید در این متد تعریف کنید که چه اتفاقی باید برای خصوصیات ارجاعی در هنگام کلون کردن بیفتد.

توضیحات و مثال های مربوط به مجیک متد __clone در پست های بعدی با مبحث مجیک متد ها داده میشود.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍5
مجیک متدها (Magic Methods) در PHP توابعی هستند که به طور خودکار در پاسخ به برخی رویدادهای خاص در شیء فراخوانی می‌شوند.
این توابع با دو علامت زیرخط (__) شروع می‌شوند. مجیک متدها به برنامه‌نویسان اجازه می‌دهند تا رفتارهای خاصی را در زمان اجرا، مانند ساختن یک شیء یا نابودی آن، اضافه، تغییر یا حذف خصوصیات و غیره، به کلاس‌های خود اضافه کنند.

در ادامه توضیحات کاملی برای هر یک از مجیک متد ها داده میشود.
اگرچه همه شما با مجیک متد های __construct و __destruct آشنا هستید ولی لازم است توضیحاتی برای آنها نیز داده شود.

متد __construct به عنوان سازنده کلاس عمل می‌کند و به محض ایجاد نمونه‌ای از کلاس فراخوانی می‌شود. این متد معمولاً برای اولیه‌سازی خصوصیات شیء و انجام تنظیمات اولیه استفاده می‌شود.

مثال:
class Person {
public $name;
public $age;

public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}

public function greet() {
return "Hello, my name is " . $this->name . " and I am " . $this->age . " years old.";
}
}

$person = new Person("John", 30);
echo $person->greet();


متد __construct زمانی فراخوانی می‌شود که یک نمونه جدید از کلاس Person ساخته می‌شود. این متد دو پارامتر name و age را می‌گیرد و آن‌ها را به خصوصیات شیء اختصاص می‌دهد.
این روش برای اولیه‌سازی شیء با داده‌های اولیه استفاده می‌شود.
متد greet یک پیام خوش‌آمدگویی تولید می‌کند که نام و سن شخص را شامل می‌شود که در متد __construct مقدار دهی شده است.

———

متد __destruct نابودکننده کلاس است و زمانی فراخوانی می‌شود که شیء دیگر مورد استفاده قرار نگیرد یا اسکریپت به پایان برسد. این متد معمولاً برای انجام پاک‌سازی، آزادسازی منابع یا سایر تنظیمات پایانی قبل از از بین رفتن شیء استفاده می‌شود.

مثال:
class FileHandler {
private $file;

public function __construct($filename) {
$this->file = fopen($filename, 'w');
}

public function write($data) {
fwrite($this->file, $data);
}

public function __destruct() {
fclose($this->file);
echo "File closed.\n";
}
}

$file = new FileHandler("example.txt");
$file->write("Hello World");
// Result: "File closed."


متد __construct برای باز کردن یک فایل جدید یا موجود استفاده می‌شود و فایل را در پراپرتی file ذخیره میکند.
متد write داده‌ای که به آن داده شده را در فایل می‌نویسد.
و در نهایت که شئ کاری برای انجام دادن ندارد و اسکریپت به پایان میرسد متد __destruct فراخوانی می‌شود و فایل باز شده را می بندد و پیام File closed. را چاپ میکند.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍9
مجیک متدهای __call و __callStatic در PHP برای دستکاری نحوه پاسخگویی کلاس‌ها به فراخوانی متدهایی که به صورت مستقیم تعریف نشده‌اند یا اصلا وجود ندارند، استفاده می‌شوند. این دو متد به شما اجازه می‌دهند تا رفتار انعطاف پذیرتری را در کلاس‌های خود ایجاد کنید.

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

public function __call($name, $arguments)
{

}


مثال:
class Person {
private $data = [
"name" => "John",
"age" => 30
];

public function __call($method, $params) {
if (array_key_exists($method, $this->data)) {
return $this->data[$method];
} else {
return "Method $method does not exist!";
}
}
}

$person = new Person();
echo $person->name(); // Outputs: John
echo $person->age(); // Outputs: 30
echo $person->height(); // Outputs: Method height does not exist!


در این مثال، کلاس Person دارای یک آرایه خصوصی $data است که حاوی اطلاعات است. وقتی که سعی می‌کنید به متدی دسترسی پیدا کنید که مستقیماً تعریف نشده‌است، متد __call فراخوانی می‌شود.
در این مثال همانطور که می بینید متد های name و age و height تعریف نشده اند ولی به واسطه متد __call مدیریت میشوند.
این متد چک می‌کند که آیا نام متد فراخوانی شده به عنوان کلید در آرایه $data وجود دارد یا خیر. اگر وجود داشته باشد، مقدار مربوطه را برمی‌گرداند و اگر نباشد، پیام خطا می‌دهد.

———

مجیک متد __callStatic:
مجیک متد __callStatic مشابه __call است، اما برای متدهای استاتیک که وجود ندارند یا قابل دسترسی نیستند فراخوانی می‌شود.

این متد نیز همانند __call دو ورودی که به ترتیب نام متد فراخوانی شده و آرگومان های متد فراخوانی شده هستند را دریافت میکند.
ساختار آن به صورت زیر است:
public static function __callStatic($name, $arguments)
{

}


مثال:
class Utility {
private static $data = [
"pi" => 3.14159,
"e" => 2.71828
];

public static function __callStatic($method, $params) {
if (array_key_exists($method, self::$data)) {
return self::$data[$method];
} else {
return "Static method $method does not exist!";
}
}
}

echo Utility::pi(); // Outputs: 3.14159
echo Utility::e(); // Outputs: 2.71828
echo Utility::golden(); // Outputs: Static method golden does not exist!


در این مثال، کلاس Utility دارای یک آرایه خصوصی استاتیک $data است. وقتی به متد استاتیکی که تعریف نشده دسترسی پیدا می‌کنید، __callStatic فعال می‌شود. این متد بررسی می‌کند که آیا نام متد به عنوان کلید در $data وجود دارد. اگر بله، مقدار مربوطه را برمی‌گرداند و اگر نه، پیام خطا می‌دهد.


مجیک متدهای __call و __callStatic در PHP برای مدیریت دسترسی به متدهایی که به صورت مستقیم در کلاس تعریف نشده‌اند بسیار کاربردی هستند. این متدها اجازه می‌دهند که رفتار کلاس را در هنگام فراخوانی متدهای ناموجود کنترل کنید، و به شما امکان می‌دهند به شیوه‌ای انعطاف‌پذیر به آنها پاسخ دهید. این قابلیت خصوصاً مفید است در طراحی کلاس‌هایی که به نوعی به داده‌های دینامیکی کار می‌کنند یا نیاز به رابط‌های برنامه‌نویسی انعطاف‌پذیر دارند ( مانند کلاسی برای استفاده از متد های API تلگرام به جای تعریف همه متد ها ).

👤 AmirHossein

💎 Channel: @DevelopixPHP
6👍3🔥1
در PHP، مجیک متد‌های __get و __set برای دسترسی به پراپرتی که به طور مستقیم قابل دسترسی نیستند یا وجود خارجی ندارند، استفاده می‌شوند. این مجیک متدها اجازه می‌دهند تا شما در هنگام دسترسی یا تنظیم مقادیر پراپرتی کلاس، کنترل بیشتری داشته باشید. به عبارت دیگر، وقتی خواسته می‌شود که به یک پراپرتی دسترسی پیدا شود که تعریف نشده است یا دسترسی مستقیم به آن امکان‌پذیر نیست، این متد‌ها فعال می‌شوند.

مجیک متد __get:
این مجیک متد زمانی فراخوانی می‌شود که سعی می‌کنید به یک پراپرتی که وجود ندارد یا خصوصی است، دسترسی پیدا کنید.

مثال:
class User {
private $data = [
"name" => "John Doe",
"email" => "john@example.com"
];

public function __get($name) {
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
} else {
return null;
}
}
}

$user = new User();
echo $user->name; // Outputs: John Doe
echo $user->email; // Outputs: john@example.com
echo $user->age; // Outputs: null


در این مثال، هرگاه که می‌خواهیم به name یا email دسترسی پیدا کنیم، مجیک متد __get فراخوانی شده و مقدار مربوطه برگردانده می‌شود. اگر پراپرتی وجود نداشته باشد، null برگردانده می‌شود.

مجیک متد __set:
این مجیک متد زمانی فراخوانی می‌شود که سعی می‌کنید مقدار یک پراپرتی که وجود ندارد یا خصوصی است را تنظیم کنید.

مثال:
class User {
private $data = [
"name" => "John Doe",
"email" => "john@example.com"
];

public function __set($name, $value) {
if (array_key_exists($name, $this->data)) {
$this->data[$name] = $value;
}
}
}

$user = new User();
$user->name = "Jane Doe"; // changes the name property
echo $user->name; // Outputs: Jane Doe


در این مثال، مقدار name از طریق مجیک متد __set تغییر می‌کند. اگر پراپرتی وجود نداشته باشد، امکان افزودن یا تغییر آن وجود ندارد و می‌توانید خطایی را لاگ یا اکسپشن بیندازید.

مثال تکمیلی:
class Product {
private $data = [];

public function __set($key, $value) {
switch ($key) {
case "price":
if (!is_numeric($value) || $value < 0) {
throw new Exception("Invalid price");
}
break;
case "name":
$value = trim(strip_tags($value));
break;
}
$this->data[$key] = $value;
}

public function __get($key) {
return $this->data[$key] ?? null;
}
}

$product = new Product();
$product->name = "New <b>Product</b>"; // HTML tags will be removed
$product->price = 20;

echo $product->name; // Outputs: New Product
echo $product->price; // Outputs: 20


در این مثال، مجیک متد __set به گونه‌ای تعریف شده است که قبل از ذخیره‌سازی، مقدار قیمت را بررسی می‌کند تا از صحت آن اطمینان حاصل کند و از ذخیره‌سازی مقادیر نامعتبر جلوگیری کند. همچنین، نام محصول از تگ‌های HTML پاک می‌شود.
سپس توسط مجیک متد __get نام و قیمت دریافت می شود.
همه این ها در حالی است که پراپرتی های name و price در کلاس ما وجود ندارند.

مجیک متدهای __get و __set در PHP ابزارهای قدرتمندی هستند که به شما امکان می‌دهند کنترل بیشتری بر نحوه دسترسی و تغییر داده‌ها در کلاس‌هایتان داشته باشید.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍51🔥1
مجیک متد های __isset و __unset برای کنترل دسترسی به ویژگی‌هایی که نامعلوم یا ناقابل دسترس هستند.

مجیک متد __isset:
مجیک متد __isset زمانی فعال می‌شود که تابع isset() یا empty() بر روی ویژگی‌هایی که در کلاس به صورت مستقیم قابل دسترسی نیستند، استفاده شود. این مجیک متد به شما امکان می‌دهد که تعیین کنید آیا یک ویژگی موجود است یا خیر، حتی اگر این ویژگی به صورت خصوصی یا محافظت‌شده تعریف شده باشد.
این مجیک متد یک ورودی میگیرد که نام پراپرتی است که تابع isset یا empty بر روی آن فراخوانی شده است.


مثال:
تصور
کنید یک کلاس با ویژگی‌های خصوصی داریم و می‌خواهیم بررسی کنیم که آیا یک ویژگی خصوصی تنظیم شده است یا خیر:
class User {
private $data = [
'name' => 'John Doe',
'email' => 'john@example.com'
];

public function __isset($property) {
return isset($this->data[$property]);
}
}

$user = new User();
echo isset($user->name) ? 'Name is set' : 'Name is not set';
// Output: Name is set


در این مثال بررسی میشود که پراپرتی name در کلاس User موجود است یا خیر، این درحالی است که این پراپرتی به طور مستقیم در دسترس نیست.

مجیک متد __unset:
مجیک متد __unset زمانی فعال می‌شود که تابع unset() بر روی ویژگی‌هایی که به طور مستقیم دسترسی‌پذیر نیستند، فراخوانی شود. این به شما اجازه می‌دهد که تعریف کنید چه اتفاقی باید هنگام حذف یک ویژگی رخ دهد.
این مجیک متد یک ورودی میگیرد که نام پراپرتی unset شده میباشد.

مثال:
class User {
private $data = [
'name' => 'John Doe',
'email' => 'john@example.com'
];

public function __unset($property) {
echo "Unsetting property '$property'\n";
unset($this->data[$property]);
}
}

$user = new User();
unset($user->name);


در این مثال، وقتی unset($user->name) فراخوانی می‌شود، مجیک متد __unset اجرا می‌شود و پیامی مبنی بر حذف ویژگی نمایش داده می‌شود و ویژگی مورد نظر را از آرایه داده‌های داخلی کلاس حذف می‌کند.
این نیز درحالی است که پراپرتی name مستقیما در کلاسی User موجود نمیباشد.


این دو مجیک متد، __isset و __unset، ابزارهای مفیدی در PHP هستند که به شما اجازه می‌دهند تا رفتار دسترسی به ویژگی‌ها و حذف آن‌ها در کلاس‌های شما را به شکل کنترل‌شده‌ای مدیریت کنید. استفاده از این مجیک متدها به خصوص در مواقعی که با داده‌های حساس یا پیچیده کار می‌کنید، می‌تواند بسیار مفید باشد. این تکنیک‌ها به شما اجازه می‌دهند تا یک واسط کاربری برنامه‌نویسی روان‌تر و ایمن‌تری را ارائه دهید، زیرا می‌توانید جلوی دسترسی مستقیم به ویژگی‌های داخلی کلاس را بگیرید و در عین حال به کاربران اجازه دهید تا تنها عملیات‌های معتبر را روی آن‌ها انجام دهند.

👤 AmirHossein

💎 Channel: @DevelopixPHP
🔥5👍2
مجیک متدهای __sleep و __wakeup در PHP به شما امکان می‌دهند کنترلی بر فرآیند سریالیزه کردن و دسریالیزه کردن یک شیء را داشته باشید.

مجیک متد __sleep :
وقتی یک شیء در PHP سریالیزه می‌شود (برای ذخیره شدن آن در فایل یا ارسال آن از طریق شبکه)، مجیک متد __sleep فراخوانی می‌شود. این مجیک متد امکان می‌دهد تا شما مشخص کنید که کدام ویژگی‌های شیء باید قبل از سریالیزه شدن ذخیره شوند.

مثال:
class MyClass {
public $name;
public $age;
public $city;

public function __construct($name, $age, $city) {
$this->name = $name;
$this->age = $age;
$this->city = $city;
}

public function __sleep() {
return array('name', 'age');
}
}

$obj = new MyClass('John', 30, 'New York');
$data = serialize($obj);
echo $data;
// Output: O:7:"MyClass":2:{s:4:"name";s:4:"John";s:3:"age";i:30;}


در این مثال، ما یک کلاس به نام MyClass داریم که سه ویژگی name، age و city را دارد. ما یک مجیک متد __construct داریم که مقادیر این ویژگی‌ها را تنظیم می‌کند.
سپس، ما مجیک متد __sleep را به کلاس اضافه می‌کنیم. این مجیک متد در زمانی که یک شیء از این کلاس سریالیزه می‌شود، فراخوانی می‌شود و آرایه‌ای از نام‌های ویژگی‌ها را که قبل از سریالیزه شدن باید ذخیره شوند، برمی‌گرداند.
در نهایت، ما یک شیء از این کلاس ایجاد می‌کنیم و آن را سریالیزه می‌کنیم.
وقتی این برنامه اجرا می‌شود، فقط ویژگی‌های name و age از شیء $obj در زمان سریالیزه شدن ذخیره می‌شوند.

———

مجیک متد __wakeup:
وقتی یک شیء سریالیزه شده را می‌خوانید و به شیء تبدیل می‌کنید، مجیک متد __wakeup فراخوانی می‌شود. این مجیک متد به شما اجازه می‌دهد که فرآیند بازیابی داده‌ها پس از دسریالیزه کردن را کنترل کنید.

مثال:
class MyClass {
public $name;
public $age;
public $city;

public function __construct($name, $age, $city) {
$this->name = $name;
$this->age = $age;
$this->city = $city;
}

public function __sleep() {
return array('name', 'age');
}

public function __wakeup() {
$this->city = 'Unknown';
}
}

$data = 'O:7:"MyClass":2:{s:4:"name";s:4:"John";s:3:"age";i:30;}';
$obj = unserialize($data);
var_dump($obj);

/*
Output:

object(MyClass)#1 (3) {
["name"]=>
string(4) "John"
["age"]=>
int(30)
["city"]=>
string(7) "Unknown"
}
*/


در این مثال، ما از همان کلاس MyClass استفاده می‌کنیم. اما در اینجا ما مجیک متد __wakeup را به کلاس اضافه می‌کنیم. این مجیک متد هنگامی که یک شیء از این کلاس دسریالیزه می‌شود، فراخوانی می‌شود و این امکان را به ما می‌دهد که داده‌هایی را پس از دسریالیزه کردن تغییر دهیم.
سپس، ما یک رشته حاوی داده سریالیزه شده را به کلاس MyClass منتقل می‌کنیم و آن را با استفاده از تابع unserialize دسریالیزه می‌کنیم.
وقتی این برنامه اجرا می‌شود، وقتی که $obj دسریالیزه می‌شود، مجیک متد __wakeup فراخوانی می‌شود و مقدار city به "Unknown" تنظیم می‌شود.

به طور خلاصه، مجیک متدهای __sleep و __wakeup در PHP ابزارهایی هستند که به شما امکان می‌دهند کنترلی دقیق بر فرآیند سریالیزه کردن و دسریالیزه کردن یک شیء داشته باشید.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍7🔥3
مجیک متدهای __serialize و __unserialize در PHP بخشی از ویژگی‌های مدیریت سریالیزیشن اشیاء هستند. این متدها به شما امکان می‌دهند که کنترل دقیق‌تری بر روند سریالیزیشن و آنسریالیزیشن اشیاء داشته باشید. این کاربرد به ویژه در مواقعی مفید است که شیء شامل داده‌هایی است که نیاز به سریالیزیشن خاصی دارند یا باید از سریالیزیشن برخی داده‌ها جلوگیری شود.

مجیک متد __serialize:
این متد به شما امکان می‌دهد که تعیین کنید کدام داده‌های یک شیء هنگام سریالیزیشن ذخیره شوند. این کار از طریق برگرداندن یک آرایه که شامل نام‌ها و مقادیر متغیرهایی که باید سریالیز شوند، انجام می‌پذیرد.

مثال:
فرض کنید می‌خواهیم کلاس User را داشته باشیم که می‌خواهیم هنگام سریالیزیشن، رمز عبور را حذف کنیم تا در داده‌های سریال شده ذخیره نشود.

class User {
public $username;
private $password;
public $email;

public function __construct($username, $password, $email) {
$this->username = $username;
$this->password = $password;
$this->email = $email;
}

public function __serialize(): array {
return [
'username' => $this->username,
'email' => $this->email
];
}
}

$user = new User('alice', 'secretPassword123', 'alice@example.com');
$serializedUser = serialize($user);

در این مثال، وقتی شیء $user سریالیز می‌شود، متد __serialize فقط username و email را برمی‌گرداند و password سریالیز نمی‌شود.

———

مجیک متد __unserialize:
این متد هنگام آنسریالیزیشن یک شیء فراخوانی می‌شود و به شما امکان می‌دهد که مشخص کنید چگونه داده‌های آنسریالیز شده باید در شیء بازیابی شوند. این متد یک آرایه از داده‌ها را به عنوان ورودی می‌گیرد و شما می‌توانید این داده‌ها را در ویژگی‌های شیء تنظیم کنید.

مثال:
حالا
، برای همان کلاس User، متد __unserialize را پیاده‌سازی می‌کنیم تا هنگام آنسریالیزیشن، رمز عبور را به یک مقدار پیش‌فرض تنظیم کنیم.

class User {
public $username;
private $password;
public $email;

public function __construct($username, $password, $email) {
$this->username = $username;
$this->password = $password;
$this->email = $email;
}

public function __unserialize(array $data): void {
$this->username = $data['username'];
$this->email = $data['email'];

$this->password = 'defaultPassword';
}
}

$serializedUser = 'O:4:"User":2:{s:8:"username";s:5:"alice";s:5:"email";s:17:"alice@example.com";}';
$user = unserialize($serializedUser);

در این مثال، هنگام آنسریالیزیشن، username و email از داده‌های سریال شده بازیابی می‌شوند و password به 'defaultPassword' تنظیم می‌شود. این روش مطمئن می‌کند که هیچ داده حساسی از طریق فرآیند سریالیزیشن و آنسریالیزیشن افشا نشود.

———
تفاوت ها با مجیک متد های __sleep و __wakeup:

__sleep:
مجیک متد __sleep قبل از سریالیزیشن یک شیء فراخوانی می‌شود. هدف از این متد آماده‌سازی شیء برای سریالیزیشن است. __sleep باید یک آرایه از نام‌های خصوصیاتی که قرار است سریالیز شوند را برگرداند. خصوصیاتی که در این آرایه ذکر نشده‌اند در نتیجه سریالیزیشن حذف می‌شوند و حالت فعلی آن‌ها از بین می‌رود.
———

__wakeup:
پس از آنکه شیء آنسریالیز شد، متد __wakeup فراخوانی می‌شود. این متد برای بازیابی منابع یا انجام تنظیمات خاص پس از آنسریالیزیشن استفاده می‌شود، مثلاً بازکردن اتصالات پایگاه داده یا دیگر منابعی که نمی‌توانند مستقیماً سریالیز شوند.
———

__serialize:
این متد جدیدتر و انعطاف‌پذیرتر است و به شما اجازه می‌دهد که دقیقاً مشخص کنید چه داده‌هایی باید به چه شکلی سریالیز شوند. با __serialize، می‌توانید یک آرایه کلید-مقدار برگردانید که دقیقاً نشان‌دهنده‌ی آن چیزی است که می‌خواهید سریالیز شود. این روش فرصت‌های بیشتری برای مدیریت حالت شیء فراهم می‌کند.
———

__unserialize:
هنگام آنسریالیزیشن، __unserialize فراخوانی می‌شود و یک آرایه از داده‌ها را دریافت می‌کند. این متد به شما اجازه می‌دهد که مشخص کنید چگونه این داده‌ها باید در شیء استفاده شوند و به شما امکان می‌دهد تنظیمات لازم را اعمال کنید.
———

مجیک متدهای __serialize و __unserialize به شما کنترل دقیق‌تری بر داده‌هایی که سریالیز و آنسریالیز می‌شوند می‌دهند، در حالی که __sleep و __wakeup بیشتر برای مدیریت ویژگی‌ها و منابع استفاده می‌شوند.

👤 AmirHossein

💎 Channel: @DevelopixPHP
5👍1