چرا از کلاس Request دوبار new کردیم؟

پرسیده شده
فعالیت 934 روز پیش
دیده شده 422 بار
0

سلام و عرض ادب

ما توی فایل init یکبار از کلاس Request یه آبجکت new کردیم. اینجا:

define('BASE_PATH',__DIR__ . "/../");

include BASE_PATH . 'vendor/autoload.php';

$dotenv = Dotenv\Dotenv::createImmutable(BASE_PATH);
$dotenv->load();

$request = new \App\Core\Request();

include BASE_PATH . 'helpers/helpers.php';

include BASE_PATH . 'routes/web.php';

بعد  اومدیم تو متد construct کلاس Router هم باز یه بار دیگه از این کلاس new کردیم. اینجا:

    public function __construct()
    {
        $this->request = new Request();
        $this->routes = Route::routes();
        $this->currentRoute = $this->findRoute($this->request) ?? null;
    }

این یکی از اصول solid یا clean code رو نقض نمیکرد؟ الان اسمش رو یادم نمیاد. ولی چیزی که یادم میاد تو یکی از جلسات گفته شد که از یه کلاس بیشتر از یک بار new نشه. باید یکبار یک آبجکت از اون کلاس ساخته شه و هر جا نیاز بود از همون آبجکت استفاده کنیم.

اگه درست متوجه شدم،1- اینجا چرا دوبار new کردیم؟ و 2- چطور باید اینجا این مشکل رو حل کنیم؟

فایل پیوست

2
حذف شده

سلام.

اگر شما بخواهید از Reflection API هم استفاده کنید بازهم باید مثل بدون رفلکشن، وابستگی رو بعنوان پارامتر تزریق کنید. اگر پارامتری داخل کلاس تعریف نشده باشه چطور میتونیم دسترسی داشته باشیم؟ مگر اینکه ساختار به شکلی باشه که instance (از کلاس مد نظر) درون کلاس های والدش ساخته شده باشد بنابراین اینطوری میشه دسترسی پیدا کرد.

اما در این کدی که اوردید باید به این شکل عمل کرد:

public function __construct(Request $request)
{
    $this->request = $request;
    $this->routes = Route::routes();
    $this->currentRoute = $this->findRoute($this->request) ?? null;
}

حالا باید زمانی که ازین کلاس یک instance ساخته میشه، به هر طریقی(چه با Reflection و چه بطور ساده) پارامتر request مقدار دهی بشه.

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

متد build رو میتونید از این لینک بررسی کنید که فریمورک لاراول، چطور از ReflectionClass و متد getConstructor استفاده میکند.

راه دیگه میتونید یک کلاس helpers یا یک تابع برای ساخت آبجکت مورد نظر در ساختار برنامه تون کد نویسی کنید. البته خب باید به این مسئله هم توجه داشت که چطور و چه زمان این کلاس ها و متد ها call بشن.

شما اگر بخواهید جای دیگه ای یک instance از Rquest بسازید دیگه به این تکه کد در فایل init نیازی ندارید:

$request = new \App\Core\Request();

اگر هم بخواهید از همین تکه کد بالا بهره ببرید، خیلی ساده، زمانی که یک شیء از Router میسازید، $request رو هم بعنوان پارامتر constructor ارسال کنید.

 

یه نکته ای هم در مورد Reflection بگم، ببینید بصورت کلی کار Reflection اینه که بتونیم Inspect کنیم و ساختار و متدها و پارامترها و . . . رو مورد بررسی قرار بدیم، ما بغیر از Reflection API داخل خود PHP هم توابعی که کار Reflection رو میکنند، داریم، اونها هم میتونن بعنوان توابع Reflection ازشون نام برد.

چندتاشونو برای مثال میارم:

class_exists()

get_class()

get_class_methods()

get_parent_class()

is_subclass_of()

method_exists()

میخواستم یه نتیجه ای بگیریم که خیلی از کارهارو میتونیم بدون Reflection API هم پیاده کنیم باید ببینید کاری که میخواهید انجام بدید داخل توابع PHP وجود دارد یا خیر! ضمناً Reflection API ظاهراً یه مقدار روی performance  تاثیر میذاره.(تست نگرفتم)

 

فایل پیوست

محسن موحد

توسط

محسن موحد

20 مهر 00

2
حذف شده

سلام و احترام

فکر کنم شما منظورتون دیزاین پترن singleton باشه

توی کلاس ها ما هر چیزی که اون کلاس نیاز داره رو میتونیم از طرق contructorش وابستگی هاشون رو تزریق بکنیم، توی کلاس روتر مواردی که این کلاس نیاز داره به این شکل داریم استفاده میکنیم

نمیشه گفت که داریم به بهترین شکل از کلاس request استفاده میکنیم. مثلا برای پاس دادن آبجکت request به متدهای کنترلر هی مختلف میتونستیم از reflection استفاده کنیم

https://www.php.net/manual/en/reflectionfunctionabstract.getparameters.php

فایل پیوست

امیر صالحی

توسط

امیر صالحی

18 مهر 00

حذف شده
سلام. متوجه این قسمت نشدم: "مثلا برای پاس دادن آبجکت request به متدهای کنترلر های مختلف"
محسن موحد

20 مهر 00

0
حذف شده

ممنون آقای صالحی، داکیومنتای Reflection رو خوندم، جالب بود.

فقط یه سری مزیت داره، یه سری اشکال.

الان اینجا تو این کد:

$ref = new ReflectionClass('App\Core\Request');
        $ref->newInstance()->getIp();

یه آبجکت از ReflectionClass ساختم و کلاس Request رو بهش پاس دادم، بعد با استفاده از متد ()newInstance یه شی از کلاس Request ساختم و در ادامه تونستم ازش استفاده کنم. (به طور مثال اینجا متد getIpش رو صدا زدم.)

ولی خب باز هم من اینجا یه بار دیگه از کلاس Request، یه شی دیگه new کردم.

 

البته یه راه دیگه هم داره و اونم به این صورته:

$reflectedObject = new ReflectionObject($request);

اینجا اطلاعات آبجکت request که یه instance از کلاس Request هست رو میگیریم.

ولی موضوع اینجاست که الان آبجکت request توی init تعریف شده و توی کلاس Router قابل دسترس نیست. با global scope هم امتحان کردم، به این صورت:

$reflectedObject = new ReflectionObject(global $request);

جواب نداد.

فایل پیوست

پویا پارسایی

توسط

پویا پارسایی

19 مهر 00