سرفصل‌های آموزشی
آموزش معماری MVC
ساخت لایهٔ Controller

ساخت لایهٔ Controller

تا این مرحله از دورهٔ آشنایی با معماری MVC با موفقیت توانسته‌ایم تا لایه‌های View و Model را پیاده‌سازی نماییم؛ حال در این آموزش قصد داریم تا به توسعهٔ لایهٔ Controller بپردازیم که این وظیفه را دارا است تا مابین دو لایهٔ دیگر ارتباط برقرار سازد. برای این منظور، پوشه‌ای تحت عنوان Controllers ساخته و فایلی تحت عنوان DefaultController.php با محتویات زیر داخل آن ایجاد می‌کنیم:

<?php
namespace Base\Controllers;

use Core\BaseController;

class DefaultController extends BaseController
{
    public function homepage()
    {}

    public function about($param = null)
    {}

    public function notfound()
    {}

    public function users()
    {}
}

طبق روال معمول،‌ ابتدا به ساکن اقدام به درج نِیم‌اِسپس این فایل می‌کنیم و با توجه به اینکه قرار است در این فایل از کلاس‌های User ،Database و BaseController استفاده نماییم، آن‌ها را use می‌کنیم.

نامی مشابه نام فایل تحت عنوان DefaultController برای این کلاس در نظر گرفته و این در حالی است که این کنترلر کلیهٔ خصوصیات خود را از کلاس BaseController به ارث خواهد برد؛ به عبارتی، از این پس می‌توانیم از ویژگی‌های کلاس BaseController که حاوی کدهای زیر است در کنترلر خود استفاده نماییم:

<?php
namespace Core;

use Core\Interfaces\ControllerInterface;

class BaseController implements ControllerInterface
{
    public function renderView($moduleType, $controllerName, $view, $data = [])
    {
        require_once "../app/$moduleType/Views/$controllerName/$view.php";
    }
}

همان‌طور که قبلاً در حین نوشتن این کلاس توضیح دادیم، فانکشن ()renderView این وظیفه را دارا است تا بر اساس پارامترهایی که می‌گیرد، ویوی مرتبط را ایمپورت نماید. داخل کلاس DefaultController چهار متد یا اَکشن مختلف داریم که عبارتند از:

- متد ()homepage به منظور نمایش هوم‌پیج سایت
- متد ()about به منظور نمایش صفحهٔ دربارهٔ ما
- متد ()notfound به منظور نمایش صفحهٔ 404
- متد ()users به منظور نمایش لیست کاربران

ساخت اَکشن مرتبط با صفحهٔ هوم‌پیج

متد یا اَکشن ()homepage را به صورت زیر تکمیل کرده سپس به توضیح آن خواهیم پرداخت:

public function homepage()
{
    parent::renderView('Base', 'default', 'homepage');
}

شیئ‌گرایی در زبان پی‌اچ‌پی بدین صورت است که اگر از داخل کلاس فرزند بخواهیم به متدی از کلاس والد دست یابیم، می‌باید از کیورد parent استفاده نماییم بدین صورت که این کیورد را نوشته سپس علائم :: را درج می‌کنیم و نام متد مربوطه از کلاس والد را می‌نویسیم. بر همین اساس، داخل بدنهٔ متد ()homepage به متد ()renderView دست یافته‌ایم که این وظیفه را دارا است تا به ویویی مرتبط با آرگومانی که دریافت می‌کند ارجاع دهد. چنانچه به پارامترهای ورودی متد ()renderView نگاهی بیندازیم، خواهیم دید که این متد برای اجرا نیاز به پارامترهای زیر دارد:

public function renderView($moduleType, $controllerName, $view, $data = [])
{
    require_once "../app/$moduleType/Views/$controllerName/$view.php";
}

پارامتر moduleType$ به نام ماژول اشاره دارد که در این مثال مقدار استرینگ Base را در نظر گرفته‌ایم. پارامتر controllerName$ به نام کنترلر اشاره دارد که در این مثال مقدار استرینگ default را در نظر گرفته‌ایم که این مقدار با همان فولدری که داخل لایهٔ Views ساخته و گفتیم که هم‌نام با کنترلر است مرتبط می‌باشد. پارامتر سوم به نام فایل ویو اشاره دارد که در این مثال استرینگ about را در نظر گرفته‌ایم که در نهایت با استرینگ php. کانتکت شده و هم‌نام با ویوی about.php می‌گردد. در نهایت هم پارامتر data$ را داریم که در اَکشن ()homepage آن را پاس نداده‌ایم چرا که به آن نیازی نخواهیم داشت.

ساخت اَکشن مرتبط با صفحهٔ دربارهٔ ما

اَکشن ()about را به صورت زیر تکمیل کرده سپس به توضیح آن خواهیم پرداخت:

public function about($param = null)
{
    parent::renderView('Base', 'default', 'about', [
        'param' => $param,
    ]);
}

همان‌طور که می‌بینیم، اَکشن ()about بر خلاف ()homepage یک پارامتر ورودی تحت عنوان param$ با مقدار اولیهٔ [] می‌گیرد سپس آن را در قالب آرگومان چهارم به متد ()renderView پاس داده و در فایل about.php به صورت زیر مورد استفاده قرار می‌دهیم:

<!DOCTYPE html>
<html>
    <head>
        <title>About</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
        <link rel="stylesheet" href="../../../../css/styles.css">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    </head>
    <body>
        <div class="container">
            <h1>About</h1>
            <p>This is the about page of the site. <?= $data['param'] ?></p>
        </div>
    </body>
    <script src="../../../../js/app.js"></script>
</html>

می‌بینیم که در خط چهاردهم با استفاده از تگ‌های <? =?> اقدام به چاپ آرایهٔ ['data['param$ کرده‌ایم.

ساخت اَکشن مرتبط با صفحهٔ 404

اَکشن مرتبط با صفحهٔ 404 هم کاملاً مشابهٔ اَکشن صفحهٔ هوم‌پیج است به طوری که داریم:

public function notfound()
{
    parent::renderView('Base', 'default', 'notfound');
}

در ارتباط با طراحی صفحه‌های 404 توصیه می‌کنیم به مقالهٔ نکات یوایکسی برای طراحی صفحه‌های خطای 404 مراجعه نمایید.

ساخت اَکشن مرتبط با صفحهٔ لیست کاربران

در ارتباط با اَکشن‌های کنترلر DefaultController، موردی که نسبت به سایرین از پیچیدگی بیشتری برخوردار می‌باشد ()users است چرا که در این اَکشن قصد داریم تا ارتباط مابین ویو و مدل را برقرار سازیم:

public function users()
{
    $database = (new Database())->connect();
    $users = new User($database);
    $result = $users->fetch();
    $result = $result->fetchAll(\PDO::FETCH_ASSOC);

    parent::renderView('Base', 'default', 'users', [
        'param' => $result,
    ]);
}

در تفسیر کدهای داخل این متد می‌توان گفت که ابتدا آبجکتی از روی کلاس Database ساخته و متد ()connect آن را فراخوانی کرده‌ایم و آن را به متغیری تحت عنوان database$ منتسب نموده‌ایم سپس آبجکتی از روی مدل User ساخته و متغیر database$ را به عنوان پارامتر ورودی این کلاس پاس داده‌ایم و در نهایت این مدل را به متغیری تحت عنوان users$ منتسب کرده‌ایم. در ادامه متغیری تحت عنوان result$ ساخته‌ایم که مقدارش برابر با فراخوانی متد ()fetch روی آبجکت users$ است و در نهایت هم مجدد مقدار این متغیر را برابر با فراخوانی متدی تعبیه‌شده در کلاس PDO تحت عنوان ()fetchAll روی همان متغیر قرار داده‌ایم.

با توجه به اینکه متد ()fetch در مدل User متغیر statement$ را ریترن می‌کند، لذا به متغیر تعبیه‌شدهٔ ()fetchAll در کلاس PDO دسترسی خواهیم داشت که به عنوان پارامتر ورودی این متد از PDO::FETCH_ASSOC\ استفاده نموده‌ایم که این دستور را به کلاس مذکور می‌دهد تا نتایج فراخوانی داده‌ها از جدول users را در قالب یک به اصطلاح Associative Array ریترن کند که در آن کلیدهای آرایه همان ستون‌های جدول users است.

در پایان، همچون اَکشن‌های دیگر این کنترلر، متغیر result$ را به عنوان مقدار کلید param از آرگومان چهارم متد ()renderView به فایل users.php پاس داده‌ایم که با مراجعه به این فایل خواهیم داشت:

<!DOCTYPE html>
<html>
    <head>
        <title>Users` List</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
        <link rel="stylesheet" href="../../../../css/styles.css">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    </head>
    <body>
        <div class="container">
            <h1>Users` List</h1>
            <?php
            if ($data['param']) {
                echo "<ol>";
                foreach ($data['param'] as $user) {
                    echo "<li>{$user['first_name']} {$user['last_name']}</li>";
                }
                echo "</ol>";
            }
            ?>
        </div>
    </body>
    <script src="../../../../js/app.js"></script>
</html>

می‌بینیم که به سادگی روی این آرایه foreach زده و تک‌تک مقادیر آن را چاپ کرده‌ایم.

در این آموزش به تکمیل لایهٔ Controller در معماری MVC پرداختیم که این وظیفه را دارا است تا نقش پلی ارتباطی مابین ویو و مدل را بازی نماید به طوری که در تکمیل اَکشن مرتبط با لیست کاربران، به بررسی این موضوع پرداختیم که به چه شکل می‌توان ابتدا دیتا را از طریق مدل از دیتابیس فراخوانی کرده سپس آن‌ را در اختیار ویو گذاشته و ویو هم در قالب یک صفحهٔ اچ‌تی‌ام‌اس ساده لیست کاربران را به نمایش بگذارد.

online-support-icon