Initialize Akeneo PIM Standard Edition
composer create-project --prefer-dist akeneo/pim-community-standard /tmp/pim-standard-edition "1.6.*@stable"
Generate Extension Skeleton
Navigate to src/ of your Akeneo installation and run:
composer create-project akeneo-labs/extension-starter YourCompanyName
Customize the Starter
Replace placeholders in composer.json (e.g., Acme → YourCompanyName, DemoConnectorBundle → YourExtensionBundle):
sed -i "s#Acme#YourCompanyName#g" composer.json
sed -i "s#DemoConnectorBundle#YourExtensionBundle#g" composer.json
Register the Bundle
Add the bundle to app/AppKernel.php and update composer.json autoload:
"autoload": {
"psr-4": {
"YourCompanyName\\Bundle\\YourExtensionBundle\\": "src/YourCompanyName"
}
}
Run:
composer dump-autoload
Test Clear cache and verify the extension loads:
php app/console cache:clear
Create a New Attribute Type Class
Extend Akeneo\Tool\Component\Attribute\Common\Type\AbstractType in YourExtensionBundle/AttributeType/YourType.php.
Register the Type
Override buildAttributeTypes() in YourExtensionBundle/DependencyInjection/YourExtensionExtension.php:
public function load(array $configs, ContainerBuilder $container)
{
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
Define Services
In Resources/config/services.yml:
services:
your_extension.attribute_type.your_type:
class: YourCompanyName\Bundle\YourExtensionBundle\AttributeType\YourType
tags:
- { name: akeneo_attribute.type, type: your_type }
Verify in PIM Check if the new attribute type appears in the UI under Settings > Attributes.
Symlink or Vendor Integration
src/ for live development:
ln -s /path/to/extension src/YourCompanyName
composer require yourcompany/your-extension
Processor-Based Logic
Use Akeneo’s ProcessorInterface for imports/exports. Example:
namespace YourCompanyName\Bundle\YourExtensionBundle\Processor;
use Akeneo\Tool\Component\Connector\Processor\Item\ItemProcessorInterface;
class YourProcessor implements ItemProcessorInterface
{
public function process($item)
{
// Transform $item (e.g., map PIM fields to external API)
return $transformedItem;
}
}
Event Subscribers
Hook into Akeneo’s events (e.g., pim_enrich.product.save):
namespace YourCompanyName\Bundle\YourExtensionBundle\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class YourSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
'pim_enrich.product.save' => 'onProductSave',
];
}
public function onProductSave($event)
{
// Custom logic on product save
}
}
Configuration Management
Use Extension class to inject configuration:
namespace YourCompanyName\Bundle\YourExtensionBundle\DependencyInjection;
class YourExtensionExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$container->setParameter('your_extension.config', $config);
}
}
Database Migrations Use Doctrine Migrations for schema changes:
php app/console doctrine:migrations:diff
php app/console doctrine:migrations:migrate
Asset Management
Place static assets (JS/CSS) in Resources/public/ and enable Twig:
{% block stylesheets %}
{{ parent() }}
{{ asset('bundles/yourextension/css/your.css') }}
{% endblock %}
Testing
Extend Akeneo’s WebTestCase for functional tests:
use Akeneo\Test\Integration\WebTestCase;
class YourExtensionTest extends WebTestCase
{
public function testYourFeature()
{
$client = static::createClient();
$crawler = $client->request('GET', '/your-route');
// Assertions...
}
}
Localization Use translation domains in templates:
{{ 'your_extension.your_message'|trans }}
Define translations in Resources/translations/messages.en.yml.
Namespace Collisions
YourCompanyName\Bundle\YourExtensionBundle) is unique.Akeneo\).Autoloading Issues
composer dump-autoload after manual composer.json changes.Event Dispatcher Conflicts
pim_enrich.product.index). Use custom events instead.$dispatcher->dispatch('your_extension.product.post_save', new YourEvent($product));
Database Compatibility
findAll() in processors. Use pagination or cursors:
$repository->createQueryBuilder('p')
->setMaxResults(100)
->getQuery()
->getResult();
Cache Invalidation
php app/console cache:clear --env=prod
php app/console pim:cache:warmup
Log Output Use Monolog in your bundle:
$this->container->get('logger')->info('Your debug message');
Check logs at var/log/dev.log.
Symfony Profiler
Enable the profiler in app/config/config_dev.yml:
framework:
profiler: { only_exceptions: false }
Access at /_profiler.
XDebug
Configure php.ini for remote debugging:
xdebug.remote_enable=1
xdebug.remote_port=9000
Akeneo-Specific Tools
app/config/config_dev.yml:
akeneo_debug_toolbar:
enabled: true
pim:import and pim:export for testing connectors.Custom Attribute Types
Extend AbstractType and register via akeneo_attribute.type tag. Example:
services:
your_extension.attribute_type.color:
class: YourCompanyName\Bundle\YourExtensionBundle\AttributeType\ColorType
tags:
- { name: akeneo_attribute.type, type: pim_catalog_color }
Custom Forms
Override Akeneo’s form types in Resources/config/akeneo_form_types.yml:
akeneo_form.type.product:
parent: Akeneo\Platform\Bundle\Form\Type\ProductType
class: YourCompanyName\Bundle\YourExtensionBundle\Form\Type\ProductType
Custom Actions
Add mass actions via akeneo_action tag:
services:
your_extension.action.your_action:
class: YourCompanyName\Bundle\YourExtensionBundle\Action\YourAction
tags:
- { name: akeneo_action.action, type: your_action, label: 'Your Action' }
Custom Widgets Create
How can I help you explore Laravel packages today?