state-processor skill
POST, PUT, PATCH ve DELETE gibi yazma işlemlerinde kalıcılık (persistence) ve yan etkileri (side effects) yönetmek için state processor'lar oluşturur.
- GitHub yıldızları
- 29
- Dosyalar
- 1
- Son commit
- 22 Eki 2026
- Lisans
- —
- İzin verilen araçlar
- —
state-processor skill ne işe yarar?
state-processor bir agent skill'dir. POST, PUT, PATCH ve DELETE gibi yazma işlemlerinde kalıcılık (persistence) ve yan etkileri (side effects) yönetmek için state processor'lar oluşturur.
Özet, skill'in SKILL.md dosyasından oluşturuldu.
state-processor skilli hakkında
Bu SKILL, API Platform içerisinde yazma işlemlerini ve yan etkileri yönetmenizi sağlar. Geliştiricilerin, özellikle POST, PUT, PATCH ve DELETE istekleri için CQRS tarzı operasyonların Command tarafını yöneten state processor'lar oluşturmasına olanak tanır. Bir agent; şifre hashleme, ilişkili entity'ler oluşturma veya e-posta bildirimlerini tetikleme gibi özel kalıcılık mantıkları uygulaması gerektiğinde, verilerin yazma aşamasında nasıl işleneceğini tanımlamak için bu SKILL'i kullanabilir.
Developerlar, Doctrine ORM persist processor veya MongoDB ODM remove processor gibi yerleşik servisleri dekore etmek için bu processor'ları kullanabilirler. Bu yaklaşım, standart kalıcılık döngüsünden önce veya sonra mantık eklemeye imkan tanır. SKILL ayrıca, GET işlemlerinde write bayrağını true olarak ayarlayarak soft-delete işlevselliği uygulama veya dosya indirmeleri için Symfony Response nesneleri döndürme gibi gelişmiş kullanım durumlarını da destekler. ProcessorInterface kullanarak Symfony ve Laravel Eloquent dahil olmak üzere farklı framework'lerde çalışır.
Bir agent bununla neler yapabilir
- 1Özel yan etkiler uygulayınBir sipariş başarıyla kaydedildikten hemen sonra e-posta bildirimi göndermek için mantık ekleyin.
- 2Soft-delete mantığını yönetinBir kaynağı veritabanından silmek yerine silindi olarak işaretleyen, yeniden kullanılabilir bir processor oluşturun.
- 3Dosya indirmeleri oluşturunBinary dosya yanıtı döndüren bir processor'ı tetiklemek için bir GET işlemini yapılandırın.
- 4İlişkili entity oluşturmayı otomatize edinYeni bir hesap kaydedildiğinde posta kutuları gibi alt kaynakların otomatik olarak oluşturulmasını sağlayın.
Skill'in SKILL.md dosyasından yazılmıştır. Her kullanım durumu oradaki bir alıntı ile kontrol edilir.
state-processor skill nasıl kurulur
Her komut, skill klasörünü istemcinin skills dizinine kopyalar. Yüklemek için istemciyi yeniden başlatın veya yeni bir oturum başlatın.state-processor skill'ini Eklenti uygulamasına kur
/plugin marketplace add api-platform/skillset /plugin install api-platform@api-platform-skillset
state-processor skill'ini Claude Code uygulamasına kur
~/.claude/skills/state-processor/SKILL.md
$ npx degit api-platform/skillset/skills/state-processor ~/.claude/skills/state-processorstate-processor skill'ini Claude Code (project) uygulamasına kur
.claude/skills/state-processor/SKILL.md
$ npx degit api-platform/skillset/skills/state-processor .claude/skills/state-processorstate-processor skill'ini Codex uygulamasına kur
~/.agents/skills/state-processor/SKILL.md
$ npx degit api-platform/skillset/skills/state-processor ~/.agents/skills/state-processorstate-processor skill'ini Gemini CLI uygulamasına kur
~/.gemini/skills/state-processor/SKILL.md
$ npx degit api-platform/skillset/skills/state-processor ~/.gemini/skills/state-processorstate-processor skill'ini Claude.ai uygulamasına kur
npx degit api-platform/skillset/skills/state-processor state-processor && zip -r state-processor.zip state-processor # claude.ai → Customize → Skills → + → Create skill → Upload a skill → state-processor.zip
SKILL.md
GitHub'da görüntüleCreating State Processors
State Processors handle persistence and side effects for write operations (Post, Patch, Put, Delete) — the write phase of an operation, the Command side of API Platform's CQRS-style split (a state-provider handles the Query/read side).
A processor runs when the operation's write flag is true. You normally leave it
unset and API Platform resolves it from the request: write defaults to "the HTTP
method is not safe", and read (the provider) to "the operation has URI
variables, or the method is safe".
| Operation | processor runs (write) |
provider runs (read) |
|---|---|---|
Get (item) / GetCollection |
no | yes |
Post (collection) |
yes | no (no URI vars, unsafe) |
Put, Patch, Delete (item) |
yes | yes |
A Get defaults to write: false, so its processor never fires until you set
write: true (file downloads, report generation — see Returning HTTP Responses
below). See operations → Read & write phases for the full read → deserialize → validate → write → serialize lifecycle.
Basic Structure
<?php
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
/**
* @implements ProcessorInterface<YourResource, YourResource>
*/
final class YourProcessor implements ProcessorInterface
{
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
{
// Business logic + persistence
return $data;
}
}
Decorating Built-in Processors
Wrap the default processor to add side effects before/after persistence:
use Symfony\Component\DependencyInjection\Attribute\Autowire;
final class OrderCreateProcessor implements ProcessorInterface
{
public function __construct(
#[Autowire(service: 'api_platform.doctrine.orm.state.persist_processor')]
private ProcessorInterface $persistProcessor,
private MailerInterface $mailer,
) {}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
{
// Pre-persistence: set relationships, hash passwords, etc.
$data->setCreatedBy($this->getUser());
$result = $this->persistProcessor->process($data, $operation, $uriVariables, $context);
// Post-persistence: send notifications, trigger events
$this->mailer->send(new OrderConfirmation($result));
return $result;
}
}
Doctrine service names
| Persistence | Persist Processor | Remove Processor |
|---|---|---|
| ORM | api_platform.doctrine.orm.state.persist_processor |
api_platform.doctrine.orm.state.remove_processor |
| MongoDB ODM | api_platform.doctrine_mongodb.odm.state.persist_processor |
api_platform.doctrine_mongodb.odm.state.remove_processor |
Laravel (Eloquent):
ProcessorInterfaceis identical and resources reference a processor by class-string (processor: YourProcessor::class). The built-in Eloquent processors are bound in the container by class name —ApiPlatform\Laravel\Eloquent\State\PersistProcessor(handles create/update, including BelongsTo/HasMany relations andstandard_put) and…\State\RemoveProcessor. To decorate, type-hint that concrete class in your constructor instead of using a#[Autowire(service: 'api_platform.doctrine.*')]attribute. Side-effect patterns (mailers, events) work the same via Laravel's container. Returning a SymfonyResponsefrom a processor is also supported.
Creating Related Entities in a Processor
Create child resources alongside the main resource:
final class AccountCreateProcessor implements ProcessorInterface
{
public function __construct(
#[Autowire(service: 'api_platform.doctrine_mongodb.odm.state.persist_processor')]
private ProcessorInterface $persistProcessor,
) {}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
{
$this->hashPassword($data);
// Create related entities before persisting
foreach (['INBOX', 'Sent', 'Trash', 'Drafts'] as $name) {
$mailbox = new Mailbox();
$mailbox->path = $name;
$data->addMailbox($mailbox); // cascade: ['persist']
}
// Single persist call saves parent + children
return $this->persistProcessor->process($data, $operation, $uriVariables, $context);
}
}
Soft-Delete Processor
Reusable processor for soft-deleting resources:
/**
* @implements ProcessorInterface<Account|Domain, Account|Domain>
*/
readonly class SoftDeleteProcessor implements ProcessorInterface
{
public function __construct(private DocumentManager $dm) {}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
{
$data->isDeleted = true;
$this->dm->persist($data);
$this->dm->flush();
return $data;
}
}
Assign to Delete operations:
new Delete(processor: SoftDeleteProcessor::class)
Combine with a collection extension that filters isDeleted = false to hide soft-deleted records from queries (see securing-collections skill).
Returning HTTP Responses (File Downloads)
Processors can return a Symfony Response for binary content:
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\Response;
/**
* @implements ProcessorInterface<Message, Response>
*/
final class DownloadProcessor implements ProcessorInterface
{
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): Response
{
$content = $this->buildContent($data);
$response = new Response($content);
$response->headers->set('Content-Type', 'application/octet-stream');
$response->headers->set('Content-Disposition',
HeaderUtils::makeDisposition(HeaderUtils::DISPOSITION_ATTACHMENT, $data->getId() . '.bin')
);
return $response;
}
}
Use with a Get operation that has write: true:
new Get(
uriTemplate: '/orders/{id}/download',
write: true,
processor: DownloadProcessor::class,
name: '_api_order_download',
)
Handling Both Persist and Delete
When a single processor handles Create/Update AND Delete, inject both services:
public function __construct(
#[Autowire(service: 'api_platform.doctrine.orm.state.persist_processor')]
private ProcessorInterface $persistProcessor,
#[Autowire(service: 'api_platform.doctrine.orm.state.remove_processor')]
private ProcessorInterface $removeProcessor,
) {}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
{
if ($operation instanceof DeleteOperationInterface) {
return $this->removeProcessor->process($data, $operation, $uriVariables, $context);
}
return $this->persistProcessor->process($data, $operation, $uriVariables, $context);
}
Processor Parameters
- $data: The deserialized/validated object
- $operation: Operation metadata (Post, Patch, Delete, etc.)
- $uriVariables: URI path variables
- $context: Includes
previous_data(before modification),request,resource_class
Best Practices
- Always return data from processors — omitting breaks serialization
- Decorate built-in processors rather than replacing them
- Keep processors focused: one processor per operation when logic differs significantly
- Use
$context['previous_data']in Patch/Put to detect what changed - Throw
HttpExceptionsubclasses for domain errors (BadRequestHttpException,UnprocessableEntityHttpException)
Bu becerideki dosyalar
1state-processor skill soruları
state-processor skill'ini Claude Code uygulamasına nasıl kurarım?
npx degit api-platform/skillset/skills/state-processor ~/.claude/skills/state-processor komutunu çalıştırın. Claude Code, skill'leri ~/.claude/skills (tüm projeler) veya .claude/skills (tek proje) konumundan yükler ve açıklaması görevle eşleştiğinde skill'i kullanır.
state-processor skill'ini hangi istemciler kullanabilir?
Agent Skills biçimini okuyan her istemci: Claude Code, Codex, Gemini CLI ve claude.ai (ZIP olarak yükleyin). Skill içindeki betikler yalnızca istemcinin kod çalıştırmaya izin verdiği yerlerde çalışır.
Bir state processor ne zaman çalışır?
Bir processor, işlemin 'write' bayrağı true olarak ayarlandığında, genellikle POST, PUT, PATCH veya DELETE işlemleri sırasında çalışır.
Bir processor GET işlemleri için kullanılabilir mi?
Evet, ancak GET işleminde 'write: true' ayarını açıkça yapmanız gerekir; bu durum dosya indirme veya rapor oluşturma gibi görevler için kullanışlıdır.
Yazma işlemi sırasında e-posta göndermek gibi yan etkiler nasıl eklenir?
Veriler kaydedilmeden önce veya sonra mantık yürütmek için yerleşik persistence processor'ı dekore edebilirsiniz.
API Platform'da provider ve processor arasındaki fark nedir?
Bir state-provider Query (okuma) tarafını yönetirken, bir state-processor CQRS tarzı ayrımın Command (yazma) tarafını yönetir.