استفاده از سرویس منیجر برای تنظیمات table gateway و تزریق کردن اطلاعات درون AlbumTable:

برای اینکه همیشه از یک مثال از AlbumTalbe استفاده کنیم از servicemanager بهره می گیریم تا چه جوری یه دونه بسازه. اینکار با استفاده از کلاس module و با متد ()getServiceConfig به راحتی انجام خواهد شد، ماژول منیجر این فایل را لود می کند و در سرویس منیجر به کار می برد. با این روش ما هر موقع که به این کلاس احتیاج داشتیم در اختیارمون هست.

برای تنظیم کردن سرویس منیجر ما یا می تونیم اسم کلاس رو به کار ببریم که بعنوان مثال معرفی بشه یا اینکه یک factory تعریف کنیم که یک شی معرفی کنه وقتی که ماژول منیجر بهش احتیاج داره. برای اینکار کد زیر را به module/Album/src/Module.php اضافه می کنیم.

namespace Album;

// Add these import statements:
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
use Zend\ModuleManager\Feature\ConfigProviderInterface;

class Module implements ConfigProviderInterface
{
    // getConfig() method is here

    // Add this method:
    public function getServiceConfig()
    {
        return [
            'factories' => [
                Model\AlbumTable::class => function($container) {
                    $tableGateway = $container->get(Model\AlbumTableGateway::class);
                    return new Model\AlbumTable($tableGateway);
                },
                Model\AlbumTableGateway::class => function ($container) {
                    $dbAdapter = $container->get(AdapterInterface::class);
                    $resultSetPrototype = new ResultSet();
                    $resultSetPrototype->setArrayObjectPrototype(new Model\Album());
                    return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
                },
            ],
        ];
    }
}

این متد یک آرایه از factories می گردونه و ماژول منیجر قبل از پاس دادن اون به سرویس منیجر آن ها رو با هم ترکیب می کنه . فکتوری Album/Model/AlbumTable از سرویس منیجر استفاده می کنه تا یک سرویس Album\Model\AlbumTableGateway بسازه تابا ست کردن TableGateway ،به constructor کلاس پاس داده بشه. ما به سرویس منیجر می گوییم که سرویس AlbumTableGateway با فراخوانی Zend\Db\Adapter\AdapterInterface ساخته شده و از اون برای ساخت شی TableGateway استفاده می کنیم.

به TableGateway گفته میشه که از شی Album استفاده کنه هر زمانی که می خواد یک ردیف جدید بسازه.

کلاس های TableGateway از prototype pattern برای ساخت ردیف ها و موجودیت ها استفاده می کنه این به معنی کلون سازی از نمونه های ایجاد شده قبلی آبجکت به جای ساخت آبجکت جدید می باشد.

نتیجه نهایی این است که حالا ما یک فکتوری برای سرویس Zend\Db\Adapter\AdapterInterface داریم . حالا می تونیم تنظیمات برای ساخت یک آداپتر(adapter) رو انجام بدیم.

ماژول منیجر برای هر ماژول تنظیمات فایل module.config.php ترکیب می کنه و با فایل های config/autoload/ (اول در global.php و سپس در local.php)ترکیب می کنه. مافایل اطلاعات تنظیمات دیتابیس رو global.php قرار می دهیم که شما باید به ورژن کنترل سیستم خودتون بسپرید. شما می توانید از فایل local.php (خارج از VCS) اطلاعات دسترسی به دیتابیس رو قرار دهید. حالا وارد فایل config/autoload/global.php در برنامه شده و تنظیمات زیر را انجام دهید.

return [
    'db' => [
        'driver' => 'Pdo',
        'dsn'    => sprintf('sqlite:%s/data/zftutorial.db', realpath(getcwd())),
    ],
];

اگر شما در حال تنظیم کردن یک دیتابیس هستید که نیاز به دسترسی دارد می توانید دسترسی های عمومی را در فایل config/autoload/global.php انجام دهید و تنظیمات برای محیط کنونی خود را شامل DSN و دسترسی های بالاتر خود را در فایل config/autoload/local.php قرار دهید.این فایل ها هنگام اجرای برنامه با هم ترکیب می شوند به منظور اطمینان از تعریف کامل و با امکان این که سطوح دسترسی را در خارج از VCS قرار دهید.

بازگشت به کنترلر:
خب حالا ما مدل رو ایجاد کردیم و نیاز داریم برای استفاده از اون داخل کنترلر اینجکت کنیم.
در مرحله اول باید در کنترلر یک constructor ایجاد کنیم. وارد فایل module/Album/src/Controller/AlbumController.php شوید و تغییرات زیر را اعمال کنید.

namespace Album\Controller;

// Add the following import:
use Album\Model\AlbumTable;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class AlbumController extends AbstractActionController
{
    // Add this property:
    private $table;

    // Add this constructor:
    public function __construct(AlbumTable $table)
    {
        $this->table = $table;
    }

    /* ... */
}

چون ما فکتوری خودمون رو اینجا درست کردیم می تونیم فایل module/Album/config/module.config.php را تغییر دهیم و قسمت معرفی کنترلر رو پاک کنیم.

<?php
namespace Album;

// Remove this:
use Zend\ServiceManager\Factory\InvokableFactory;

return [
    // And remove the entire "controllers" section here:
    'controllers' => [
        'factories' => [
            Controller\AlbumController::class => InvokableFactory::class,
        ],
    ],

    /* ... */
];

حالا می تونیم به table$ در داخل کنترلر زمانی که نیاز به تعامل با مدل داریم دسترسی داشته باشیم.

لیست کردن آلبوم ها:
برای لیست کردن آلبوم ها باید آنها را از مدل گرفته و به view پاس بدهیم.
برای اینکار داخل متد() indexAction کد زیر را وارد می کنیم.

// module/Album/src/Controller/AlbumController.php:
// ...
    public function indexAction()
    {
        return new ViewModel([
            'albums' => $this->table->fetchAll(),
        ]);
    }
// ...

در فریمورک زند برای اینکه متغیر ها را در view ها ست کنیم از یک نمونه از ()viewModel استفاده می کنیم، که آرگومان اول آن شامل اطلاعاتی است که می خواهیم به صفحه view پاس داده شود.
و متغیر ها به view به طور خودکار ارسال می شوند. آبجکت های viewModel به ما اجازه میدهند که اسکریپت های view  را تغییر دهیم اما به طور پیش فرض {module name}/{controller name}/{action name} استفاده می شود.

<?php
// module/Album/view/album/album/index.phtml:

$title = 'My albums';
$this->headTitle($title);
?>
<h1><?= $this->escapeHtml($title) ?></h1>
<p>
    <a href="<?= $this->url('album', ['action' => 'add']) ?>">Add new album</a>
</p>

<table class="table">
<tr>
    <th>Title</th>
    <th>Artist</th>
    <th>&nbsp;</th>
</tr>
<?php foreach ($albums as $album) : ?>
    <tr>
        <td><?= $this->escapeHtml($album->title) ?></td>
        <td><?= $this->escapeHtml($album->artist) ?></td>
        <td>
            <a href="<?= $this->url('album', ['action' => 'edit', 'id' => $album->id]) ?>">Edit</a>
            <a href="<?= $this->url('album', ['action' => 'delete', 'id' => $album->id]) ?>">Delete</a>
        </td>
    </tr>
<?php endforeach; ?>
</table>

اولین کاری که می کنیم ست کردن تیتر برای صفحه می باشد. سپس تیتر را برای تگ <head> از طریق() headTitle اضافه می کنیم. بعد از اینکار یک لینک برای ورود به صفحه add قرار می دهیم.
متد ()url که بوسیله zend-mvc و zend-view آماده شده است برای این منظور استفاده می شود.
اولین پارامتر در این متد نام روتی هست که از اون استفاده میکنیم و پارامتر های آنهایی هست که در تعریف URL استفاده می شود. اینجا از روت album استفاده می کنیم که ۲ پارامتر را قبول می کند action و id.
برای گرفتن تمام ردیف های دیتابیس از حلقه استفاده می کنیم و پارامتر اون رو از کنترلر می گیریم.
سپس برای نشان دارن ردیف های جدول دیتابیس یک table ایجاد می کنیم که شامل تیتر ها و لینک های مورد نیاز برای پاک کردن و ویرایش می باشد.
حلقه ی foreach برای تکرار در لیست های آلبوم بکار می رود.