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

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

💎 @Developix
🚀 Developix.ir

📌 پشتیبانی و تبلیغات:
@DevelopixSupport
Download Telegram
کلاس‌های انتزاعی (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
مجیک متد __toString در PHP برای تعریف نحوه تبدیل یک شیء به رشته استفاده می‌شود. این مجیک متد زمانی فراخوانی می‌شود که شیء به صورت خودکار باید به یک رشته تبدیل شود، مثلاً زمانی که می‌خواهیم یک شیء را به عنوان یک رشته چاپ کنیم یا در یک رشته ادغام کنیم. این قابلیت برای ارائه نمایش معنادار و قابل فهم از شیء در قالب رشته بسیار مفید است.

مجیک متد __toString هیچ پارامتری ندارد و یک رشته برگرداند.

مثال:
فرض کنید می‌خواهیم یک کلاس برای نمایش اطلاعات کتاب در یک کتابخانه داشته باشیم. ما می‌توانیم مجیک متد __toString را به کار ببریم تا یک خلاصه مناسب از کتاب را زمانی که نیاز به نمایش آن به صورت رشته‌ای داریم، تولید کنیم.
class Book {
private $title;
private $author;
private $year;

public function __construct($title, $author, $year) {
$this->title = $title;
$this->author = $author;
$this->year = $year;
}

public function __toString() {
return "{$this->title} written by {$this->author}, published in {$this->year}.";
}
}

$book = new Book("The Little Prince", "Antoine de Saint-Exupéry", 1945);
echo $book;
// Output: The Little Prince written by Antoine de Saint-Exupéry , published in 1945


در این مثال، کلاس Book شامل سه خصوصیت (عنوان، نویسنده، و سال نشر) است. مجیک متد __construct برای تعیین این خصوصیات هنگام ایجاد شیء استفاده می‌شود، و مجیک متد __toString برای تولید یک رشته خلاصه از کتاب به کار می‌رود. زمانی که echo برای نمایش شیء استفاده می‌شود، مجیک متد __toString به طور خودکار فراخوانی می‌شود و رشته مورد نظر چاپ می‌گردد.

———

مجیک متد __debugInfo در PHP به شما اجازه می‌دهد تعیین کنید چه اطلاعاتی باید زمان استفاده از تابع var_dump برای شیء نمایش داده شود. این مجیک متد به خصوص در مواقعی مفید است که شما می‌خواهید برخی از جزئیات داخلی شیء را مخفی کنید یا فرمت خروجی را سفارشی سازی کنید.

مجیک متد __debugInfo باید یک آرایه را برگرداند که کلیدهای آن نشان دهنده نام‌های خصوصیاتی هستند که باید در خروجی var_dump نمایش داده شوند، و مقادیر آن خود داده‌هایی هستند که باید نمایش داده شوند.

مثال:
فرض کنید می‌خواهیم کلاس User داشته باشیم که شامل اطلاعات حساس مثل رمز عبور است. ما می‌خواهیم که زمان استفاده از var_dump بر روی نمونه‌های این کلاس، رمز عبور نمایش داده نشود.
<?php

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

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

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


$user = new User("ali", "12345", "ali@example.com");
var_dump($user);
/*
Output:
object(User)#1 (2) {
["username"]=>
string(3) "ali"
["email"]=>
string(15) "ali@example.com"
}
*/


در این مثال، کلاس User شامل سه خصوصیت است: نام کاربری، رمز عبور و ایمیل. مجیک متد __construct برای مقداردهی این خصوصیات استفاده می‌شود. مجیک متد __debugInfo تعریف شده است تا زمانی که var_dump بر روی نمونه‌های این کلاس اجرا می‌شود، رمز عبور نمایش داده نشود. به جای آن، فقط نام کاربری و ایمیل نمایش داده می‌شوند. این روش کنترل بیشتری بر داده‌هایی که ما می‌خواهیم نمایش داده شود و نشود به ما می‌دهد، و از نمایش اطلاعات حساس در محیط‌های توسعه جلوگیری می‌کند.

👤 AmirHossein

💎 Channel: @DevelopixPHP
🔥4👍1
مجیک متد __invoke در PHP به شیء اجازه می‌دهد تا همچون یک تابع عمل کند. یعنی وقتی شی‌ای از کلاسی که این مجیک متد در آن تعریف شده است، ساخته می‌شود، می‌تواند مستقیماً فراخوانی شود.

مثال:
فرض کنید می‌خواهیم یک کلاس داشته باشیم که عملیات ریاضی را انجام دهد. می‌توانیم __invoke را استفاده کنیم تا بتوانیم شیء را مانند یک تابع فراخوانی کنیم و یک عملیات را انجام دهیم.

class MathOperation {
private $operand;

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

public function __invoke($number) {
return $number * $this->operand;
}
}

$double = new MathOperation(2);
echo $double(10); // Output: 20


در این مثال، شیء $double همچون یک تابع فراخوانی شده و عدد 10 را دو برابر می‌کند.

———

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

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

مثال:
در این مثال، ما یک کلاس ساده به نام Person را تعریف می‌کنیم که دارای دو ویژگی name و age است و مجیک متد __set_state را برای آن تعریف می‌کنیم:

class Person {
public $name;
public $age;

public static function __set_state($an_array) {
$obj = new Person;
$obj->name = $an_array['name'];
$obj->age = $an_array['age'];
return $obj;
}
}

$person = new Person;
$person->name = 'John';
$person->age = 30;

$exported = var_export($person, true);

eval('$restored_person = ' . $exported . ';');
echo $restored_person->name; // Output: John
echo $restored_person->age; // Output: 30


مجیک متد __set_state برای بازسازی شیء از آرایه‌ای که توسط var_export تولید شده استفاده می‌کند.
تابع var_export برای تولید یک رشته است که نمایش دهنده کد PHP برای بازسازی شیء Person است.
با استفاده از eval شیء جدیدی از رشته خروجی var_export ساخته می‌شود و می‌توان مقادیر ویژگی‌های آن را استخراج کرد.

👤 AmirHossein

💎 Channel: @DevelopixPHP
5👍2
مجیک متد __clone زمانی فراخوانی می‌شود که یک شیء کلون شود. استفاده از کلون به شما اجازه می‌دهد یک نسخه دقیق از یک شیء موجود را ایجاد کنید، اما با این توانایی که رفتار پیش‌فرض کلون را اصلاح کنید. این بدان معناست که می‌توانید تنظیمات ویژه‌ای را برای نحوه کپی شدن خصوصیات شیء اعمال کنید، بخصوص زمانی که با خصوصیاتی که به شیء‌های دیگر اشاره دارند سروکار دارید.

مثال:
فرض
کنید که شما یک کلاس برای مدیریت پروفایل کاربر دارید و می‌خواهید که هر کلون از این کلاس دارای تنظیمات پیش‌فرض مشابهی باشد اما بتوان آن را به صورت جداگانه تنظیم کرد:
class UserProfile {
public $name;
public $email;
private $settings;

public function __construct($name, $email)
{
$this->name = $name;
$this->email = $email;
$this->settings = new stdClass();
$this->settings->theme = "default";
}

public function __clone()
{
$this->settings = clone $this->settings;
}
}

$user1 = new UserProfile("Ali", "ali@example.com");
$user2 = clone $user1;
$user2->name = "Reza";
$user2->settings->theme = "dark";

echo $user1->name . " has theme " . $user1->settings->theme . "\n";
// Ali has theme default
echo $user2->name . " has theme " . $user2->settings->theme . "\n";
// Reza has theme dark


در مثال ارائه شده، یک کلاس به نام UserProfile تعریف شده که حاوی اطلاعات کاربر است. وقتی شیء این کلاس کلون می‌شود، مجیک متد __clone فعال شده و به جای اینکه تنها به شیء settings ارجاع دهد، یک نسخه کاملاً جدید از آن را ایجاد می‌کند.
این کار موجب می‌شود که هر کاربر کلون شده دارای تنظیمات مستقل خود باشد و تغییرات اعمال شده بر روی یک شیء، بر شیء دیگر تأثیر نگذارد. این امکان از طریق کپی عمیق انجام می‌شود که به معنای کپی کردن همه خصوصیات، و نه فقط ارجاع‌ها، به نسخه کلون شده است.

کپی عمیق و کپی سطحی:
در
PHP، کلونینگ می‌تواند به دو نوع تقسیم شود: کپی سطحی و کپی عمیق.

کپی سطحی (Shallow Copy):
در این نوع کپی، فقط خصوصیات سطحی شیء کپی می‌شوند و هر خصوصیتی که به شیء دیگری ارجاع دهد، فقط ارجاع کپی می‌شود. این بدین معنی است که شی‌های اصلی و کلون شده به همان شیء ارجاعی اشاره خواهند کرد.

کپی عمیق (Deep Copy):
کپی عمیق شامل کپی کردن شیء و همچنین هر شیء دیگری است که توسط خصوصیات اصلی به آن اشاره شده است. این اطمینان حاصل می‌کند که شیء کلون شده و شیء اصلی هیچ ارتباط مستقیمی با یکدیگر ندارند. استفاده از مجیک متد __clone در PHP این امکان را می‌دهد که شما بتوانید کپی عمیق را اجرا کنید و خصوصیاتی که به شیء‌های دیگر اشاره دارند را نیز به صورت مجزا کپی کنید.

👤 AmirHossein

💎 Channel: @DevelopixPHP
🔥4👍2
مجیک کانستنت‌ها در PHP مقادیر ثابتی هستند که بسته به نحوه استفاده آن‌ها در کد، مقادیرشان تغییر می‌کنند. این کانستنت‌ها اغلب برای ارائه اطلاعات در مورد کد، مانند محل فایل‌ها یا نام کلاس‌ها، استفاده می‌شوند.

__LINE__:

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

<?php
echo "This is line " . __LINE__;


Output: This is line 2

———

__FILE__:

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

<?php
echo "This file is " . __FILE__;


Output: This file is C:\Users\{SysName}\Desktop\index.php

———

__DIR__:

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

<?php
echo "Directory path is " . __FILE__;


Output: Directory path is C:\Users\{SysName}\Desktop

———

__FUNCTION__:

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

function test() {
echo "Function name is " . __FUNCTION__;
}
test();


Output: Function name is test


———

__CLASS__:

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

class Sample {
public function getClassName() {
echo "Class name is " . __CLASS__;
}
}
$obj = new Sample();
$obj->getClassName();


Output: Class name is Sample

———

__TRAIT__:

نام trait جاری را برمی‌گرداند.در صورتی که خارج از یک Trait باشید، این کانستنت مقداری خالی برمی‌گرداند. در صورت داشتن Namespace نام تریت همراه با Namespace برگردانده می شود.

trait Sample
{
public function getTraitName() {
echo "Trait name is " . __TRAIT__;
}
}

class Test
{
use Sample;
}

$obj = new Test();
$obj->getTraitName();


Output: Trait name is Sample


———

__METHOD__:

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

class Sample {
public function getMethodName() {
echo "Method name is " . __METHOD__;
}
}
$obj = new Sample();
$obj->getMethodName();


Output: Method name is Sample::getMethodName


———

__NAMESPACE__:

نام فضای نام (namespace) جاری را برمی‌گرداند. این برای مدیریت کد در پروژه‌های بزرگ که از نیم‌اسپیس‌ها برای جداسازی کد استفاده می‌کنند، مفید است.

namespace Test\MyNamespace;
echo "Namespace name is " . __NAMESPACE__;


Output: Namespace name is Test\MyNamespace


———

ClassName::class:

نام کامل کلاس را برمیگرداند. در صورت داشتن Namespace نام کلاس همراه با Namespace برگردانده می شود.

<?php
class Sample { }
echo Sample::class;


Output: Sample


👤 AmirHossein

💎 Channel: @DevelopixPHP
👍95🔥3
کلمه کلیدی yield در PHP برای ساخت جنراتورها استفاده می‌شود. جنراتورها امکان ایجاد سری‌هایی از داده‌ها را فراهم می‌کنند بدون اینکه نیاز به بارگذاری همه آن‌ها در حافظه باشد. این ویژگی خصوصاً برای کار با داده‌های حجیم یا عملیات‌هایی که به تولید تعداد زیادی داده نیاز دارند مفید است.

‏yield در واقع مقداری را به Caller (تابعی که جنراتور را فراخوانی می‌کند) بازمی‌گرداند، اما در عین حال حالت فعلی جنراتور را نیز ذخیره می‌کند تا بتوان بعداً از همان نقطه ادامه داد. این تفاوت اصلی بین yield و return است؛ return کارکرد تابع را به طور کامل پایان می‌دهد، در حالی که yield این امکان را می‌دهد که تابع بعداً از همان نقطه توقف اجرا شود.

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

function readLargeFile($filename) {
$handle = fopen($filename, "r");

while (!feof($handle)) {
yield fgets($handle);
}

fclose($handle);
}

foreach (readLargeFile("large_log_file.txt") as $line) {
echo $line . "<br>";
}


در این مثال، تابع readLargeFile به عنوان یک جنراتور عمل می‌کند. این تابع ابتدا فایل مورد نظر را برای خواندن باز می‌کند. درون حلقه while، از fgets برای خواندن هر خط از فایل استفاده می‌کنیم. تابع fgets خط بعدی را از فایل می‌خواند، و با استفاده از yield، این خط را به کد خارج از تابع برمی‌گرداند.

با استفاده از حلقه foreach، ما می‌توانیم هر خطی که جنراتور readLargeFile باز می‌گرداند را استفاده کنیم. این اجازه می‌دهد که هر خط را بلافاصله پردازش کنیم بدون اینکه نیاز باشد کل فایل در حافظه بارگذاری شود. این روش بسیار مؤثری برای کار با فایل‌های بزرگ است، زیرا فقط بخشی از فایل که در حال پردازش است در حافظه نگه داشته می‌شود، و بنابراین مصرف حافظه به شدت کاهش می‌یابد.

این رویکرد خصوصاً در مواقعی مفید است که با داده‌هایی کار می‌کنیم که بسیار بزرگ‌تر از حافظه موجود هستند یا وقتی که می‌خواهیم اطمینان حاصل کنیم که برنامه‌ی ما بهینه و کارآمد باقی می‌ماند حتی در مواجهه با حجم زیادی از داده‌ها.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍64🔥2