Skip to main content
Version: 2026.2

Workflow Tutorial

This tutorial builds a product workflow for data objects, covering places, transitions, guards, custom layouts, and additional fields.

Create a class and custom layouts

Start with a simple product class containing sku, localized name, localized picture, localized description, price, and quantity.

Example product classExample product classExample product class

Add four custom layouts to assign to specific workflow statuses:

  • newProduct layout with ID = newProduct

The new product custom layoutThe new product custom layoutThe new product custom layout

  • fillContents layout with ID = fillContents

The fill contents custom layoutThe fill contents custom layoutThe fill contents custom layout

  • updatePicture layout with ID = updatePicture

The update picture custom layoutThe update picture custom layoutThe update picture custom layout

  • validateQtyPrice layout with ID = validateQtyPrice

The validate qty and price custom layoutThe validate qty and price custom layoutThe validate qty and price custom layout

The workflow declaration

Create the base configuration in config/config.yaml:

pimcore:
workflows:
my_workflow:
label: 'Product Workflow'
type: 'state_machine'
supports:
- 'Pimcore\Model\DataObject\Product'
places:
#TODO
transitions:
#TODO

The workflow is called Product Workflow and applies only to instances of Pimcore\Model\DataObject\Product. The workflow type state_machine restricts the element to one active place at a time. Places and transitions are defined in the following sections.

Specify places

Define places for products. In this scenario, new products arrive from an external system as empty objects with only a SKU. The workflow needs to support deciding which products to use in Pimcore and which to reject. This requires (at least) three places:

  • new - for the newest products
  • rejected - for products that will not be used, with a required note explaining the reason
  • update content - for products to prepare for publishing
(...)
places:
new:
label: 'New product'
color: '#377ea9'
permissions:
- objectLayout: 'newProduct'
rejected:
label: 'Rejected product'
color: '#28a013'
update_content:
label: 'Update Content'
title: 'Updating content step'
color: '#d9ef36'
permissions:
- objectLayout: 'fillContents'

(...)

The objectLayout key defines which custom layout to use for each place. Here, the new place uses custom layout 1 and update_content uses custom layout 2.

Specify the first transitions

An administrator can decide which products to process and which to reject. Add two transitions:

  • reject product - changes the status for products not to be used
  • start processing - moves the product to the processing step
(...)
transitions:
reject_product:
from: new
to: rejected
options:
label: 'Reject the product'
notes:
commentEnabled: true
commentRequired: true
start_processing:
from: new
to: update_content
options:
label: 'Start processing the product'
(...)

More statuses, actions, and definitions

Add 4 more places for the content update pipeline:

  • updating the content
  • updating the picture
  • updating the price and stock
  • marking content as ready - moving the product back to the administrator

Add these to the configuration file:


(...)
places:
(...)
update_picture:
label: 'Update Product Picture'
title: 'Update the product picture'
color: '#d9ef36'
permissions:
- objectLayout: 'updatePicture'
validate_stock_and_price:
label: 'Validate Stock + Price'
title: 'Check the quantity and the price'
color: '#d9ef36'
permissions:
- objectLayout: 'validateQtyPrice'
content_prepared:
label: 'Content Prepared'
title: 'Content ready to publish'
color: '#28a013'
(...)

transitions:
(...)
content_updated:
from: update_content
to: update_picture
options:
label: 'Content up-to-date'
notes:
commentEnabled: true
commentRequired: false
picture_updated:
from: update_picture
to: validate_stock_and_price
options:
label: 'Picture up-to-date'
notes:
commentEnabled: true
commentRequired: false
content_ready:
from: validate_stock_and_price
to: content_prepared
options:
label: 'Content is ready to publish'
(...)

Last actions: publish or rollback

At the final stage, the workflow offers three choices:

  • Publish the product (with an additional field called "timeWorked")
  • Start the workflow from the beginning
  • Reject the product (with a note)

The reject and start processing transitions already exist. Add content_prepared as an additional from place. This works because the workflow type state_machine supports multiple from places per transition.


(...)
transitions:
reject_product:
from: [new, content_prepared]
to: rejected
options:
label: 'Reject the product'
notes:
commentEnabled: true
commentRequired: true
start_processing:
from: [new, content_prepared]
to: update_content
options:
label: 'Start processing the product'
notes:
commentEnabled: true
commentRequired: false
(...)

The final addition is a publish transition with a place and a guard restricting it to a certain role:

(...)
places:
(...)
accepted:
label: 'Accepted product'
color: '#28a013'
(...)

And the transition with a "timeWorked" additional field:

(...)
transitions:
(...)
publish:
from: content_prepared
to: accepted
guard: "is_fully_authenticated() and is_granted('ROLE_PIMCORE_ADMIN')"
options:
label: 'Publish the product'
notes:
commentEnabled: true
commentRequired: true
additionalFields:
- name: 'timeWorked'
fieldType: 'input'
title: 'Time Spent'
required: true
(...)

Workflow in action

The following table shows the workflow at each stage:

StatusScreenshot
Initial status when new object comes into the system
Initial PlaceInitial PlaceInitial Place
Update Content
Update ContentUpdate ContentUpdate Content
Update Picture
Update PictureUpdate PictureUpdate Picture
Validate Price and Stock
ValidateValidateValidate
Content is ready
Content ReadyContent ReadyContent Ready
Publish the Product
Publish ProductPublish ProductPublish Product

Check the history

The "Notes & Events" tab lists every action applied to the object through the workflow module.

Notes & Events - notes from the workflowNotes & Events - notes from the workflowNotes & Events - notes from the workflow