۷ Amir
Access Modifier (private)
جامعه پی اچ پی ایجاد شده در ۱۱ بهمن ۱۴۰۱

سلام تو این جلسه گفته شد که تحت هیچ عنوان نمیشه به پراپرتی و متود هایی که access modifier انها private هست خارج از کلاس دسترسی داشت یه سوالی که برام پیش اومد اینه که تو یکی از تاپیک‌ها که دیدم گفته شد از طریق  Reflection Api میشه خارج کلاس بهش دسترسی داشت میشه راجبش بیشتر توضیح بدید

سلام امیر عزیز

منظور همون تعریف getter هست.

احمدرضا فاطمی کیا ۱۱ بهمن ۱۴۰۱، ۱۶:۳۴

سلام،

ببینید Encapsulation(getter/setter) توسط خود برنامه نویس در حین کدنویسی پیاده میشود. (یادگرفتیم که چطور با پیاده سازی getter به پراپرتی‌ها دسترسی داشته باشیم.) اگر بخواهید کلاس‌ها و متدها و پراپرتی‌ها و ... رو اصطلاحاً inspect کنید Reflection Api کمک میکنه تا در حین اجرای کد بررسی کنید و حتی تغییراتی رو اعمال کنید. یکی از قابلیت هایی که Reflection میتونیم پراپرتی‌های کلاس رو بخونیم:

class Foo 
{
    private $privateProperty = '7Learn.com';    
}
$obj = new Foo;
$reflector = new ReflectionClass($obj);
$property = $reflector->getProperty('privateProperty');
var_dump($property->getValue($obj));
// Fatal error: Uncaught ReflectionException: Cannot access non-public property Foo::$privateProperty

اگر اسکریپتو اجرا کنید با خطا مواجه میشید که با اجازه ی دسترسی این مشکل حل میشود: (setAccessible)

class Foo 
{
    private $privateProperty = '7Learn.com';    
}
$obj = new Foo;
$reflector = new ReflectionClass($obj);
$property = $reflector->getProperty('privateProperty');
$property->setAccessible(true);
var_dump($property->getValue($obj));

نکته: از php 8.1 به بعد نیازی به استفاده از setAccessible نیست و اگر هم ننویسید با خطا روبرو نمیشید. (مطرح شده در PHP RFC)

برای فهمیدن این تغییرات میتونید اسکریپت رو روی نسخه‌های مختلف php اجرا بگیرید.(3v4l.org)

محسن موحد ۱۲ بهمن ۱۴۰۱، ۲۲:۲۷

الان من اینو متوجه نشدم خود استاد گفتن که خارج از کلاس کلا نمیشه به پراپرتی که از نوع پرایویت هستن دسترسی داشت و الان شما میگید که با این reflection api میشه من اینو متوجه نمیشم

Amir ۱۳ بهمن ۱۴۰۱، ۰۷:۳۴

پیشنها میکنم مقاله زیر رو برای درک مطالعه کنید:

https://anexia.com/blog/en/reflection-in-php-projects/amp/

احمدرضا فاطمی کیا ۱۳ بهمن ۱۴۰۱، ۱۰:۳۲

مثالی از این پیاده سازی میارم با ابزار خود PHP:

نکته اول: از داخل کلاس به عناصر private دسترسی داریم و معمولا متدهایی بعنوان getter/setter پیاده میکنیم.

نکته دوم: از طریق Closure::bind یا Closure::bindTo تابعی به scope کلاس اضافه میکنیم تا بتوانیم دسترسی بگیریم.

class A {
    private $ifoo = 2;
}
$bcl = Closure::bind(fn() => $this->ifoo, new A(), 'A');
echo $bcl();

با استفاده از bindTo:

$myClosure = function() {
    echo $this->property;
};
class MyClass
{
    private $property;
    public function __construct($propertyValue)
    {
        $this->property = $propertyValue;
    }
}
$myInstance = new MyClass('Hello world!');
$myBoundClosure = $myClosure->bindTo($myInstance, MyClass::class);
$myBoundClosure(); // Shows "Hello world!"

این کلاس رو هم میتونید ببینید.


نتیجه گیری این است که اصل ماجرا و گفته ی شما تغییری نکرده، منتها تکنیک پیاده سازی متفاوت رو میبینیم چه بطور مستقیم(getter/setter) و چه غیر مستقیم.(در اینجا بصورت غیر مستقیم و با خود PHP و در Reflection API توسط Zend Engine)

محسن موحد ۱۳ بهمن ۱۴۰۱، ۲۰:۵۹

تشکر از آقای فاطمی کیا و آقای موحد عزیز بابت راهنمایی هاشون?

Amir ۱۳ بهمن ۱۴۰۱، ۲۲:۵۸

موفق باشید.

تاپیک را به حل شده تغییر وضعیت دهید تا از پیگیری خارج شود.

بهترین پاسخ
احمدرضا فاطمی کیا ۱۴ بهمن ۱۴۰۱، ۰۴:۵۴