AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Magento2 Backend Dev

skill-ddtcorex-dev-skills-hub-magento2-backend-dev · by ddtcorex

|

No reviews yet
0 installs
8 views
0.0% view→install

Install

$ agentstack add skill-ddtcorex-dev-skills-hub-magento2-backend-dev

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-ddtcorex-dev-skills-hub-magento2-backend-dev)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
17d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Magento2 Backend Dev? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Magento 2 Backend Developer

This skill covers API development (REST, SOAP, GraphQL), CLI commands, cron jobs, and message queues.

Related Skills

REQUIRED BACKGROUND: Load magento2-dev-core first — it defines the DI, repository, and security patterns (constructor injection, service contracts, escaping, discouraged functions) this skill assumes without repeating.

Pairs with magento2-security-scan when the API/resolver you're building touches authentication, ACL, or user input, and with magento2-performance-audit for queue/consumer and N+1 concerns once the endpoint is built. In a Govard environment, use govard-magento for the CLI/container side (bin/magento, cache, indexers).

REST API

Service Contract Structure

Vendor/Module/
├── Api/
│   ├── ProductRepositoryInterface.php    # Declaration
│   └── Data/
│       └── ProductInterface.php          # Data entity
└── Model/
    └── ProductRepository.php              # Implementation

Data Interface

resource->save($product);
        return $product;
    }

    public function getById(int $id): ProductInterface
    {
        $product = $this->productFactory->create();
        $this->resource->load($product, $id);
        if (!$product->getId()) {
            throw new \Magento\Framework\Exception\NoSuchEntityException(
                __('Product with ID %1 does not exist', $id)
            );
        }
        return $product;
    }

    public function get(SearchCriteriaInterface $searchCriteria): ProductSearchResultsInterface
    {
        $searchResults = $this->searchResultsFactory->create();
        $searchResults->setSearchCriteria($searchCriteria);
        $collection = $this->productCollection->create();
        $this->applySearchCriteria($collection, $searchCriteria);
        $searchResults->setItems($collection->getItems());
        $searchResults->setTotalCount($collection->getSize());
        return $searchResults;
    }
}

WebAPI Configuration


    
    
        
        
            
        
    

    
    
        
        
            
        
    

    
    
        
        
            
        
    

ACL Configuration


    
        
            
                
                    
                    
                    
                
            
        
    

GraphQL

Schema Definition

# etc/schema.graphqls

type Query {
    products(filter: ProductFilterInput, pageSize: Int = 20, currentPage: Int = 1): Products
    @doc(description: "Get products list")
    @resolver(class: "Vendor\\Module\\Model\\Resolver\\ProductList")
    @cache(cacheable: false)
}

type Mutation {
    createProduct(input: ProductInput!): Product
    @doc(description: "Create a new product")
    @resolver(class: "Vendor\\Module\\Model\\Resolver\\CreateProduct")
    @cache(cacheable: false)
}

input ProductFilterInput {
    entity_id: FilterTypeInput
    name: FilterTypeInput
    sku: FilterTypeInput
    price: FilterTypeInput
}

type Product {
    entity_id: Int
    name: String
    sku: String
    price: Float
}

input ProductInput {
    name: String!
    sku: String!
    price: Float!
}

Resolver Implementation

searchCriteriaBuilder
            ->setPageSize($args['pageSize'])
            ->setCurrentPage($args['currentPage'] ?? 1)
            ->create();

        $searchResults = $this->productRepository->get($searchCriteria);

        return [
            'total_count' => $searchResults->getTotalCount(),
            'items' => $this->convertProducts($searchResults->getItems())
        ];
    }

    private function convertProducts(array $products): array
    {
        return array_map(function ($product) {
            return [
                'entity_id' => $product->getId(),
                'name' => $product->getName(),
                'sku' => $product->getSku(),
                'price' => $product->getPrice()
            ];
        }, $products);
    }
}

For cacheable GraphQL types, implement IdentityInterface on the resolver (or a dedicated identity provider) so Magento can tag the response for full-page cache invalidation — without it, @cache(cacheable: true) has nothing to key on and the type is effectively never cached correctly.

CLI Commands

Command Class

commandName);
    }

    protected function configure(): void
    {
        $this->setDescription($this->commandDescription);
        $this->addOption(
            'dry-run',
            'd',
            InputOption::VALUE_NONE,
            'Run without making changes'
        );
        $this->addOption(
            'limit',
            'l',
            InputOption::VALUE_REQUIRED,
            'Limit number of products',
            100
        );
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $io->title('Product Synchronization');

        $limit = (int) $input->getOption('limit');
        $dryRun = $input->getOption('dry-run');

        if ($dryRun) {
            $io->note('Running in dry-run mode');
        }

        try {
            $externalProducts = $this->apiClient->fetchProducts($limit);
            $io->progressStart(count($externalProducts));

            foreach ($externalProducts as $externalProduct) {
                if (!$dryRun) {
                    $this->syncProduct($externalProduct);
                }
                $io->progressAdvance();
            }

            $io->progressFinish();
            $io->success(sprintf('Synchronized %d products', count($externalProducts)));

            return Command::SUCCESS;
        } catch (\Exception $e) {
            $io->error('Synchronization failed: ' . $e->getMessage());
            return Command::FAILURE;
        }
    }
}

Register Command


    
        
            Vendor\Module\Console\Command\SyncProductsCommand
        
    

state->setAreaCode(Area::AREA_ADMINHTML)` (or `AREA_FRONTEND`/`AREA_GLOBAL`) — a bare CLI command defaults to no area, and area-dependent services throw a `LocalizedException` otherwise.

## Cron Jobs

### Cron Class

```php
logger->info('Running expired product cleanup');

        try {
            $expiredProducts = $this->findExpiredProducts();
            foreach ($expiredProducts as $product) {
                $product->setStatus(Status::STATUS_DISABLED);
                $this->productRepository->save($product);
            }

            $this->logger->info(sprintf('Cleaned up %d expired products', count($expiredProducts)));
        } catch (\Exception $e) {
            $this->logger->error('Cleanup failed: ' . $e->getMessage());
        }
    }
}

Cron Configuration


    
        
            0 2 * * *
        
    
    
        
            */5 * * * *
        
    

Cron Groups (for large scale)


    
        1
        4
        2
        10
        1440
        60
        1
    

Message Queue

Not every project needs all four queue XML files — communication.xml (topic schema) is the one that's always required. Add queue_topology.xml, queue_publisher.xml, queue_consumer.xml only for what the use case actually needs (e.g. just queue_publisher.xml when publishing to a queue a third party already owns).

Publisher Configuration


    
        
    

Queue Consumer

handler->process($data);
    }
}

Message Class


    

Pitfalls recap

  • The resource ref in webapi.xml must match an actual id declared in acl.xml — a typo here fails silently with a 403, not a config error.
  • Always throw NoSuchEntityException (not return null) when a repository can't find an entity — the WebAPI framework maps it to a proper 404.
  • A configured consumer (queue.xml) does nothing on its own — it must actually be running as a process via cron or a supervisor (bin/magento queue:consumers:start), or messages just pile up in the queue_message tables. See magento2-performance-audit.
  • GraphQL resolvers get no automatic ACL check — validate the customer/admin context explicitly inside resolve() if the field exposes anything sensitive.

cron_schedule rows move through pendingrunningsuccess/error/missed. Never TRUNCATE cron_schedule to "fix" a stuck cron — query it (WHERE status IN ('error','missed')) to diagnose the actual cause instead, since truncating destroys the run history you'd need to find it.

Verification

# Test CLI command
bin/magento vendor:products:sync --dry-run --limit=10

# List registered commands
bin/magento list | grep vendor

# Run cron manually
bin/magento cron:run --group=custom

# Check queue consumers
bin/magento queue:consumers:list

# Start message queue consumer
bin/magento queue:consumers:start vendor.product.update.consumer

# Test REST API
curl -X GET "http://localhost/V1/vendor/product/1" \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json"

# Clear API cache
bin/magento cache:clean config

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.