بیان خلاصه ای از بحث توسط هوش مصنوعی:
در فصل قبل، ما Backend را برای کامپوننت خود توسعه دادیم. با این حال، بسیاری از کامپوننت ها به یک قسمت frontend نیز نیاز دارند که کاربران ما بتوانند با کامپوننت ما تعامل داشته باشند.
در این فصل، قسمت frontend کامپوننت خود را توسعه خواهیم داد. ما یک لیست پروژه ایجاد خواهیم کرد که پروژه های فعلی ما را نشان می دهد. سپس، یک نمای جزئیات پروژه را کدنویسی می کنیم که جزئیات هر پروژه را نشان می دهد. با توسعه این نماهای جدید، یاد می گیریم که چگونه آیتم های منو برای اجزای خود ایجاد کنیم. همچنین یاد خواهیم گرفت که چگونه گزینه هایی را به آیتم های منو اضافه کنیم.
هنگام کدنویسی برای frontend ، باید مراقب باشیم و تجربه کاربری را بهبود بخشیم، بنابراین باید آدرس های دوستانه ای (Friendly URLs) برای کامپوننت خود ایجاد کنیم. در frontend ، ما می خواهیم یک تجربه عالی ارائه دهیم، بنابراین یاد می گیریم که استایل های CSS و تعامل با جاوا اسکریپت ( JS ) را به کامپوننت خود اضافه کنیم.
بنابراین، در این فصل به موارد زیر خواهیم پرداخت :
-
در حال توسعه یک نمای فهرست ظاهری برای کامپوننت ما
-
در حال توسعه نمای آیتم frontend برای کامپوننت ما
-
اضافه کردن URL های دوستانه به کامپوننت ما
-
افزودن CSS و JS به کامپوننت ما
در پایان این فصل، شما قادر خواهید بود یک نمای ظاهری کاربردی به کاربران خود ارائه دهید، که در آن آنها می توانند لیستی از موارد و نمای جزئیات سفارشی شده هر مورد را مشاهده کنند.
الزامات فنی
برای گذراندن این فصل، باید کد را ویرایش کرده و در سایت جوملا آزمایش کنیم. بنابراین، به موارد زیر نیاز خواهید داشت:
-
Visual Studio Code (یا ویرایشگر کد دلخواه شما)
-
سایت جوملا که در فصل های قبل نصب کردیم.
می توانید فایل های کد این فصل را در GitHub در https://github.com/PacktPublishing/Developing-Extensions-for-Joomla-5/tree/chapter03 بیابید.
frontend یک نمای فهرست برای کامپوننت ما
با استفاده از الگوی Model-View-Controller ( MVC ) توسعه افزونه ها در جوملا را ساده می کند. ساختار فایل برای frontend مانند ساختار backend است که فقط با چند تغییر جزئی انجام می شود.
همانطور که در شکل زیر نشان داده شده است، با ایجاد مجدد پوشه ها در داخل پوشه سایت، از قسمت frontend کامپوننت خود شروع می کنیم:
شکل 3.1 - ساختار پوشه برای قسمت frontend کامپوننت ما
ما در حال کدنویسی در قسمت frontend کامپوننت هستیم، بنابراین فایل های را در داخل پوشه src/component/site/ ذخیره می کنیم و مانند backend، پوشه های زیر را داریم:
-
src
-
tmpl
در پوشه src ، همان ساختار پوشه را در backend تکرار می کنیم:
-
Controller
-
Model
-
Service
-
View
فایل ها و محتوای آنها نیز مانند موارد موجود در backend است. بیایید شروع به اضافه کردن فایل ها برای نمای لیست کنیم.
کد گذاری نمای لیست
اگر چه در جوملا، Backend و Frontend دو برنامه جداگانه هستند، اما معماری فایل و الگوهای کدنویسی در هر دو مورد یکسان است. بنابراین، برای نمای لیست در frontend، ما همچنین باید فایلی را با کلاس DisplayController اصلی اضافه کنیم ، که نمایش کامپوننت ما را در قسمت frontend کنترل می کند.
افزودن DisplayController
در frontend کامپوننت، ما فایل src/component/site/src/Controller/DisplayController.php را با کد زیر ایجاد خواهیم کرد:
<?php
namespace Piedpiper\Component\Spm\Site\Controller;
defined('_JEXEC') or die;
use Joomla\CMS\MVC\Controller\BaseController;
class DisplayController extends BaseController
{
protected $default_view = 'Projects';
protected $app;
}
در این کد، اولین چیزی که ممکن است متوجه شوید این است که فضای نام کلاس ما تغییر کرده است. از آنجایی که اکنون در frontend هستیم، مسیر فضای نام ما به Piedpiper\Component\Spm\Site تغییر می کند.
پس از آن، کلاس BaseController را از جوملا MVC فراخوانی میکنیم، دقیقاً همانطور که برای فایل DisplayController.php در backend انجام دادیم.
برای ایجاد لیست پروژه های موجود در frontend ، باید پوشه های MVC را به همان روشی که در فصل قبل برای backend انجام داده ایم، تنظیم کنیم.
افزودن نمای لیست پروژه های ما
در جوملا MVC، صفحه view داده ها را برای مدل درخواست می کند، پس بیایید ببینیم برای نمای خود به چه داده هایی نیاز داریم.
بیایید شروع به ایجاد view خود کنیم، فایل src/component/site/src/View/Projects/HtmlView.php را با کد زیر اضافه میکنیم:
<?php
namespace Piedpiper\Component\Spm\Site\View\Projects;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
class HtmlView extends BaseHtmlView
{
public $state;
public $items=[];
public $pagination;
public function display($tpl=null): void
{
$this->state = $this->get('State');
$this->items = $this->get('Items');
$this->pagination = $this->get('Pagination');
parent::display($tpl);
}
}
اولین چیزی که می بینیم این است که فضای نام این کد در پوشه site است :
Piedpiper\Component\Spm\Site\View\Projects
سپس، HtmlView را از جوملا MVC فراخوانی میکنیم و برای جلوگیری از درگیری با نام کلاس خود، آن را مستعار می کنیم.
برای نمایش، باید متد display را پیاده سازی کنیم ، جایی که از مدل داده های وضعیت، صفحه بندی و داده های آیتم را می خواهیم.
از آنجایی که مدل ما کلاسی است که مسئول ارائه همه این داده ها است، بیایید ببینیم چگونه می توانیم آنها را به frontend خود اضافه کنیم.
دریافت داده ها برای نمایش - اضافه کردن مدل
برای اضافه کردن مدلی از نمای پروژه های ما ، فایل src/component/site/src/Model/ProjectsModel.php را ایجاد کنید. ما شروع به تعریف فضای نام خود کرده و کلاسی را ایجاد و اضافه می کنیم:
<?php
namespace Piedpiper\Component\Spm\Site\Model;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Model\ListModel;
class ProjectsModel extends ListModel
{
}
فضای نام این مدل از پوشه site استفاده می کند:
Piedpiper\Component\Spm\Site\Model
همچنین، کلاس ListModel را از جوملا MVC فراخوانی میکنیم تا کد نویسی را برای ما ساده تر کند.
هنگام فراخوانی کلاس ListModel ، باید متد خود را برای populateState پیاده سازی کنیم تا متغیرهایی که باید از تعامل فعلی کاربر دریافت کردیم را منعکس کنیم. بنابراین، این متد را به کلاس اضافه می کنیم:
protected function populateState($ordering = 'name', $direction = 'ASC')
{
$app = Factory::getApplication();
$value = $app->input->get('limit', $app->get('list_limit', 0), 'uint');
$this->setState('list.limit', $value);
$value = $app->input->get('limitstart', 0, 'uint');
$this->setState('list.start', $value);
parent::populateState($ordering, $direction);
}
در این متد، تعداد پروژه هایی که باید نمایش داده شوند (که توسط متغیر list_limit نشان داده می شود) به دست خواهیم آورد و تعیین کنید صفحه بندی ما از کجا شروع می شود (که توسط متغیر limitstart نمایش داده می شود)
برای بدست آوردن این متغیرها از متد $app->input-get() استفاده می کنیم. این متد، متغیر مشخص شده را از فرم درخواست دریافت می کند. علاوه بر نام متغیر به عنوان پارامتر اول، متد، یک پارامتر دوم را نیز می پذیرد که اگر متغیر درخواستی، مقداری نداشته باشد، برگردانده می شود.
در نهایت، پارامتر سوم را با نوع فیلتری که می خواهیم روی متغیر اعمال کنیم، می پذیرد.
(در فصل 4 و فصل 13 درباره فیلتر کردن فرم ها بیشتر خواهیم آموخت.)
در نهایت، ما متد والد را فراخوانی می کنیم تا تمام کارهای دیگری را که جوملا برای ما انجام می دهد، به پایان برساند.
در ListModel جوملا، موارد را با استفاده از getListQuery دریافت می کنیم. در این روش کوئری را برای استفاده از پایگاه داده ایجاد می کنیم. این متد مختص ساختار پایگاه داده ما است، و در لیست پروژه های ما، از این کد را استفاده میکنیم:
protected function getListQuery()
{
$db = $this->getDatabase();
$query = $db->getQuery(true);
$query->select(
$this->getState(
'list.select',
[
$db->quoteName('a.id'),
$db->quoteName('a.name'),
$db->quoteName('a.deadline'),
]
)
)->from($db->quoteName('#__spm_projects', 'a'));
$orderCol = $this->state->get('list.ordering', 'a.name');
$orderDirn = $this->state->get('list.direction', 'ASC');
$query->order($db->escape($orderCol) . ' ' . $db->
escape($orderDirn));
return $query;
}
در این متد از آبجکت پایگاه داده (database object) برای ایجاد کوئری استفاده خواهیم می کنیم. این آبجکت بخشی از آبجکت listModel است و ما آن را با متد ()getDatabase دریافت می کنیم. در نهایت، با توجه به تصمیم کاربر در مورد سفارش، داده های سفارش را از بخش مربوطه اضافه می کنیم.
هنگامی که ما داده ها را درخواست کردیم، view تمام اطلاعات را به فایل چیدمان قالب منتقل می کند، بنابراین بیایید اکنون ببینیم چگونه این داده ها را نشان دهیم.
اضافه کردن الگو برای چیدمان داده ها
قالبlayout مشخص می کند که چگونه داده هایی را که به دست آورده ایم در view نشان داده شود. باید این فایل را در src/component/site/tmpl/projects/default.php ایجاد کنید و فضای نامی را که در ابتدای سند استفاده می کنیم را در یک بلوک PHP تعریف کنیم:
<?php
\defined('_JEXEC');
use Joomla\CMS\Router\Route;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Factory;
?>
پس از بلوک PHP ، علامت گذاری برای لیست پروژه ها را انجام میدهیم:
<form>
<div class="items-limit-box">
<?php echo $this->pagination->getLimitBox(); ?>
</div>
</form>
در این کد، ما نشانه گذاری HTML را برای لیست پروژه های خود اضافه می کنیم، اما باید فهرست را در یک تگ form قرار دهیم تا امکان تعامل فیلترینگ وجود داشته باشد. در داخل فرم، یک درخواست به متد $this->pagination->getLimitBox() اضافه می کنیم. این یک کادر انتخاب را نشان می دهد تا تعداد پروژه هایی را که می خواهیم در هر صفحه ببینیم، انتخاب کنیم.
بعد از کادر انتخاب محدودیت در تعداد، لیست پروژه های خود را ایجاد می کنیم و div زیر را درست بعد از div قبلی به آن اضافه می کنیم:
<div>
<?php foreach ($this->items as $item) : ?>
<div>
<h2>
<?php echo $item->name; ?>
</h2>
<div id="project-id">
<?php echo $item->id; ?>
</div>
<div id="project-deadline">
<?php echo $item->deadline; ?>
</div>
</div>
<?php endforeach;?>
</div>
در این کد HTML، تمام موارد خود را با استفاده از یک حلقه foreach مرور خواهیم کرد. در قسمت frontend، ما از یک بلوک div به جای جدول برای چیدمان داده ها و کمی جذاب تر کردن آنها استفاده می کنیم.
در نهایت، باید در نظر بگیریم که ممکن است بیش از یک صفحه از موارد در این لیست داشته باشیم، بنابراین باید راهی برای تغییر صفحه ارائه دهیم. ما این کار را با استفاده از آبجکت صفحه بندی (pagination object) یک بار دیگر انجام خواهیم داد. بنابراین، ما این کد را درست زیر آخرین div خود اضافه می کنیم:
<div><?php echo $this->pagination->getResultsCounter(); ?></div>
<?php echo $this->pagination->getListFooter(); ?>
<input type="hidden" name="task" value="projects">
همچنین همانطور که در فصل بعدی خواهیم دید، در فرم های جوملا، باید یک نشانه امنیتی را به عنوان یک مقدار پنهان ارسال کنیم، بنابراین آن را قبل از بستن فرم، در خط آخر اضافه می کنیم:
<?php echo HTMLHelper::_('form.token'); ?>
(می توانید اطلاعات بیشتری در مورد آبجکت صفحه بندی (pagination object) در بخش مطالعه بیشتر این فصل بیابید.)
اکنون که تمام فایل های MVC را تکمیل کردیم، می توانیم بسته خود را با فشرده سازی همه فایل ها و نصب آن ها در سایت آزمایشی خود، ایجاد کنیم.
پس از نصب بسته در سایت خود، به yourtestsite.joomla.com/index.php?option=com_spm&view=projects
بروید ، جایی که لیست پروژه های خود را همانطور که در تصویر زیر نشان داده شده است مشاهده خواهید کرد :
شکل 3.2 - لیست پروژه ها در قسمت frontend کامپوننت ما
در شکل قبل، می توانید لیستی از پنج پروژه را از پایگاه داده خود، مشاهده کنید. در بالای صفحه، کادر انتخاب محدودیت در تعداد برای تغییر تعداد پروژه هایی که می توانید ببینید، و فهرستی از صفحات برای بررسی بقیه پروژه ها را خواهید دید.
برخی از بخش های استاندارد فهرست، مانند «کادر انتخاب محدودیت در تعداد» و «صفحه بندی»، خوب به نظر می رسند، اما می توانیم استایل سازی بهتری برای فهرست پروژه ها انجام دهیم. در قسمت بعدی نحوه افزودن فایل های CSS و JS به کامپوننت ما برای بهبود رابط کاربری را خواهیم دید.
افزودن CSS و JS به کامپوننت ما
جوملا با ابزار محبوب Bootstrap 5 عرضه می شود. این جعبه ابزار چندین کلاس CSS و فایل های جاوا اسکریپت را برای افزودن ویژگی ها و استایل های رایج به کامپوننت ما ارائه می دهد.
ما می توانیم کلاس های Bootstrap CSS را مستقیماً در کامپوننت خود با اضافه کردن آنها به نشانه گذاری فایل استفاده کنیم. بیایید لیست پروژه های خود را به سادگی با استفاده از کلاس های Bootstrap بهتر کنیم.
فایل src/component/site/tmpl/projects/default.php را ویرایش کنید و طبق کد زیر صفت class را به عناصر div حاوی عناصر اضافه کنید:
<div class="cards row row-col-3">
<?php foreach ($this->items as $item) : ?>
<div class="card col m-1">
<h2>
<?php echo $item->name; ?>
</h2>
<div id="project-id">
<?php echo $item->id; ?>
</div>
<div id="project-deadline">
<?php echo $item->deadline; ?>
</div>
</div>
<?php endforeach;?>
</div>
ما کلاس های row و row-col-3 را به عنصر div که شامل پروژه ها است، اضافه کردیم. و به هر div ، کلاس های col و m-1 را اضافه کردیم. با این تغییر ساده، فهرست ما اکنون به این شکل است:
شکل 3.3 - شبکه برای لیست پروژه های ما
در این تصویر نتیجه اضافه کردن کلاس های Bootstrap را می بینیم. به جای یک لیست ساده بدون فاصله یا استایل، اکنون یک فهرست خوب از پروژه ها داریم که در هر ردیف پنج پروژه وجود دارد.
Bootstrap5ابزار قدرتمندی است و برای ساخت چیدمان زیبا مفید است. با این حال، بیایید ببینیم چگونه می توانیم CSS خود را با استفاده از Web Asset Manager (مدیر دارایی وب) جوملا ، برای سفارشی سازی تجربه کاربری اضافه کنیم.
اضافه کردن استایل ها و جاوا اسکریپت خودمان به کامپوننت
در جوملا، ما از پوشه media برای ذخیره دارایی های عمومی (Web Asset Manager) استفاده میکنیم. این یک تمرین خوب است زیرا پوشه media برای مرورگر کاربر شما در دسترس عموم خواهد بود و آنها می توانند فایل های داخل آن را بررسی کنند. با این حال، پوشه media مستقیماً برای یک مدیر معمولی سایت شما قابل دسترسی نیست. روش استاندارد برای انجام این کار این است که یک پوشه برای افزونه ی خود ایجاد کنید و در داخل آن، css ، js و هر پوشه دیگری را که ممکن است نیاز داشته باشید قرار دهید. به عنوان مثال، می توانید یک پوشه img برای تصاویر افزونه خود اضافه کنید.
در حال حاضر، ما یک فایل با کلاس های CSS خودمان به کامپوننت اضافه می کنیم.
اول، ما نیاز داریم فایل CSS خود را ایجاد کنید، پس بیایید به فایل کامپوننت خود برویم و فایل src/component/media/css/projects.css را با محتوای زیر ایجاد کنیم:
.cards {
padding: 1rem;
flex-wrap: wrap;
}
.card{
padding: 1rem;
}
.meta {
color: #666;
font-size: .8rem;
}
#project-id{
text-align: right;
}
با استفاده از این فایلCSS، ما مقداری padding (فاصله) بیشتری به پروژه ها اضافه می کنیم و اندازه فونت ID پروژه و تاریخ مهلت را کمی کوچکتر میکنیم. همچنین، ID پروژه به سمت راست محدوده ی خود حرکت می کند.
حال، باید به جوملا دستور دهیم که هنگام نصب کامپوننت، یک پوشه برای کامپوننت ما در داخل پوشه media ایجاد کند. برای این کار، فایل مانیفست کامپوننت را ویرایش می کنیم. به آدرس src/component/spm.xml برویم و خطوط زیر را درست قبل از بستن تگ </ extension> اضافه می کنیم:
<media folder="media" destination="com_spm">
<folder>css</folder>
</media>
این کد یک تگ media است که دو ویژگی دارد:
-
folder : این نشان می دهد که فایل ها و پوشه ها در بسته ما کجا هستند.
-
destination : این نشان دهنده نام زیرپوشه داخل پوشه رسانه جوملا است که فایل های ما در آن ذخیره می شوند.
تگ media ما دارای یک فرزند از نوع folder است که نام پوشه ای را که باید نصب شود نشان می دهد.
بنابراین، اساسا، این به جوملا می گوید که پوشه css که داخل پوشه media بسته است ، در پوشه ای به نام com_spm که داخل پوشه media جوملا است، نصب کند.
اکنون می توانید یک بسته نصب جدید برای کامپوننت خود ایجاد کرده و آن را در سایت آزمایشی خود نصب کنید. پس از آن، می توانید با یک سرویس گیرنده FTP یا با ابزارهای هاست خود، جوملا را بررسی کنید که پوشه media/com_spm را ایجاد کرده است و شامل پوشه css ما با فایل projects.css در داخل آن است.
این عالی است، اما اگر نمای پروژه را بارگذاری کنید، متوجه خواهید شد که استایل های جدید ما هنوز بارگذاری نشده اند. در بخش بعدی، به جوملا دستور می دهیم که فایل CSS جدید را هنگام بارگذاری نمای پروژه، با استفاده از Web Asset Manager بارگذاری کند.
Web Asset Manager در جوملا
مدیر دارایی وب در جوملا 4 برای مدیریت فایل های CSS و JS و بهبود عملکرد سایت معرفی شد. برای استفاده از مدیر دارایی های وب، باید دارایی هایی را که قرار است در افزونه خود استفاده کنیم را ثبت کنیم. این کار را با اعلان فایلی به نام joomla.asset.json با فرمت خاص انجام خواهیم داد.
استفاده از مدیر دارایی وب جوملا چندین مزیت جالب برای کد ما ارائه می دهد:
-
ما را از بارگیری یک فایل دارایی دو بار جلوگیری می کند
-
این به ما کمک می کند تا وابستگی ها را در فایل های JS بارگذاری کنیم
-
هنگامی که افزونه های مختلف سعی می کنند فایل های CSS و JS را با نام های یکسان بارگذاری کنند، از تداخل جلوگیری می کند
بنابراین، بیایید ببینیم چگونه می توانیم از مدیریت دارایی وب جوملا برای افزودن CSS خود به این کامپوننت استفاده کنیم.
ثبت تمام دارایی های خود با استفاده از یک فایل JSON
ثبت دارایی های ما در این کامپوننت به کاربران ما اجازه می دهد که در صورت نیاز به سفارشی سازی یا لغو ، آنها را لغو کند.
همچنین، ثبت دارایی های خود با استفاده از یک فایل JSON به شما امکان می دهد تمام استایل های خود را پیگیری کنید. این روشی سازماندهی شده برای مدیریت دارایی های شما است.
برای استفاده از این فایل دارایی، باید فایل joomla.asset.json را در داخل پوشه src/component/media/ با محتوای زیر ایجاد کنیم:
{
"$schema": "https://developer.joomla.org/schemas/json-
schema/web_assets.json",
"name": "com_spm",
"version": "1.0.0",
"description": "Simple Project Manager component assets",
"license": "GPL-2.0-or-later",
"namespace": "Piedpiper\\component\\Spm",
"assets": [
{
"name": "com_spm.projects",
"type": "style",
"uri": "com_spm/projects.css"
}
]
}
این یک آبجکت JSON است که در آن تمام دارایی های کامپوننت خود را اعلام می کنیم. در ویژگی اول، ویژگی $schema را اعلام می کنیم. این ویژگی نوع ساختاری را که ما از آن پیروی خواهیم کرد را نشان می دهد. این همیشه یکسان است و به یک URL در وب سایت شبکه توسعه دهندگان جوملا اشاره می کند.
پس از آن، باید نام ، نسخه و ویژگی های توضیحات و در نهایت آرایه ای از دارایی های خود را اعلام کنیم.
هر تعریف دارایی نیز یک آبجکت است که باید name ، type و uri (Uniform Resource Identifier) را برای آن اعلام کنیم :
-
ویژگی name همان چیزی است که در صورت نیاز برای گنجاندن دارایی خود استفاده می کنیم. باید منحصر به فرد باشد تا از دارایی دیگری استفاده نکند. بنابراین، در مورد ما، نام افزونه را به عنوان نام اضافه می کنیم.
-
ویژگی type مشخص می کند که چه نوع دارایی را بارگذاری می کنیم. برای هدف این کتاب، می توانیم از style برای بارگذاری یک فایل CSS یا script برای بارگذاری یک فایل JS استفاده کنیم. (لطفاً برای اطلاعات بیشتر درباره Web Asset Manager به بخش مطالعه بیشتر مراجعه کنید.)
-
ویژگی uri به جوملا می گوید که دارایی را که اعلام می کنیم، کجا پیدا کند. مسیر در اینجا مربوط به پوشه media است، جایی که دارایی های خود را ذخیره می کنیم.
هنگامی که فایل joomla.asset.json خود را ایجاد کردیم ، باید آن را در فایل مانیفست ثبت کنیم، بنابراین لطفاً فایل مانیفست خود را به روز کنید و فایل جدید را در داخل تگ media به صورت زیر اضافه کنید:
<media folder="media" destination="com_spm">
<folder>css</folder>
<filename>joomla.asset.json</filename>
</media>
این فایل مانیفست جدید تگ file را داخل تگ media اضافه می کند تا به جوملا بگوید که باید فایل را در پوشه css نصب کند.
هنگامی که فایل joomla.asset.json ما در جای خود قرار گرفت، آماده بارگذاری استایل های CSS جدید خود در کامپوننت خود هستیم.
بارگیری projects.css با استفاده از فایل joomla.assets.json
بعد از ثبت استایل های خود با استفاده از joomla.asset.json ، می توانیم از Web Asset Manager برای بارگذاری استایل های خود استفاده کنیم. فایل src/component/site/tmpl/projects/default.php را ویرایش کرده و محتوای زیر را جایگزین آن کنید:
<?php
\defined('_JEXEC');
use Joomla\CMS\Router\Route;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Factory;
$wam = Factory::getApplication()->getDocument()->getWebAssetManager();
$wam->useStyle('com_spm.projects');
?>
<form>
<div class="items-limit-box">
<?php echo $this->pagination->getLimitBox(); ?>
</div>
<div class="cards row">
<?php foreach ($this->items as $item) : ?>
<div class="card col m-1">
<h2>
<?php echo $item->name; ?>
</h2>
<div id="project-id" class="meta">
<?php echo $item->id; ?>
</div>
<div id="project-deadline" class="meta">
<?php echo $item->deadline; ?>
</div>
</div>
<?php endforeach;?>
</div>
<p><?php echo $this->pagination->getResultsCounter(); ?></p>
<?php echo $this->pagination->getListFooter(); ?>
<input type="hidden" name="task" value="projects">
<?php echo HTMLHelper::_('form.token'); ?>
</form>
در این کد شما می توانید ببینید که چگونه، پس از دریافت Web Asset Manager در $wam ، از آن برای بارگذاری استایل خود استفاده می کنیم و آن را با نامی که در فایل joomla.asset.json اختصاص داده ایم، صدا می زنیم.
علاوه بر استفاده از joomla.asset.json برای ثبت استایل ها و اسکریپت های ما، می توانیم با استفاده از کلاسHtmlHelper استایل ها را اضافه کنیم.
بارگیری دارایی ها با HtmlHelper
در جوملا نیز امکان افزودن فایل های دیگر، بدون استفاده از Web Asset Manager وجود دارد. این توصیه نمی شود، زیرا تمام مزایای استفاده از Web Asset Manager را از دست خواهید داد، اما ممکن است در برخی از حالات مفید باشد.
به عنوان مثال، دارایی های بارگذاری شده با کلاس HtmlHelper بعد از Web Asset Manager بارگذاری می شوند. این به شما این امکان را می دهد که استایل های خاصی از CSS خود را بدون نادیده گرفتن کل فایل، override کنید.
فرض کنید می خواهیم رنگ تاریخ مهلت و شناسه پروژه را تغییر دهیم. ما فایل زیر را با محتوای زیر ایجاد میکنیم:
src/component/media/css/projects-override.css
.meta {
color: #666;
}
از آنجایی که فایل از قبل در پوشه css داخل پوشه media ما قرار دارد ، در بسته بعدی به جوملا ما اضافه خواهد شد، و مسیر نهایی آن media/com_spm/css/projects-override.css خواهد بود.
برای استفاده از این override در قالب خود، فایل src/component/tmpl/projects/default.php را تغییر می دهیم تا این کد را قبل از مقداردهی اولیه متغیر $wam قرار دهیم :
HTMLHelper::_(
'stylesheet',
'com_spm/projects-override.css',
['version' => 'auto', 'relative' => true]
);
اگر کامپوننت خود را بسته بندی و نصب کنید، خواهید دید که چگونه تاریخ مهلت یک رنگ متفاوت را نشان می دهد. جالب است بدانید که ما کلاس HtmlHelper را قبل از فراخوانی Web Asset Manager گنجانده ایم ، اما رندر (rendering) صفحه نهایی در مرحله دیگری اتفاق می افتد، زمانی که دارایی ها به ترتیب تعریف شده، در هسته ی جوملا بارگذاری می شوند.
برگه های استایل اضافه شده از طریق متد HtmlHelper بعد از Web Asset Manager بارگذاری می شود، بنابراین می توانیم از این روش برای نادیده گرفتن استایل های خود، در صفحه استفاده کنیم. مهم نیست چه زمانی آنها را در قالب بارگذاری می کنیم. (ما در فصل 10 موارد override قالب را بررسی خواهیم کرد.)
پس از افزودن استایل های خود به صفحه، نمای لیست خود را در قسمت frontend به پایان رسانده ایم. در حال حاضر، ما به یک نمای item نیاز داریم، تا جزئیات پروژه های ما را ببینید.
در حال توسعه نمای آیتم frontend برای کامپوننت ما
افزودن نمای آیتم در frontend کامپوننت ما با جوملا MVC ، مانند افزودن یک نمای آیتم به backend کامپوننت ما هست. بنابراین، اجازه دهید با ایجاد فایل src/component/site/View/Project/HtmlView.php با تعریف نام و کلاس شروع کنیم:
<?php
namespace Piedpiper\Component\Spm\Site\View\Project;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
use Joomla\CMS\MVC\View\GenericDataException;
class HtmlView extends BaseHtmlView
{
public $item;
}
ین فایل مانند فایلی هست که ما برای لیست پروژه های بخش قبل ایجاد کردیم. در اینجا می توانیم نکاتی را بیان کنیم. همانطور که ما در حال توسعه بخش frontend پروژه هستیم، فضای نام ما اکنون به پوشه Site اشاره می کند که در نمای فرانت اند Projects ایجاد شده است.
ما چند فضای نام را اضافه میکنیم که از در متد display استفاده می کند و باید کد زیر را داشته باشد:
public function display($tpl=null): void
{
$this->item = $this->get('Item');
if (count($errors = $this->get('Errors')))
{
throw new GenericDataException(implode("\n", $errors), 500);
}
parent::display($tpl);
}
در نمای جزئیات، ما نیازی به افزودن فیلتر، صفحه بندی یا هر عنصر دیگری نداریم، بنابراین در متد display ، فقط متد get('Item') را فراخوانی می کنیم تا از مدل داده های مورد خود را درخواست کنیم.
همچنین برای بررسی هر گونه خطا در مدل، از متد get('Errors') استفاده میکنیم. اگر موردی وجود داشته باشد، به ما نشان خواهد داد.
اکنون، باید کلاس مدل را برای نمای جزئیات پروژه خود که آیتم را بازیابی می کند، اضافه کنیم.
افزودن مدل برای نمای آیتم در frontend
برای مدل خود، باید BaseDatabaseModel را از کتابخانه جوملا فراخوانی کنیم، که شامل تمام متد هایی است که در این مورد نیاز داریم. بیایید تعریف کلاس را ایجاد کنیم و فضای نام آن را پر کنیم. ما فایل src/component/site/src/Model/ProjectModel.php را ایجاد خواهیم کرد با مطالب زیر:
<?php
namespace Piedpiper\Component\Spm\Site\Model;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
class ProjectModel extends BaseDatabaseModel
{
protected $_item = null;
}
در مدل های جوملا، ما معمولاً با تنظیم وضعیت سیستم شروع می کنیم، بنابراین باید متد populateState را به کلاس خود اضافه کنیم:
protected function populateState()
{
$app = Factory::getApplication();
$params = $app->getParams();
$id = $app->input->getInt('id');
$this->setState('project.id', $id);
$this->setState('project.params', $params);
}
متد populateState یک بار در ساخت مدل اجرا می شود و شناسه پروژه را از URL استخراج کرده و به وضعیت فعلی اضافه می کند.
پس از پر کردن حالت، می توانیم آیتم را برای نمایش در نمای جزئیات بازیابی کنیم، بنابراین متد getItem را با استفاده از این کد اضافه می کنیم:
function getItem($pk = null)
{
$id = (int) $pk ?: (int) $this->getState('project.id');
if (!$id) {
throw new \Exception('Missing project id', 404);
}
if ($this->_item !== null && $this->_item->id != $id) {
return $this->_item;
}
$db = $this->getDatabase();
$query = $db->getQuery(true);
$query->select('*')
->from($db->quoteName('#__spm_projects', 'a'))
->where($db->quoteName('a.id') . ' = ' . (int)
$id);
$db->setQuery($query);
$item = $db->loadObject();
if (!empty($item)) {
$this->_item = $item;
}
return $this->_item;
}
در این متد آرگومان اختیاری $pk را ارسال می کنیم. این متغیر $pk به ID پروژه ای که ما میخواهیم نشان دهیم، اشاره می کند. اگر متد را بدون آرگومان ها فراخوانی کنیم، سعی می کند مقدار را از حالت دریافت کند. همانطور که قبلاً متد populateState خود را اضافه کرده بودیم ، این حالت قبلاً شامل ID پروژه است و می توانیم از متد getState برای بازیابی آن استفاده کنیم.
اگر هیچ شناسه ای در URL ما وجود نداشته باشد یا شناسه 0 باشد، چیزی وجود ندارد که بتوانیم بازیابی کنیم و خطا خواهیم داشت. با این کار چرخه اجرای فعلی را قطع می کند و جوملا یک صفحه ی خطا، شبیه به صفحه زیر را نشان می دهد:
شکل 3.4 - یک صفحه خطا ایجاد شده از پروژه یافت نشد
هنگام فراخوانی کلاس Extension، یک پیام و یک کد استثنا اضافه می کنیم. جوملا پیام را به کاربر نشان می دهد و کد استثنا را به پاسخ HTTP اضافه می کند و در نتیجه این صفحه خطا نشان داده می شود.
هنگامی که بررسی کردیم که شناسه پروژه داریم، بلوک کد بعدی تشخیص می دهد که آیا قبلاً مورد این شناسه را برای ذخیره کوئری در پایگاه داده بازیابی کرده ایم یا خیر.
اگر ما این مورد را در وضعیت فعلی، درخواست نکرده ایم، باید داده ها را از پایگاه داده خود بازیابی کنیم. بنابراین، ما Object DB جوملا را فراخوانی می کنیم تا پایگاه داده خود را کوئری کرده و داده ها را بازیابی کند.
در این کد، ممکن است متوجه شده باشید که ما متغیر ID را به نوع int ارسال می کنیم. این یک اقدام امنیتی است، زیرا ما در حال بازیابی شناسه از یک درخواست عمومی (URL اضافه شده توسط کاربر) هستیم و ممکن است دارای کد مخرب باشد. این اقدام احتیاطی ساده قطعات شما را بسیار ایمن تر نگه می دارد.
در نهایت، ما آبجکت مورد را مستقیماً به view بر می گردانیم و اکنون آماده هستیم تا یک چیدمان زیبا برای نمایش داده های خود ایجاد کنیم.
اضافه کردن چیدمان برای جزئیات پروژه
اکنون که همه چیزهایی را که برای نشان دادن پروژه به کاربران خود نیاز داریم در اختیار داریم، یک چیدمان زیبا اضافه می کنیم. بنابراین، فایل src/component/site/tmpl/project/default.php را با محتوای زیر ایجاد کنید:
<?php
defined('_JEXEC');
?>
<div class="project-item p-4">
<h1><?php echo $this->item->name; ?></h1>
<div id="created" class="date meta">
<?php echo $this->item->created;?>
</div>
<p id="description" class="description">
<?php echo $this->item->description; ?>
</p>
<div id="deadline" class="date">
<?php echo $this->item->deadline; ?>
</div>
</div>
این کد هر عنصر پروژه را در یک تگ HTML مناسب نشان می دهد.
اگر حالا، آخرین تغییرات را در سایت جوملا خود نصب کنید، متوجه خواهید شد که هیچ راهی برای دسترسی به نمای جزئیات پروژه وجود ندارد. تنها راه در حال حاضر استفاده از URL مستقیم است. به عنوان مثال:
اگر از index.php?option=com_spm&view=project&id=1 استفاده کنید، به نمای جزئیات اولین پروژه خود خواهید رفت.
برای اجازه دادن به ناوبری مناسب، می خواهیم پروژه ها را در نمای پروژه ها با نمای جزئیات پروژه مرتبط کنیم. بنابراین، محتوای فایل src/component/site/projects/default.php را با کد زیر جایگزین کنید:
<?php
use Joomla\CMS\Router\Route;
?>
<a href="/<?php echo Route::_('index.php?option=com_spm&view=project&id=' . $item->id);?>">
<?php echo $item->name; ?></a>
در این کد، ما اکنون یک لینک به نمای جزئیات پروژه اضافه کنید. ما از متدRoute استفاده خواهیم کرد، زیرا به ما در ایجاد یک URL دوستانه در بخش های زیر کمک می کند.
پس از آماده شدن، می توانید پوشه کامپوننت خود را فشرده کرده و از طریق مدیریت افزونه جوملا نصب کنید و تغییرات را مشاهده نمایید.
ما با افزودن لینک به نمای جزئیات پروژه، قابلیت استفاده کامپوننت خود را بسیار بهبود بخشیده ایم، اما هنوز باید یک راه ساده برای بررسی لیست پروژه هایمان ارائه دهیم. در قسمت بعدی یک آیتم منو برای نمای لیست در کامپوننت ایجاد خواهیم کرد تا برنامه مفیدتر شود.
افزودن یک آیتم منو برای نظرات ما
در جوملا، ما ساختار سایت خود را با استفاده از منوها ایجاد می کنیم. ما چندین آیتم منو که به نماهای اجزای ما لینک شده اند، اضافه می کنیم. هنگامی که یک آیتم منو ایجاد می کنیم، پیوند مناسبی (به نمای خود در نوار ناوبری سایت) درست کرده ایم. ایجاد یک آیتم منو برای کامپوننت ما، همچنین به ما این امکان را می دهد که به جای استفاده از آدرس زشت index.php?option=com_spm&view=projects ، یک URL خوب و دوستانه برای نمای خود داشته باشیم. این برای کاربران ما بسیار راحت است، بنابراین بیایید شروع به ثبت موارد منوی خود کنیم.
ابتدا باید یک نوع آیتم منو برای کامپوننت خود ثبت کنیم.
ما می توانیم این کار را با افزودن یک فایل XML به پوشه tmpl خود برای مشاهده انجام دهیم.
بنابراین، اجازه دهید شروع به ایجاد فایل src/component/site/tmpl/projects/default.xml کنیم و مطالب زیر را قرار دهیم:
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<layout title="COM_SPM_VIEW_PROJECTS_MENU_LABEL">
<message>
<![CDATA[COM_SPM_VIEW_PROJECTS_MENU_DESC]]>
</message>
</layout>
</metadata>
در این کد XML، عنوانی را که می خواهیم برای آیتم منو در ویژگی title برای تگ <layout> نشان دهیم، تعریف می کنیم. همچنین توضیحاتی را که مدیران سایت هنگام ایجاد آیتم منو مشاهده خواهند کرد، با استفاده از تگ <message> تعریف خواهیم کرد. ما از متن توصیفی برای ویژگی عنوان و همچنین تگ <message> استفاده نمی کنیم، در عوض، از یک برچسب توصیفی استفاده خواهیم کرد. در فصل 5، استفاده از قدرت جوملا در کامپوننت شما، فایل های زبانی را که برای تبدیل این برچسب ها به متن انگلیسی (یا هر زبانی که نیاز داریم)، اضافه می کنیم.
در تصویر زیر نتیجه افزودن این فایل XML را مشاهده می کنید:
شکل 3.5 - جزئیات انتخاب نوع آیتم منو برای کامپوننت ما
در این تصویر، ما می ببینیم چگونه یک عنصر برای کامپوننت COM_SPM ما وجود دارد ، با یک عنصر فرزند که نوع آیتم منو را که ما ایجاد کردیم را نشان می دهد. در عنصر فرزند، ما می توانیم عنوان و توضیحات را ببینیم.
این برای لیست پروژه های ما عالی عمل می کند، اما چگونه می توانیم پروژه های خاصی را در منوی خود پیوند دهیم؟ خوب، ما باید یک نوع آیتم منو را برای نمای جزئیات پروژه خود ثبت کنیم و این دقیقاً همان چیزی است که در بخش بعدی خواهیم دید.
افزودن گزینه ها به آیتم های منو
ثبت منو آیتم برای نمای جزئیات (detail) پروژه دقیقاً همان فرآیندی است که برای نمای لیست انجام می شود. با این وجود، در نمای جزئیات، باید راهی برای مدیر سایت اضافه کنیم تا تعریف کند کدام پروژه را از لیست پروژه های ما نشان دهد.
بیایید ببینیم چگونه می توانیم گزینه هایی را به آیتم های منو اضافه کنیم. فایل src/component/site/tmpl/project/default.xml را ایجاد کرده و آن را با تعریف XML زیر پر کنید :
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<layout title="COM_SPM_VIEW_PROJECT_MENU_LABEL">
<message>
<![CDATA[COM_SPM_VIEW_PROJECT_MENU_DESC]]>
</message>
</layout>
<fields name="request">
<fieldset name="options">
<field
name="id"
type="text"
label="COM_SPM_FIELD_ID_LABEL"
required="true" />
</fieldset>
</fields>
</metadata>
این تعریف آیتم منو مانند قبلی است، اما XML دارای بخشfield جدید است. در داخل این بخش، ما یک بخشfieldset اضافه می کنیم ، با تعداد موارد اختیاری که می خواهیم ارائه دهیم.
برای بخشfield ، از ویژگی name="request" استفاده می کنیم تا به جوملا بگوییم که باید این مقدار را به درخواست صفحه ارسال کند. به این ترتیب، ما نیازی به تغییر مدل خود نداریم.
ه باید این مقدار را به درخواست صفحه ارسال کند. به این ترتیب، ما نیازی به تغییر مدل خود نداریم.
طبق معمول، در تعاریف XML، می توانیم یک پارامتر نام که نمایانگر فیلد است، اضافه کنیم و برای قسمت fieldset ، از name="options" استفاده می کنیم. این به یک تب جدید در پیکربندی آیتم های منو ترجمه می شود، که در آن تمام فیلدهای موجود در این بخش قرار خواهند داشت.
اگر نام دیگری انتخاب کنید، جوملا نام برگه را با ساختار COM_MENUS_YOURNAME_FIELDSET_LABEL جایگزین می کند. (ما به ترجمه ها و فایل های زبان در فصل 5، استفاده از قدرت جوملا در کامپوننت خود نگاه خواهیم کرد.)
اکنون برای ساده تر کردن کارها، از یک نوع فیلد متنی استفاده می کنیم که در تصویر زیر نشان داده شده است:
شکل 3.6 - جزئیات تب گزینه های جدید با فیلد متنی که شامل پروژه ما می شود
این فیلد به ما امکان می دهد شناسه پروژه های خود را تایپ کرده و پروژه ای را که می خواهیم نشان دهیم را انتخاب کنیم.
اکنون می توانیم داشته باشیمURL های مختلف برای پروژه های ما در منو. همچنین، هر آیتم منو در جوملا دارای یک URL دوستانه مرتبط است.
با این حال، ایجاد یک آیتم منو برای هر پروژه در کامپوننت ما عملی نیست، بنابراین ما به راهی نیاز داریم که URL های دوستانه را برای موارد خود مجاز کنیم. در بخش بعدی، ما شروع به اضافه کردن خدمات جوملا به کامپوننت خود برای این کار خواهیم کرد.
اضافه کردن URL های دوستانه به کامپوننت ما
URL های دوستانه در توسعه وب یک مشکل دو طرفه است. از یک طرف، هنگام نشان دادن URL به کاربران خود، باید تمام پیوندهای زشت خود را با پارامترهای با معنی جایگزین کنید تا آنها را دوستانه تر شوند. این کلمات معمولاً با نام صفحه ای که نشان می دهیم مطابقت دارند و ما آنها را مستعار (slugs or aliases) می نامیم.
برای مثال، در لینک https://YourDomain.com/joomla-4-extension-development ، نام مستعار قسمت برجسته شده است.
مشکل دوم زمانی شروع می شود که کاربران شما یک URL دوستانه درخواست می کنند و شما باید آن را به پارامترهایی برای جوملا خود ترجمه کنید تا سایت این درخواست را درک کند.
برای رسیدگی به این مشکلات در جوملا، باید یک به اصطلاح router به کامپوننت اضافه کنیم. در جوملا router را به بخش service سرویس اضافه می کنیم.
برای انجام این کار، فایل src/component/admin/services/provider.php را ویرایش کنید و فضای نام زیر را اضافه کنید:
use Joomla\CMS\Extension\Service\Provider\RouterFactory;
use Joomla\CMS\Component\Router\RouterFactoryInterface;
پس از افزودن این موارد جدید فضاهای نام، ما می توانیم کلاس RouterFactory را ثبت کنیم ، بنابراین همانطور که در کد مشخص شده، آن را به متد register اضافه می کنیم :
return new class implements ServiceProviderInterface
{
public function register(Container $container)
{
…
$container->registerServiceProvider(newRouterFactory('\\Piedpiper\\Component\\Spm'));
…
);
}
};
در نهایت، طبق کد مشخص شده، کلاس RouterFactory را در تابع ناشناس container اضافه می کنیم :
$container->set(
ComponentInterface::class,
function (Container $container)
{
…
$component->setRouterFactory($container->
get(RouterFactoryInterface::class));
…
}
);
};
با این خطوط جدید، ما سرویس router را برای کامپوننت خود ثبت کرده ایم و اکنون می توانیم کد گذاری Service را شروع کنیم.
router کامپوننت ما در قسمت frontend سایت ما کار می کند، بنابراین ما پوشه src/component/site/src/Service را ایجاد کرده و فایلی به نام Router.php را در آن قرار می دهیم.
ما شروع به اضافه کردن فضاهای نام و تعریف کلاس میکنیم:
src/component/site/src/Service/Router.php
<?php
namespace Piedpiper\Component\Spm\Site\Service;
use Joomla\CMS\Application\SiteApplication;
use Joomla\CMS\Component\Router\RouterView;
use Joomla\CMS\Component\Router\RouterViewConfiguration;
use Joomla\CMS\Component\Router\Rules\MenuRules;
use Joomla\CMS\Component\Router\Rules\NomenuRules;
use Joomla\CMS\Component\Router\Rules\StandardRules;
use Joomla\Database\DatabaseInterface;
use Joomla\CMS\Menu\AbstractMenu;
class Router extends RouterView
{
private $db;
}
این کلاس router ما است و این کد جایی است که به جوملا می گوییم چگونه نام های مستعار را به پارامتر ها ترجمه کند و بالعکس.
در سازنده (constructor) ، ما باید تعیین کنیم که کدام نماهای کامپوننت ما به URL SEF نیاز دارد و همچنین قوانینی را برای پیروی از هر URL در کامپوننت خود تنظیم خواهیم کرد.
برای این کلاس، سازنده ای راه اندازی می کنیم که پیکربندی مسیریابی ما را تنظیم می کند. این کدی است که باید اضافه کنیم:
public function __construct(SiteApplication $app, Abstract
Menu $menu, $category, DatabaseInterface $db)
{
$this->db = $db;
$projects = new RouterViewConfiguration('projects');
$this->registerView($projects);
}
برای سهولت کار، ویژگی $db را با object پایگاه داده فعلی خود ثبت می کنیم. این object به object construction منتقل می شود.
پس از آن، باید نماها را در کامپوننت خود ثبت کنیم. ما از کلاس RouterViewConfiguration از کتابخانه های جوملا استفاده خواهیم کرد. ما باید یک آبجکت RouterViewConfiguration برای هر نمای قابل مسیریابی در کامپوننت خود ایجاد کنیم و از نام view به عنوان پارامتر سازنده استفاده می کنیم.
اولین object ای که ایجاد خواهیم کرد برای نمای project است. پس از ایجاد، ما آبجکت را با استفاده از متد registerView از کلاس اصلی که توسعه می دهیم، ثبت می کنیم.
نمای projects یک نمای فهرست است، به این معنی که شامل موارد دیگری است که احتمالاً در سلسله مراتب URL پایین تر قرار دارند.
سپس، می توانیم نمای پروژه های جداگانه، نمای project را ثبت کنیم. این نما به پروژه ها بستگی دارد و ما آن را در پیکربندی SEF منعکس خواهیم کرد. بنابراین، بلافاصله پس از ثبت نمای projects ، این کد را اضافه می کنیم :
$project = new RouterViewConfiguration('project');
$project->setKey('id')->setParent($projects);
$this→registerView($project);
در این کد، مانند نمای $projects ، از کلاس RouterViewConfiguration استفاده می کنیم، اما با چند مورد اضافه. از آنجایی که هر پروژه در پایگاه داده ما منحصر به فرد است، URL های امن ما باید برای هر یک از آنها متفاوت باشد. بنابراین، برای نمای project detail ، باید کلیدی برای تمایز بین پروژه ها تنظیم کنیم. این کلید شناسه هر پروژه خواهد بود. این شناسه، هر پروژه را متمایز می کند، بنابراین برای هر URL منحصر به فرد است.
در همین خط، سلسله مراتب را تعریف کنید. نمای project detail مادر است بعد از نمای کلی پروژه ها می آید، بنابراین ما آبجکت $projects را به عنوان والد آن تعریف می کنیم. برای این کار از متد setParent استفاده می کنیم.
هنگامی که نماهای خود را تعریف کردیم، می توانیم متد والد __construct را فراخوانی کنیم که برخی از متغیرهای مورد نیاز در فرآیند مسیریابی را مقداردهی اولیه می کند، و برخی از قوانین پیش فرض را برای مدیریت سناریوهای رایج اضافه می کنیم. بنابراین، کد زیر را اضافه می کنیم :
parent::__construct($app, $menu);
$this->attachRule(new MenuRules($this));
$this->attachRule(new StandardRules($this));
$this->attachRule(new NomenuRules($this));
در سه بیانیه پایانی، ما قوانین اضافی را ضمیمه خواهیم کرد که از قسمت مسیریابی که مستقیماً با افزونه ما مرتبط نیست، مراقبت می کند :
-
کلاس MenuRules از کد زبان URL SEF مراقبت می کند و سلسله مراتب منو را به URL اضافه می کند.
-
کلاس StandardRules اطمینان حاصل می کند که کامپوننت به مسیریابی URL عمومی جوملا احترام می گذارد
-
کلاس NomenuRules به شما این امکان را می دهد که URL های SEF را برای مؤلفه خود در زمانی که به هیچ آیتم منو متصل نیست، ایجاد کنید.
ترجمه پارامترها به یک URL دوستانه
پس از راه اندازی router ما در متد construct ، باید به جوملا آموزش دهیم که چگونه URL های زشت خود را به آدرس های دوستانه ترجمه کند. برای این کار متد ()getViewNameSegment را تعریف می کنیم. هر یک از این روش ها نشان دهنده راهی است که جوملا یک URL مستعار یا دوستانه برای آن view دریافت می کند.
برای نمای پروژه ی ما، می توانید کد زیر را به کلاس router خود اضافه کنید:
src/component/site/src/Service/Router.php
public function getProjectSegment($key, $urlQuery)
{
$id = (int) $id;
$query = $this->db->getQuery(true);
$query->select($this->db->quoteName('alias'))
->from($this->db->quoteName('#__spm_projects'))
->where($this->db->quoteName('id') . ' = ' .
(int) $key);
$this->db->setQuery($query);
$id = $this->db->loadResult();
return [$id];
}
این متد $key ، مقداری را که در پیکربندی view تنظیم کرده ایم، دریافت می کند، بنابراین در مورد ما، شناسه پروژه و پارامترهای ارسال شده به URL را خواهد داشت.
برای پروژه های خود، ما فقط به شناسه نیاز داریم، بنابراین از آن برای دریافت نام مستعار از پایگاه داده استفاده می کنیم.
این ترجمه، یک شناسه را به یک کلمه ی انسان پسند تغییر می دهد. بیایید در بخش بعدی ببینیم که چگونه می توان به جوملا دستور داد که این نام مستعار را به یک شناسه برای بازیابی پروژه مناسب تبدیل کند.
ترجمه URL های SEF به متغیرهایی برای کامپوننت ما
هنگامی که یک URL SEF وارد می شودrouter ما، باید آن را به متغیرهایی که پروژه ما را تعریف می کنند ترجمه کنیم و کاربر را به نمای صحیح هدایت کنیم.
برای انجام این کار، متد getProjectId را به کد router خود اضافه می کنیم:
src/component/site/src/Service/Router.php
public function getProjectId($segment, $urlQuery)
{
$query = $this->db->getQuery(true);
$query->select($this->db->quoteName('id'))
->from($this->db->quoteName'#__spm_projects'))
->where($this->db->quoteName('alias') . ' = :
alias')
->bind(':alias', $segment);
$this->db->setQuery($query);
return (int) $this->db->loadResult();
}
}
این متد بخش یا نام مستعار و همچنین پارامترهایی را که جوملا قبلاً از قوانین SEF دیگر مانند ItemId و موارد مشابه کشف کرده است، از جوملا دریافت می کند. در این روش از نام مستعار برای بازیابی کلید منحصر به فرد پروژه خود (شناسه منحصر به فرد) از پایگاه داده استفاده می کنیم. نام مستعار در آرگومان $segment ارسال می شود و سایر پارامتر ها در آرایه $urlQuery قرار دارند.
اگر به کوئری پایگاه داده ای که انجام می دهیم دقت کنید، متوجه خواهید شد که از متد bind() برای اضافه کردن نام مستعار به کوئری استفاده می کنیم. ما از این روش برای ایجاد دستورات آماده MySQL در جوملا استفاده می کنیم. در جوملا، ما باید در صورت امکان از عبارات آماده شده استفاده کنیم، زیرا آنها محافظت بسیار خوبی در برابر حملات به MySQL می کنند. عبارات آماده شده برای پرس و جو های تکراری کارایی بیشتری دارند، زیرا عبارات در پایگاه داده ذخیره می شوند، که فقط متغیرهای هر پرس و جو مربوطه را جایگزین می کند. در جوملا از نام متغیری مانند : alias در پرس و جو استفاده می کنیم و متغیر را با مقدار آن با استفاده از متد ()bind متصل می کنیم.
این چرخه مسیریابی را تکمیل می کند و اجازه می دهد کامپوننت ما URL های زشت خود را به URL های زیبا و امن ترجمه کند و بالعکس.
اکنون می توانیم بخش frontend یک کامپوننت جوملا را توسعه دهیم که مهمترین بخش های توسعه را پوشش می دهد.
منابع فصل
-
صفحه بندی آبجکت، روش های جالبی را ارائه می دهد که می توانید از آنها برای سفارشی کردن تجربه ی صفحه بندی استفاده کنید. می توانید جزئیات بیشتر درباره آبجکت صفحه بندی را در صفحه اسناد API آن بیابید:
-
می توانید با Bootstrap در صفحه آن آشنا شوید:
-
در W3Schools، یک مقاله خوب در مورد عبارات آماده شده MySQL وجود دارد:
-
یک صفحه مستند سازی خوب برای مدیریت دارایی وب در جوملا وجود دارد: