원클릭으로
joomla-conventions
Joomla 4/5 component development with MVC, services, plugins, and language handling
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Joomla 4/5 component development with MVC, services, plugins, and language handling
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
RESTful API design patterns, HTTP standards, versioning, error handling, and documentation
Joomla 3.x legacy patterns with JFactory, non-namespaced MVC, JDatabase, and plugin structure
Laravel best practices for Eloquent, controllers, validation, services, and testing
Performance optimization for PHP, JavaScript, databases, and caching strategies
PHP coding standards including strict typing, OOP patterns, error handling, and documentation
Deep dive into SOLID principles with PHP/TypeScript examples, refactoring patterns, and violation detection
| name | joomla-conventions |
| description | Joomla 4/5 component development with MVC, services, plugins, and language handling |
| license | MIT |
| compatibility | opencode |
| metadata | {"cms":"joomla","version":"4.0+"} |
com_example/
├── administrator/
│ ├── forms/
│ │ └── item.xml
│ ├── services/
│ │ └── provider.php
│ ├── src/
│ │ ├── Controller/
│ │ ├── Extension/
│ │ ├── Field/
│ │ ├── Helper/
│ │ ├── Model/
│ │ ├── Service/
│ │ ├── Table/
│ │ └── View/
│ └── tmpl/
│ └── items/
├── site/
│ ├── src/
│ └── tmpl/
├── media/
│ ├── css/
│ └── js/
└── language/
└── en-GB/
<?php
declare(strict_types=1);
namespace Joomla\Component\Example\Administrator\Extension;
use Joomla\CMS\Extension\ComponentInterface;
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
return new class implements ServiceProviderInterface
{
public function register(Container $container): void
{
$container->registerServiceProvider(new MVCFactory('\\Joomla\\Component\\Example'));
$container->registerServiceProvider(new ComponentDispatcherFactory('\\Joomla\\Component\\Example'));
$container->set(
ComponentInterface::class,
function (Container $container) {
$component = new ExampleComponent($container->get(ComponentDispatcherFactoryInterface::class));
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
return $component;
}
);
}
};
<?php
declare(strict_types=1);
namespace Joomla\Component\Example\Administrator\Model;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\Database\QueryInterface;
class ItemsModel extends ListModel
{
protected function getListQuery(): QueryInterface
{
$db = $this->getDatabase();
$query = $db->getQuery(true);
$query->select($db->quoteName(['a.id', 'a.title', 'a.state']))
->from($db->quoteName('#__example_items', 'a'));
// Filter by state
$state = $this->getState('filter.state');
if (is_numeric($state)) {
$query->where($db->quoteName('a.state') . ' = :state')
->bind(':state', $state, ParameterType::INTEGER);
}
return $query;
}
}
<?php
declare(strict_types=1);
namespace Joomla\Component\Example\Administrator\Table;
use Joomla\CMS\Table\Table;
use Joomla\Database\DatabaseDriver;
class ItemTable extends Table
{
public function __construct(DatabaseDriver $db)
{
parent::__construct('#__example_items', 'id', $db);
}
public function check(): bool
{
if (empty($this->title)) {
$this->setError(Text::_('COM_EXAMPLE_ERROR_TITLE_REQUIRED'));
return false;
}
return true;
}
}
// ALWAYS use parameter binding
$query->where($db->quoteName('id') . ' = :id')
->bind(':id', $id, ParameterType::INTEGER);
// For strings
$query->where($db->quoteName('alias') . ' = :alias')
->bind(':alias', $alias, ParameterType::STRING);
// NEVER do this:
// $query->where('id = ' . $id); // SQL INJECTION!
// In PHP
use Joomla\CMS\Language\Text;
echo Text::_('COM_EXAMPLE_TITLE');
echo Text::sprintf('COM_EXAMPLE_ITEMS_COUNT', $count);
echo Text::plural('COM_EXAMPLE_N_ITEMS_DELETED', $count);
// In templates
<?php echo Text::_('COM_EXAMPLE_SUBMIT'); ?>
Language file (language/en-GB/com_example.ini):
COM_EXAMPLE_TITLE="Example Component"
COM_EXAMPLE_ITEMS_COUNT="Found %d items"
COM_EXAMPLE_N_ITEMS_DELETED="1 item deleted"
COM_EXAMPLE_N_ITEMS_DELETED_1="1 item deleted"
COM_EXAMPLE_N_ITEMS_DELETED_MORE="%d items deleted"
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="details">
<field
name="title"
type="text"
label="COM_EXAMPLE_FIELD_TITLE_LABEL"
required="true"
maxlength="255"
/>
<field
name="state"
type="list"
label="JSTATUS"
default="1"
>
<option value="1">JPUBLISHED</option>
<option value="0">JUNPUBLISHED</option>
</field>
</fieldset>
</form>
<?php
declare(strict_types=1);
namespace Joomla\Plugin\System\Example\Extension;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\SubscriberInterface;
final class Example extends CMSPlugin implements SubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
'onAfterInitialise' => 'onAfterInitialise',
];
}
public function onAfterInitialise(): void
{
// Plugin logic here
}
}
use Joomla\CMS\Factory;
$user = Factory::getApplication()->getIdentity();
if (!$user->authorise('core.edit', 'com_example')) {
throw new \Exception(Text::_('JERROR_ALERTNOAUTHOR'), 403);
}
// In form
<?php echo HTMLHelper::_('form.token'); ?>
// In controller
if (!Session::checkToken()) {
throw new \Exception(Text::_('JINVALID_TOKEN'), 403);
}