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

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

💎 @Developix
🚀 Developix.ir

📌 پشتیبانی و تبلیغات:
@DevelopixSupport
Download Telegram
در 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
در ‏PHP،‏ heredoc و nowdoc دو روش برای تعریف رشته‌های چندخطی هستند که می‌توانند برای نگهداری متن‌های طولانی یا متن‌هایی که شامل کاراکترهای ویژه هستند، بسیار مفید باشند. این دو روش تفاوت‌هایی دارند که در ادامه توضیح داده می‌شود.

‏Heredoc:
‏Heredoc یک روش است که به کمک علامت <<<EOT (می توان هرچیزی به جای EOT نوشت) باز و بسته می‌شود.
این علامت می‌تواند چند حرف یا یک کلمه دلخواه به عنوان نشانگر داشته باشد، (<<<EOT به عنوان مثال).
متن ‏Heredoc بین نشانگر شروع و نشانگر پایان آن قرار می‌گیرد. Heredoc امکان تفسیر متغیرها را دارد.

مثال:
$name = "John";
$text = <<<EOT
Hello $name,
This is a heredoc example.
EOT;

echo $text;

Output:
Hello John,
This is a heredoc example.

در این مثال، متغیر $name درون متن heredoc استفاده شده است و مقدار واقعی آن تفسیر و نمایش داده می‌شود.

———

‏Nowdoc:
‏Nowdoc به‌طور مشابهی به heredoc عمل می‌کند، با این تفاوت که نمی‌تواند متغیرها را درون خود تفسیر کند. Nowdoc با استفاده از علامت <<<'EOT' (می توان هرچیزی به جای EOT نوشت) شروع و تا علامت پایانی خود ادامه می‌یابد.

مثال:
$name = "John";
$text = <<<'EOT'
Hello $name,
This is a nowdoc example.
EOT;

echo $text;


Output:
Hello $name,
This is a nowdoc example.

در این مثال، $name درون nowdoc استفاده شده است، اما به عنوان رشته خام خوانده می‌شود، بنابراین نتیجه نهایی متن $name خواهد بود.

———

توجه داشته باشید که هر کاراکتری بدون محدودیت بین Hewedoc و Nowdoc میتواند قرار گیرید. به عنوان مثال:
$text = <<<EOT
*''
*/'
*"
EOT;

echo $text;


Output:
*''
*/'
*"


از Heredoc و Nowdoc می توان برای نوشتن تگ های HTML یا JS و ... که دارای کاراکتر های خاص مثال / " ' هستند استفاده کرد.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍12
در PHP، مفهوم variable variables یا متغیرهای متغیر به امکان تعریف و استفاده از متغیرهایی اشاره دارد که نام آن‌ها از مقدار یک متغیر دیگر تعیین می‌شود. این به شما امکان می‌دهد تا در زمان اجرا نام متغیرها را مشخص کنید.

  $Hello = "World";
$a = "Hello";

echo $a; // Hello
echo $$a; // World


در مثال یک متغیر به نام $Hello ایجاد شده و به آن رشته World اختصاص داده شده است. همچنین یک متغیر به نام $a ایجاد شده و به آن رشته Hello اختصاص داده شده است.
زمانی که از یک علامت $ استفاده کرده ایم مقدار متغییر $a نمایش داده میشود اما زمانی که از دو علامت $ استفاده شده به معنای متغیری است که نام آن برابر با مقدار $a است.
مقدار $a برابر Hello است، بنابراین $$a معادل با $Hello می‌شود. و مقدار $Hello برابر World است.

مثال :
فرض
کنید می‌خواهید یک سری متغیر با نام‌های متمایزی ایجاد کنید، اما نام آنها را از یک آرایه بگیرید. اینجاست که متغیرهای متغیر به کمک می‌آیند:
$variable_names = array("var1", "var2", "var3");
foreach ($variable_names as $name) {
$$name = rand(1, 100);
}

echo $var1;
echo $var2;
echo $var3;


در این مثال، ابتدا یک آرایه با نام‌های متغیرها ایجاد می‌شود. سپس با استفاده از حلقه foreach، برای هر نام متغیر در آرایه، یک متغیر با همان نام ایجاد می‌شود و به آن یک مقدار تصادفی از ۱ تا ۱۰۰ اختصاص داده می‌شود. در نهایت، مقادیر متغیرها با استفاده از نام آنها نمایش داده می‌شود.

شما می توانید به هر تعداد دلخواه $ در php قرار دهید (بر خلاف زندگی عادی):
echo $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$dontTryThisAtHome;


مثال:
  $Bar = "a";
$Foo = "Bar";
$World = "Foo";
$Hello = "World";
$a = "Hello";

$a; //Returns Hello
$$a; //Returns World
$$$a; //Returns Foo
$$$$a; //Returns Bar
$$$$$a; //Returns a

$$$$$$a; //Returns Hello
$$$$$$$a; //Returns World

//... and so on ...//


و حتی به صورت زیر:
$nameTypes    = array("first", "last", "company");
$name_first = "John";
$name_last = "Doe";
$name_company = "PHP";

foreach($nameTypes as $type)
print ${"name_$type"} . "\n";

print "$name_first\n$name_last\n$name_company\n";


با این حال در برخی موارد مانند Superglobal array ها مانند $_SERVER و متغیر $this که از متغیر های خاص هستند این قابلیت غیرقابل استفاده می باشد.

👤 AmirHossein

💎 Channel: @DevelopixPHP
6👍3🔥2
در PHP، رفرنس‌ها (References) امکان اشاره به محتوای متغیرها را بدون کپی‌برداری از آن‌ها فراهم می‌کنند. این ویژگی به خصوص در زمانی مفید است که می‌خواهیم تغییراتی را بر روی متغیرها در یک تابع یا بین بخش‌های مختلف برنامه اعمال کنیم بدون اینکه نیاز به بازگرداندن مقادیر باشد.

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

$a = 10;
$b = &$a;

$b = 20;
echo $a; // Output: 20


در این مثال، متغیر $b به $a رفرنس دارد و هر تغییری در $b منجر به تغییر در $a نیز خواهد شد.

رفرنس‌ها را می‌توان در توابع برای تغییر متغیرهایی که به تابع پاس داده می‌شوند استفاده کرد. نمونه زیر این مورد را نشان می‌دهد:
function add_five(&$value) {
$value += 5;
}

$number = 10;
add_five($number);
echo $number; // Output: 15


در این مثال، تابع add_five متغیر $value را به عنوان رفرنس دریافت می‌کند و هر تغییری که در تابع بر روی این متغیر اعمال شود، در متغیر اصلی نیز منعکس می‌شود.

رفرنس‌ها همچنین می‌توانند در کار با آرایه‌ها بسیار مفید باشند، به خصوص وقتی که می‌خواهیم تغییراتی را در هر عنصر آرایه اعمال کنیم:
$numbers = [1, 2, 3, 4, 5];
foreach ($numbers as &$number) {
$number *= 2;
}

print_r($numbers); // Output: [2, 4, 6, 8, 10]


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

بعضی از توابع PHP که مقادیر را کپی می‌کنند (مانند array_map)، با رفرنس‌ها کار نمی‌کنند. در این موارد، تغییراتی که به عناصر آرایه اعمال می‌شوند، بر مقادیر اصلی تأثیری نمی‌گذارند.

استفاده از رفرنس‌ها در موقعیت‌هایی مانند متغیرهای سوپرگلوبال، مانند $_POST یا $_GET، ممکن است کار نکند و توصیه نمی‌شود، زیرا این متغیرها توسط محیط اجرا مدیریت می‌شوند و مداخله در آن‌ها می‌تواند نتایج ناخواسته داشته باشد.

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

استفاده از رفرنس‌ها در PHP نیازمند دقت است، زیرا تغییرات اعمال شده بر روی رفرنس‌ها مستقیماً بر متغیرهای اصلی تاثیر می‌گذارند، و این می‌تواند در صورت عدم توجه به ایجاد باگ منجر شود. به همین دلیل، بسیار مهم است که هنگام استفاده از رفرنس‌ها، کد را به دقت بررسی کنید تا از اعمال تغییرات ناخواسته جلوگیری شود.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍84
عملگرهای && , || , and , or همگی برای انجام عملیات‌های منطقی استفاده می‌شوند، اما بین آن‌ها تفاوت‌هایی در اولویت اجرا وجود دارد که می‌تواند بر روی نتیجه برنامه تأثیر بگذارد.

عملگر && بررسی می کند که هر دو مقدار true باشند.
عملگر and مانند && عمل می کند اما با الویت پایین تر.

عملگر || بررسی می کند که حداقل یکی از مقادیر true باشد.
عملگر or نیز مانند || عمل می کند اما با الویت پایین تر.

مثال AND:
$a = true;
$b = false;

$result = $a && $b; // false

$result = $a and $b; // true

در هر دو مثال بالا قرار است که بررسی شود هر دو مقدار true باشند، اما چرا خروجی ها متفاوت اند؟
زمانی که از عملگر && استفاده می شود، بررسی می شود که $a و $b برابر true باشند. چنانچه یکی از آنها true نبود خروجی false می شود.

اما همانطور که گفته شد عملگر and نسبت به && الویت اجرا پایین تری دارد، یعنی ابتدا $result برابر $a قرار می گیرد و سپس and $b اجرا می شود.
بیایید با استفاده از پرانتز دقیق تر نشان دهیم:
($result = $a) and $b;


مشخص است که $result برابر $a قرار گرفته است و $a هم برابر true است، در نتیجه and $b تاثیری در نتیجه نخواهد گزاشت و خروجی همان true است.
این مشکل را با گزاشتن پرانتز می توان حل کرد، چرا که پرانتز ها الویت های اجرا را تغییر می دهند:
$result = ($a and $b); // false


در مثال بالا ابتدا داخل پرانتز اجرا می شود و سپس $result برابر نتیجه می شود.

نتیجه می گیریم عملگر = سریع تر از and اجرا می شود درصورتی که && سریع تر از = اجرا می شود.

------

مثال OR:
$a = false;
$b = true;

$result = $a || $b; // true

$result = $a or $b; // false


در هر دو مثال بالا قرار است که بررسی شود حداقل یکی از مقادیر true باشند، اما چرا خروجی ها متفاوت اند؟
جواب سوال دقیقا مانند AND است.

زمانی که از عملگر || استفاده می شود، بررسی می شود که حداقل یکی از $a یا $b برابر true باشند. چنانچه هر دو آنها true نبود خروجی false می شود.

اما همانطور که گفته شد عملگر or نسبت به || الویت اجرا پایین تری دارد، یعنی ابتدا $result برابر $a قرار می گیرد و سپس or $b اجرا می شود.
بیایید با استفاده از پرانتز دقیق تر نشان دهیم:
($result = $a) or $b;


مشخص است که $result برابر $a قرار گرفته است و $a هم برابر false است، در نتیجه or $b تاثیری در نتیجه نخواهد گزاشت و خروجی همان false است.
این مشکل را با گزاشتن پرانتز می توان حل کرد، چرا که پرانتز ها الویت های اجرا را تغییر می دهند:
$result = ($a or $b); // true


در مثال بالا ابتدا داخل پرانتز اجرا می شود و سپس $result برابر نتیجه می شود.

نتیجه می گیریم عملگر = سریع تر از or اجرا می شود درصورتی که || سریع تر از = اجرا می شود.

------

بهتر است در استفاده از عملگر ها دقت کنیم تا باعث ایجا مشکل در برنامه نشویم.
ترجیحا از عملگرهای && و || به جای and و or استفاده کنید.

👤 AmirHossein

💎 Channel: @DevelopixPHP
9🔥6👍2
در PHP، عبارت match یک قابلیت نسبتاً جدید است که اولین بار در نسخه 8.0 معرفی شد. این عبارت برای جایگزینی ساختار switch استفاده می‌شود و به شما امکان می‌دهد مقادیر را به صورت اختصاصی مقایسه کنید.

در استفاده از match مقادیر را بر اساس === مقایسه می‌کند، در حالی که switch از مقایسه == استفاده می‌کند. این به این معناست که match دقیق‌تر است و تبدیل‌های خودکار نوع را انجام نمی‌دهد.
هر شاخه در match می‌تواند مستقیماً یک مقدار را برگرداند و نیازی به استفاده از return یا break نیست.

مثال:
$statusCode = 404;

$result = match ($statusCode) {
200, 201 => "OK",
301, 302 => "Redirect",
404 => "Not Found",
500 => "Server Error",
default => "Unknown status code"
};

echo $result; // Outputs: Not Found


در این مثال، یک متغیر به نام $statusCode داریم که مقدار آن 404 است. این مقدار نشان‌دهنده یک کد وضعیت HTTP است که معمولاً برای صفحاتی که یافت نشده‌اند به کار می‌رود. زمانی که $statusCode با یکی از کلید ها برابر باشد مقدار آن را بر میگرداند، و زمانی که با هیچ یک از کلید ها برابر نباشد مقدار default را بر می گرداند.

خروجی match را میتوان در لحظه return, echo یا درون متغییر ریخت:
return match ($statusCode) {
// ...
};

echo match ($statusCode) {
// ...
};

$result = match ($statusCode) {
// ...
};


بر خلاف switch-case که میتوان چندین خط را برای هر یک از حالات اجرا کرد در match تنها یک عمل قابل اجرا است:
switch (1){
case 1:
$a = 10;
$b = 20;
$c = 30;
echo 'hello';
echo 'bye';
return null;
}

match (1) {
1 => 'hello'
};


همانطور که می بینید 6 عمل درون switch-case اجرا شده، اما در match تنها یک خط قابل نوشتن است، اما چندین راه وجود دارد که در match چندین عمل را اجرا کنید.

1- می توانید برای هر حالت یک کلوژر بنویسید و خروجی match را درون متغییر بریزید و آن را اجرا کنید:
$do = match (1){
1=> function (){
echo 'hello';
echo 'bye';
return null;
}
};
$do();



2- میتوانید کلوژر را مستقیما درون match اجرا کنید:
match (1){
1=> (function (){
echo 'hello';
echo 'bye';
return null;
})()
};


3- می توانید یک تابع بنویسید و آن را به match بدهید:
function test(){
echo 'hello';
echo 'bye';
return null;
}

$do = match (1){
1=> test()
};


در نهایت match یک ابزار قدرتمند و مدرن برای جایگزینی switch در PHP است که به شما امکان می‌دهد کد خود را دقیق‌تر و خواناتر بنویسید.

👤 AmirHossein

💎 Channel: @DevelopixPHP
🔥12👍31
‏Attributes ها، ابزاری قدرتمند برای افزودن اطلاعات متا داده به کدهای PHP هستند. این قابلیت برای انواع مختلفی از کاربردها از جمله سریالایزیشن، ولیدیشن، کانفیگیوریشن دیپندنسی‌ها، و مشخص کردن روت‌های API مفید است.

در PHP، چندین Attribute به طور پیشفرض تعریف شده است که برای استفاده‌های مختلف در فریمورک‌ها و کتابخانه‌ها مناسب هستند. این Attributes درونی به شما اجازه می‌دهند تا با استفاده از امکانات زبان، ویژگی‌هایی مانند تزریق وابستگی، سریال‌سازی داده‌ها، و کنترل دسترسی‌ها را به صورت بومی مدیریت کنید.

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

فرض کنید می‌خواهیم یک Attribute برای تعریف نویسنده‌ی یک کلاس یا متد داشته باشیم:
#[Attribute()]
class Author {
public function __construct(public string $name) {}
}


در این مثال، Author یک Attribute است که نام نویسنده را دریافت می‌کند. این Attribute را می‌توان برای کلاس‌ها و متدها استفاده کرد.

حال، فرض کنید می‌خواهیم این Attribute را به یک کلاس و متد اختصاص دهیم:
#[Author("John Doe")]
class SampleClass {
#[Author("Jane Doe")]
public function exampleMethod() {}
}


برای دسترسی و استفاده از مقادیر تعریف شده توسط Attributes، می‌توانید از Reflection API استفاده کنید. این API به شما امکان می‌دهد در زمان اجرا اطلاعات را استخراج کنید.
$reflectionClass = new ReflectionClass(SampleClass::class);
$classAttributes = $reflectionClass->getAttributes(Author::class);

foreach ($classAttributes as $attribute) {
$authorInstance = $attribute->newInstance();
echo "Class Author: " . $authorInstance->name . "\n";
}

$reflectionMethod = $reflectionClass->getMethod('exampleMethod');
$methodAttributes = $reflectionMethod->getAttributes(Author::class);

foreach ($methodAttributes as $attribute) {
$authorInstance = $attribute->newInstance();
echo "Method Author: " . $authorInstance->name . "\n";
}


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

‏Attributes در PHP بر خلاف PHPDoc چیزی فراتر از کامنت‌ها هستند و به طور مستقیم توسط زبان تفسیر می‌شوند. در نسخه‌های قبلی PHP، توسعه‌دهندگان برای قرار دادن متادیتا به صورت کامنت‌هایی که به صورت دستی تفسیر می‌شدند (مانند PHPDoc) اتکا می‌کردند، اما Attributes در PHP 8 و بالاتر به گونه‌ای طراحی شده‌اند که به صورت بومی توسط زبان شناخته و مدیریت می‌شوند.

‏Attributes به شما این امکان را می‌دهند که اطلاعاتی را به اجزای مختلف کد مانند کلاس‌ها، توابع، پروپرتی‌ها، و پارامترها متصل کنید. این اطلاعات در زمان اجرا قابل استفاده هستند و می‌توانند توسط PHP و ابزارهایی که از Reflection API استفاده می‌کنند، خوانده شوند.

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍7🔥1
‏PHPDoc یک ابزار مستندسازی برای زبان برنامه‌نویسی PHP است که از کامنت‌ها برای تولید مستندات فنی استفاده می‌کند. این ابزار به توسعه‌دهندگان امکان می‌دهد تا کدهای خود را به صورت خودکار و با استفاده از تگ‌ها و فرمت‌های خاص، مستندسازی کنند.

کامنت‌های PHPDoc با دو ستاره (/) آغاز می‌شوند و می‌توانند شامل تگ‌های مختلفی باشند که اطلاعات مهمی را در مورد توابع، کلاس‌ها، ویژگی‌ها و غیره ارائه می‌دهند. درمورد این تگ ها به طور کامل توضیح داده می شود.

نمونه کد:

/**
* Calculate the sum of two numbers.
*
* @param int $a first number
* @param int $b second number
* @return int The sum of two numbers
*/
function add($a, $b) {
return $a + $b;
}


کد بالا پارامتر ها و خروجی تابع را توضیح می دهد.

از آنجایی که PHPDoc ها کامنت هستند توسط PHP تفسیر نمی شوند به همین دلیل در زمان اجرا در دسترس نیستند و برای خواندن آنها باید از ابزار هایی مانند PHPDocumentor استفاده کنید، ولی IDE ها توان تفسیر آنها را دارا می باشند و اگر کتابخانه ای توسعه می دهید به استفاده کننده گان کمک می کنند.

بررسی تگ ها:
تگ های PHPDoc با @ شرع می شوند.

@api
نشان دهنده آن دسته از عناصر API است که عمومی تلقی می‌شوند.
class UserService
{
/**
* @api
*/
public function getUser() {}

/**
* This method is "package scope", not public-API.
*/
public function callMefromAnotherClass() {}
}


در مثال بالا متد GetUser به عنوان متد عمومی درون api مشخص شده در صورتی که متد دوم مربوط به api عمومی نیست.
———
@author [name] [<email address>]
مشخص کننده نویسنده کد.
/**
* @author John Doe <john@gmail.com>
*/


———
@category [description]
دسته‌بندی کلی کلاس یا توابع را مشخص می‌کند.
/**
* @category MyCategory
*/


———
@copyright [description]
متن حق کپی‌رایت را برای کد مشخص می‌کند.
/**
* @copyright Copyright 1994-2024 Acme Corporation
*/


———
@deprecated [<Semantic Version>] [<description>]
این تگ نشان می‌دهد که یک تابع یا کلاس دیگر استفاده نمی‌شود و ممکن است در نسخه‌های آینده حذف شود.
/**
* @deprecated 2.0 Use newFunction() instead.
*/
function oldFunction() {
}


———
@example [location] [<start-line> [<number-of-lines>] ] [<description>]
یک فایل نمونه که نحوه استفاده از کد را نشان می‌دهد.
/**
* @example /path/to/example.php
*/


———
@filesource
نشان می‌دهد که متن کامل فایل باید در مستندات نمایش داده شود.
<?php
/**
* @filesource
*/


———
@global [Type] [name]
@global [Type] [description]
توضیح می‌دهد که یک تابع به یک متغیر جهانی دسترسی دارد.
/**
* @global int $GLOBAL_VAR Description of global variable.
*/
function useGlobal() {
global $GLOBAL_VAR;
}


———
@ignore [<description>]
باعث می‌شود که ابزار مستندسازی یک عنصر خاص را نادیده بگیرد.
/**
* @ignore
*/
define("RUNTIME_OS","Windows");


———
@internal [description]
اطلاعاتی که فقط برای توسعه‌دهندگان داخلی استفاده می‌شود.
/**
* @internal This is only for advanced developers.
*/
function count() {}


———
@license [<url>] [name]
نوع لایسنس کد را مشخص می‌کند.
/**
* @license GPL
* OR
* @license https://opensource.org/licenses/gpl-license.php GNU Public License
*/


———
@link [URI] [<description>]
لینک به منبع مرتبط.
/**
* @link https://example.com More information here
*/


———
@method [[static] return type] [name]([[type] [parameter]<, ...>]) [<description>]
توصیف متد مجازی در کلاس، مفید برای کلاس‌هایی با متدهایی که با مجیک متد (__call) تعریف شده‌اند.
/**
* @method int magicMethod(string $param) Description
*/
class MyClass {}


———
@package [level 1]\\[level 2]\\[etc.]
تعریف بسته‌ای که کلاس یا تابع مرتبط با آن است.
/**
* @package Core
*/


———
@param [<Type>] [name] [<description>]
توصیف پارامترهای یک تابع.
/**
* @param int $a First number
* @param int $b Second number
*/
function add($a, $b) {
return $a + $b;
}


ادامه تگ ها در پست بعدی توضیح داده می شود.

👤 AmirHossein

💎 Channel: @DevelopixPHP
5👍2🔥1
ادامه تگ های PHPDoc:

@property[<-read|-write>] [Type] [name] [<description>]
توصیف ویژگی‌های مجازی در کلاس برای استفاده در میجک متد ها.
/**
* @property-read int $id The ID of the user
* @property string $name The name of the user
*/
class User {}


———
@return [Type] [<description>]
توصیف خروجی تابع.
/**
* @return float The calculated result
*/
function compute() {
// Implementation
}


———
@see [URI | FQSEN] [<description>]
ارجاع به دیگر عناصر مستند.
/**
* @see otherFunction() For basic functionality
*/


———
@since [<version>] [<description>]
نشان دهنده نسخه‌ای که عنصر خاصی در آن اضافه یا تغییر کرده است.
/**
* @since 1.0
*/


———
@source [<start-line> [<number-of-lines>] ] [<description>]
نمایش قسمتی از کد منبع.
/**
* @source 2 1 Check that ensures lazy counting.
*/
function count()
{
if (null === $this->count) {
// ...
}
}


———
@subpackage [name]
زیرمجموعه‌ای از بسته‌ای که به آن تعلق دارد.
/**
* @package PSR
* @subpackage Documentation\API
*/


———
@throws [Type] [<description>]
استثناء‌هایی که ممکن است تابع بدهد.
/**
* @throws Exception If the file cannot be opened.
*/
function openFile($filename) {
// Implementation
}


———
@todo [description]
کارهایی که باید در آینده انجام شوند.
/**
* @todo Implement the rest of the method.
*/


———
@uses [FQSEN] [<description>]
نشان دهنده استفاده از یک عنصر توسط دیگری.
/**
* @uses functionB() Used by functionA for processing.
*/


———
@var ["Type"] [element_name] [<description>]
توصیف نوع یک متغیر، مفید در متغیرهای کلاس.
/**
* @var string $name The name of the person
*/
protected $name;


———
@version [<Semantic Version>] [<description>]
نسخه کد یا کلاس.
/**
* @version 1.0.0
*/


👤 AmirHossein

💎 Channel: @DevelopixPHP
👍6
دستور goto در PHP برای انتقال جریان اجرای برنامه به یک نقطه مشخص در کد استفاده می‌شود. این نقطه مشخص با یک برچسب (label) تعیین می‌شود. اگرچه استفاده از goto معمولاً توصیه نمی‌شود، زیرا می‌تواند کد را پیچیده و غیرقابل خواندن کند، اما در برخی موارد خاص می‌تواند مفید باشد.

دستور goto به این شکل نوشته می‌شود:
goto label;

label:
// Code to execute


مثال:
فرض کنید یک حلقه for داریم که در آن یک شرط خاص را بررسی می‌کنیم. اگر این شرط برقرار باشد، می‌خواهیم بلافاصله به یک بخش دیگر از کد بپریم و ادامه حلقه را نادیده بگیریم. مثال زیر را در نظر بگیرید:
for ($i = 0; $i < 10; $i++) {
if ($i == 5) {
goto end;
}
echo "Current value of i: $i\n";
}

end:
echo "Loop terminated because i equals 5.";


در این مثال، حلقه از 0 تا 9 اجرا می‌شود، اما وقتی مقدار $i به 5 می‌رسد، دستور goto end اجرا می‌شود و برنامه به برچسب end منتقل می‌شود. نتیجه این است که حلقه متوقف می‌شود و پیغام "Loop terminated because i equals 5." نمایش داده می‌شود.

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

در بیشتر موارد، می‌توان از ساختارهای کنترلی دیگر مانند break، continue و return استفاده کرد که خواناتر و مناسب‌تر هستند.

مثال دیگر:
فرض کنید نیاز داریم یک فایل را بخوانیم و اگر به یک خط خاص برسیم، به یک بخش دیگر از کد بپریم:
$file = fopen("example.txt", "r");

if ($file) {
while (($line = fgets($file)) !== false) {
if (strpos($line, 'special keyword') !== false) {
goto specialProcessing;
}
echo "Reading line: $line";
}

fclose($file);
}

specialProcessing:
echo "Special processing for a line containing 'special keyword'.";


در اینجا، فایل example.txt خط به خط خوانده می‌شود و اگر خطی شامل کلمه کلیدی 'special keyword' باشد، جریان برنامه به برچسب specialProcessing منتقل می‌شود.

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

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍15
⭕️ آموزش‌های عمومی PHP

💠 در این سری از آموزش‌های زبان PHP به موارد عمومی این زبان از جمله Enum ها و Closure ها و Arrow Function ها و سایر موارد مرتبط با زبان PHP پرداخته شده است.
🔥10👍5
قابلیت Type Declarations (تعیین نوع) به شما این امکان را می‌دهد که نوع متغیرها، پارامترهای تابع، مقادیر بازگشتی و ویژگی‌های کلاس را مشخص کنید. این کار به افزایش استحکام کد و جلوگیری از خطاهای احتمالی در زمان اجرا کمک می‌کند.

مثال:
// Property
public int $number;

// Const
public const int MAX_LIMIT = 100;

// Function and Method params:
function sum(int $a, int $b){}

// Return type:
function sum($a, $b): int {

}


انواع Type Declarations:

انواع پایه‌ای (Scalar Types):
این انواع، ساده‌ترین نوع‌ها در PHP هستند که شامل موارد زیر می‌شوند:

‏int برای اعداد صحیح (integer).
‏float برای اعداد اعشاری (floating-point numbers).
‏string برای رشته‌ها.
‏bool برای مقادیر بولی (true یا false).
‏false برای مقدار همیشه fasle.‏
‏true برای مقدار همیشه true.

function addNumbers(int $a, int $b): int {
return $a + $b;
}


انواع ترکیبی (Compound Types):
این نوع‌ها ترکیبی از انواع مختلف هستند:

‏array‏ برای آرایه‌ها.
‏object برای اشیاء.
‏callable برای تابع‌هایی که می‌توان آن‌ها را فراخوانی کرد (مانند closure ها، نام توابع به صورت رشته، و غیره).
‏iterable برای انواعی که قابل تکرار (iteration) هستند، شامل آرایه‌ها و اشیاء که از Traversable پیروی می‌کنند.

function getValues(array $input): iterable {
return new ArrayIterator($input);
}


انواع خاص (Special Types):
‏mixed نوعی که می‌تواند هر چیزی باشد. ‏
‏void برای توابعی که مقداری برنمی‌گردانند.
‏null برای مشخص کردن یک مقدار null.
‏never نوعی که نشان می‌دهد تابع هرگز برنمی‌گردد (معمولاً برای توابعی که با exit() یا پرتاب استثناها (Exception) خاتمه می‌یابند).

function doNothing(): void {
// This function does not return any value.
}

function terminate(): never {
exit("Terminating...");
}


انواع کلاس‌ها و اینترفیس‌ها (Class/Interface Types):
شما می‌توانید از نام کلاس‌ها یا اینترفیس‌ها به عنوان نوع پارامتر یا نوع مقدار بازگشتی استفاده کنید. این کار باعث می‌شود که پارامترها یا مقادیر بازگشتی باید از آن کلاس یا اینترفیس باشند.

class User {
// Class code
}

function setUser(User $user) : User{
// Operation on $user
}


انواع نال‌پذیر (Nullable Types):
با افزودن یک علامت ? قبل از نوع، می‌توانید یک نوع را نال‌پذیر کنید، به این معنا که مقدار می‌تواند از نوع مشخص شده یا null باشد.

function findUser(?int $id): ?User {
if ($id === null) {
return null;
}
// Search for the user and return the User object
}


انواع ترکیبی منطقی (Union Types):
می‌توانید از ترکیب چند نوع با استفاده از | استفاده کنید. این به شما اجازه می‌دهد که یک پارامتر یا مقدار بازگشتی بتواند یکی از چندین نوع مختلف باشد.

function processInput(int|string $input) {
if (is_int($input)) {
// Int processing
} else {
// String processing
}
}


انواع متقاطع (Intersection Types):
این نوع به شما اجازه می‌دهد که یک پارامتر یا مقدار بازگشتی ترکیبی از چندین نوع مختلف (همزمان) باشد. این نوع زمانی استفاده می‌شود که یک شیء باید همزمان از چندین اینترفیس پیروی کند.

function handleInput(A&B $input) {
// $input must be of type A and B at the same time.
}


‏self و parent و static :
‏self برای اشاره به کلاس فعلی.
‏parent برای اشاره به کلاس والد (در صورت وجود).
‏static به یک کلاس خاص اشاره کند، به کلاس فعلی یا کلاسی که از آن ارث‌بری شده است اشاره می‌کند.

class Base {
public function getClass(): static {
return $this;
}
}


🔖 #PHP, #پی_اچ_پی

👤 AmirHossein

💎 Channel: @DevelopixPHP
👍12🔥31