home / skills / masanao-ohba / claude-manifests / code-implementer
This skill implements production-ready CakePHP code from functional designs across controllers, models, components, and services to accelerate delivery.
npx playbooks add skill masanao-ohba/claude-manifests --skill code-implementerReview the files below or copy the command above to add this skill to your agents.
---
name: code-implementer
description: Implements production code for PHP/CakePHP applications based on functional design specifications
hooks:
SessionStart:
- type: command
command: |
if command -v yq &> /dev/null && [ -f ".claude/config.yaml" ]; then
echo "=== Architecture Constraints ==="
yq -o=json '.constraints.architecture' .claude/config.yaml 2>/dev/null || true
echo "=== Coding Standards ==="
yq -o=json '.coding_standards' .claude/config.yaml 2>/dev/null || true
fi
---
# Code Implementer
A specialized skill for translating functional designs and specifications into production-ready PHP/CakePHP code.
## Core Responsibilities
### 1. Implementation Standards
**CakePHP Conventions:**
```php
// Controller naming
class UsersController extends AppController
// Model naming
class UsersTable extends Table
class User extends Entity
// Component naming
class AuthorizationComponent extends Component
// View template naming
// templates/User/Users/index.php
// templates/User/Users/view.php
```
### 2. Controller Implementation
**Standard Controller Pattern:**
```php
<?php
declare(strict_types=1);
namespace App\Controller\User;
use App\Controller\AppController;
use Cake\Event\EventInterface;
use Cake\Http\Response;
/**
* Users Controller
*
* @property \App\Model\Table\UsersTable $Users
* @property \App\Controller\Component\MessageDeliveryDbAccessorComponent $MessageDeliveryDbAccessor
*/
class UsersController extends AppController
{
/**
* Initialize method
*/
public function initialize(): void
{
parent::initialize();
$this->loadComponent('MessageDeliveryDbAccessor');
}
/**
* Index method - List users
*
* @return \Cake\Http\Response|null|void
*/
public function index()
{
// Get company-specific connection
$companyId = $this->Auth->user('eco_company_id');
$conn = $this->MessageDeliveryDbAccessor
->getUserMessageDeliveryDbConnection($companyId);
$this->Users->setConnection($conn);
// Paginate with conditions
$query = $this->Users->find()
->where(['del_flg' => Configure::read('Common.del_flg.off')])
->order(['created' => 'DESC']);
$users = $this->paginate($query);
$this->set(compact('users'));
}
}
```
### 3. Model Implementation
**Table Class Pattern:**
```php
<?php
declare(strict_types=1);
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use Cake\ORM\RulesChecker;
use Cake\ORM\Query;
/**
* Users Model
*
* @property \App\Model\Table\CompanysTable&\Cake\ORM\Association\BelongsTo $Companys
* @property \App\Model\Table\OrdersTable&\Cake\ORM\Association\HasMany $Orders
*/
class UsersTable extends Table
{
/**
* Initialize method
*
* @param array $config Configuration
* @return void
*/
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('users');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
// Associations
$this->belongsTo('Companys', [
'foreignKey' => 'company_id',
'joinType' => 'INNER',
]);
$this->hasMany('Orders', [
'foreignKey' => 'user_id',
'dependent' => true,
]);
}
/**
* Default validation rules
*
* @param \Cake\Validation\Validator $validator
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator): Validator
{
$validator
->integer('id')
->allowEmptyString('id', null, 'create');
$validator
->email('email')
->requirePresence('email', 'create')
->notEmptyString('email')
->add('email', 'unique', [
'rule' => 'validateUnique',
'provider' => 'table',
'message' => __('このメールアドレスは既に登録されています'),
]);
$validator
->scalar('name')
->maxLength('name', 255)
->requirePresence('name', 'create')
->notEmptyString('name');
return $validator;
}
/**
* Build rules
*
* @param \Cake\ORM\RulesChecker $rules
* @return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules): RulesChecker
{
$rules->add($rules->isUnique(['email']));
$rules->add($rules->existsIn(['company_id'], 'Companys'));
return $rules;
}
/**
* Custom finder for active users
*
* @param \Cake\ORM\Query $query
* @param array $options
* @return \Cake\ORM\Query
*/
public function findActive(Query $query, array $options): Query
{
return $query->where([
'status' => Configure::read('User.status.active'),
'del_flg' => Configure::read('Common.del_flg.off'),
]);
}
}
```
**Entity Class Pattern:**
```php
<?php
declare(strict_types=1);
namespace App\Model\Entity;
use Cake\ORM\Entity;
use Cake\Auth\DefaultPasswordHasher;
/**
* User Entity
*
* @property int $id
* @property string $email
* @property string $password
* @property string $name
* @property int $company_id
* @property int $status
* @property \Cake\I18n\FrozenTime $created
* @property \Cake\I18n\FrozenTime $modified
*
* @property \App\Model\Entity\Company $company
* @property \App\Model\Entity\Order[] $orders
*/
class User extends Entity
{
/**
* Accessible fields
*
* @var array
*/
protected $_accessible = [
'email' => true,
'password' => true,
'name' => true,
'company_id' => true,
'status' => true,
'created' => true,
'modified' => true,
'company' => true,
'orders' => true,
];
/**
* Hidden fields
*
* @var array
*/
protected $_hidden = [
'password',
];
/**
* Password setter with hashing
*
* @param string $password
* @return string|null
*/
protected function _setPassword(string $password): ?string
{
if (strlen($password) > 0) {
return (new DefaultPasswordHasher())->hash($password);
}
return null;
}
}
```
### 4. Component Implementation
**Custom Component Pattern:**
```php
<?php
declare(strict_types=1);
namespace App\Controller\Component;
use Cake\Controller\Component;
use Cake\Core\Configure;
use Cake\Datasource\ConnectionManager;
/**
* MessageDeliveryDbAccessor component
*/
class MessageDeliveryDbAccessorComponent extends Component
{
/**
* Get company-specific database connection
*
* @param int $companyId
* @return \Cake\Database\Connection
*/
public function getUserMessageDeliveryDbConnection(int $companyId)
{
$connectionName = sprintf('Connection_[app_prefix]_company_%d', $companyId);
if (!ConnectionManager::getConfig($connectionName)) {
$config = ConnectionManager::getConfig('default');
$config['database'] = sprintf('[app_prefix]_company_%d', $companyId);
ConnectionManager::setConfig($connectionName, $config);
}
return ConnectionManager::get($connectionName);
}
}
```
### 5. View Implementation
**Template Pattern:**
```php
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\User[]|\Cake\Collection\CollectionInterface $users
*/
?>
<div class="users index">
<h2><?= __('ユーザー一覧') ?></h2>
<div class="table-responsive">
<table>
<thead>
<tr>
<th><?= $this->Paginator->sort('id', 'ID') ?></th>
<th><?= $this->Paginator->sort('name', '名前') ?></th>
<th><?= $this->Paginator->sort('email', 'メール') ?></th>
<th><?= $this->Paginator->sort('created', '作成日') ?></th>
<th class="actions"><?= __('操作') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td><?= $this->Number->format($user->id) ?></td>
<td><?= h($user->name) ?></td>
<td><?= h($user->email) ?></td>
<td><?= h($user->created->format('Y/m/d H:i')) ?></td>
<td class="actions">
<?= $this->Html->link(__('表示'), ['action' => 'view', $user->id]) ?>
<?= $this->Html->link(__('編集'), ['action' => 'edit', $user->id]) ?>
<?= $this->Form->postLink(
__('削除'),
['action' => 'delete', $user->id],
['confirm' => __('本当に削除しますか?')]
) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="paginator">
<?= $this->Paginator->counter(__('全 {{count}} 件中 {{current}} 件を表示')) ?>
<?= $this->Paginator->first('<<') ?>
<?= $this->Paginator->prev('<') ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next('>') ?>
<?= $this->Paginator->last('>>') ?>
</div>
</div>
```
### 6. Service Layer Implementation
**Business Logic Service:**
```php
<?php
declare(strict_types=1);
namespace App\Service;
use Cake\ORM\TableRegistry;
use Cake\Core\Configure;
use Cake\Log\Log;
/**
* Order Processing Service
*/
class OrderService
{
/**
* Process order
*
* @param array $orderData
* @return array Result with status and message
*/
public function processOrder(array $orderData): array
{
$Orders = TableRegistry::getTableLocator()->get('Orders');
$connection = $Orders->getConnection();
try {
$connection->begin();
// 1. Validate input
if (!$this->validateOrderData($orderData)) {
throw new \InvalidArgumentException('Invalid order data');
}
// 2. Calculate totals
$total = $this->calculateTotal($orderData['items']);
$orderData['total'] = $total;
// 3. Check inventory
if (!$this->checkInventory($orderData['items'])) {
throw new \Exception('Insufficient inventory');
}
// 4. Create order
$order = $Orders->newEntity($orderData);
if (!$Orders->save($order)) {
throw new \Exception('Failed to save order');
}
// 5. Update inventory
$this->updateInventory($orderData['items']);
// 6. Send notifications
$this->sendOrderNotification($order);
$connection->commit();
return [
'status' => 'success',
'order_id' => $order->id,
'message' => '注文が完了しました',
];
} catch (\Exception $e) {
$connection->rollback();
Log::error('Order processing failed: ' . $e->getMessage());
return [
'status' => 'error',
'message' => $e->getMessage(),
];
}
}
/**
* Calculate order total
*/
private function calculateTotal(array $items): float
{
$total = 0.0;
foreach ($items as $item) {
$total += $item['price'] * $item['quantity'];
}
return $total;
}
/**
* Check inventory availability
*/
private function checkInventory(array $items): bool
{
$Products = TableRegistry::getTableLocator()->get('Products');
foreach ($items as $item) {
$product = $Products->get($item['product_id']);
if ($product->stock < $item['quantity']) {
return false;
}
}
return true;
}
/**
* Update inventory after order
*/
private function updateInventory(array $items): void
{
$Products = TableRegistry::getTableLocator()->get('Products');
foreach ($items as $item) {
$product = $Products->get($item['product_id']);
$product->stock -= $item['quantity'];
$Products->save($product);
}
}
/**
* Send order notification
*/
private function sendOrderNotification($order): void
{
// Email notification logic
}
/**
* Validate order data
*/
private function validateOrderData(array $data): bool
{
return isset($data['user_id']) &&
isset($data['items']) &&
!empty($data['items']);
}
}
```
### 7. AJAX Handler Implementation
**AJAX Response Pattern:**
```php
/**
* AJAX endpoint for data retrieval
*
* @return \Cake\Http\Response JSON response
*/
public function ajaxGetData()
{
$this->request->allowMethod(['post', 'ajax']);
$this->viewBuilder()->setOption('serialize', true);
try {
$data = $this->request->getData();
// Validate request
if (empty($data['id'])) {
throw new \InvalidArgumentException('ID is required');
}
// Get data
$result = $this->Model->find()
->where(['id' => $data['id']])
->first();
if (!$result) {
throw new \NotFoundException('Data not found');
}
$response = [
'status' => 'success',
'data' => $result->toArray(),
];
} catch (\Exception $e) {
$response = [
'status' => 'error',
'message' => $e->getMessage(),
];
}
return $this->response
->withType('application/json')
->withStringBody(json_encode($response));
}
```
### 8. Multi-Tenant Implementation
**Company-Specific Data Access:**
```php
/**
* Get company-specific data
*/
public function getCompanyData()
{
// Get company ID from session
$companyId = $this->Auth->user('eco_company_id');
// Get company-specific connection
$conn = $this->MessageDeliveryDbAccessor
->getUserMessageDeliveryDbConnection($companyId);
// Switch connection for model
$this->Model->setConnection($conn);
// Query with company context
$data = $this->Model->find()
->where(['company_id' => $companyId])
->all();
return $data;
}
```
## Implementation Patterns
### 1. Error Handling
```php
try {
// Operation
$result = $this->performOperation();
if (!$result) {
throw new \RuntimeException('Operation failed');
}
} catch (\Exception $e) {
Log::error('Operation error: ' . $e->getMessage());
$this->Flash->error(__('エラーが発生しました'));
return $this->redirect(['action' => 'index']);
}
```
### 2. Transaction Management
```php
$connection = $this->Model->getConnection();
try {
$connection->begin();
// Multiple operations
$this->Model1->save($entity1);
$this->Model2->save($entity2);
$connection->commit();
} catch (\Exception $e) {
$connection->rollback();
throw $e;
}
```
### 3. Pagination with Search
```php
public function index()
{
$query = $this->Model->find();
// Search conditions
$search = $this->request->getQuery('search');
if (!empty($search)) {
$query->where([
'OR' => [
'name LIKE' => '%' . $search . '%',
'email LIKE' => '%' . $search . '%',
]
]);
}
$data = $this->paginate($query, [
'limit' => 20,
'order' => ['created' => 'DESC'],
]);
$this->set(compact('data', 'search'));
}
```
### 4. Authentication Check
```php
public function beforeFilter(EventInterface $event)
{
parent::beforeFilter($event);
// Check authentication
if (!$this->Auth->user()) {
return $this->redirect(['controller' => 'Users', 'action' => 'login']);
}
// Check authorization
$userRole = $this->Auth->user('role');
if (!in_array($userRole, ['admin', 'manager'])) {
$this->Flash->error(__('権限がありません'));
return $this->redirect('/');
}
}
```
## Code Quality Standards
### PHP Standards
```php
// Use strict types
declare(strict_types=1);
// Type hints for parameters and returns
public function processData(array $data): bool
// Use null coalescing operator
$value = $data['key'] ?? 'default';
// Use spaceship operator for comparison
return $a <=> $b;
```
### CakePHP Best Practices
1. **Use Configure::read()** for configuration values
2. **Use TableRegistry** for getting table instances
3. **Use ConnectionManager** for database connections
4. **Use Log::write()** for logging
5. **Use Flash messages** for user feedback
6. **Use Form helper** for forms
7. **Use Html helper** for links and assets
### Security Considerations
```php
// SQL Injection Prevention - Use ORM
$users = $this->Users->find()
->where(['email' => $userInput]) // Safe
->all();
// XSS Prevention - Use h() helper
<?= h($userInput) ?> // In views
// CSRF Protection - Use Form helper
<?= $this->Form->create($entity) ?> // Automatic CSRF token
// Password Hashing - Use DefaultPasswordHasher
$hasher = new DefaultPasswordHasher();
$hashed = $hasher->hash($password);
```
## Output Examples
### Example 1: User Registration Implementation
```php
// Controller action
public function register()
{
$user = $this->Users->newEmptyEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success(__('登録が完了しました'));
return $this->redirect(['action' => 'login']);
}
$this->Flash->error(__('登録に失敗しました'));
}
$this->set(compact('user'));
}
```
### Example 2: Order Processing Implementation
```php
// Service method
public function createOrder(array $orderData): Order
{
$connection = $this->Orders->getConnection();
try {
$connection->begin();
// Create order
$order = $this->Orders->newEntity($orderData);
$this->Orders->saveOrFail($order);
// Create order items
foreach ($orderData['items'] as $itemData) {
$item = $this->OrderItems->newEntity($itemData);
$item->order_id = $order->id;
$this->OrderItems->saveOrFail($item);
}
// Update inventory
$this->InventoryService->updateStock($orderData['items']);
// Send notification
$this->NotificationService->sendOrderConfirmation($order);
$connection->commit();
return $order;
} catch (\Exception $e) {
$connection->rollback();
throw new \RuntimeException('Order creation failed: ' . $e->getMessage());
}
}
```
## Best Practices
1. **Follow MVC Pattern**: Keep controllers thin, models fat
2. **Use Services**: Complex business logic in service classes
3. **Type Safety**: Use strict types and type hints
4. **Error Handling**: Proper try-catch blocks
5. **Logging**: Log errors and important events
6. **Comments**: Document complex logic
7. **Testing**: Write testable code
Remember: Good implementation follows design specifications while maintaining code quality and framework conventions.This skill implements production-ready PHP and CakePHP code from functional design specifications. I translate requirements into controllers, models, entities, components, services, views, and AJAX handlers that follow CakePHP conventions and project standards. The output targets maintainability, multi-tenant support, and secure data handling.
I inspect functional designs and map each feature to CakePHP layers: controllers for request flow, Table and Entity classes for data modeling and validation, components for reusable utilities, services for business logic and transactions, and templates for views. I generate code that follows naming conventions, uses behaviors and associations, enforces validation and rules, and includes multi-tenant connection handling and JSON/AJAX response patterns. I also recommend transaction boundaries, error handling, and logging for robust production behavior.
Do you enforce CakePHP naming and folder conventions?
Yes. All generated controllers, tables, entities, components, and templates follow CakePHP conventions and recommended structure.
How is multi-tenant database access handled?
I implement a component that creates or retrieves company-specific ConnectionManager configs and assigns connections to models before queries.