Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Added docs for Workflow component#6871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
Nyholm wants to merge38 commits intosymfony:masterfromNyholm:workflow
Closed
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
38 commits
Select commitHold shift + click to select a range
d0701f0
Added docs for Workflow component
NyholmAug 12, 2016
91867c2
Moved images
NyholmAug 12, 2016
69bca59
Fixes
NyholmAug 12, 2016
f99fbb2
Fixes
NyholmAug 12, 2016
e797f0c
Syntax error
NyholmAug 12, 2016
5b2a029
Cleanup and minor fixes
NyholmAug 16, 2016
196baf9
Separated docs for component
NyholmAug 16, 2016
763950d
Updating docs to using symfony services
NyholmAug 16, 2016
cead2f7
Added docs about registry
NyholmAug 16, 2016
e0089c5
Added placeholders
NyholmAug 16, 2016
48de43d
Added note about state machines
NyholmAug 16, 2016
805b237
Added example with twig
NyholmAug 16, 2016
f57ec14
Show Twig function workflow_transitions
NyholmAug 16, 2016
03925ff
syntax fix
NyholmAug 16, 2016
e6bdee6
Some syntax fixes and a better "why do we need this"
NyholmNov 7, 2016
c7464c7
typos
NyholmNov 7, 2016
83d26c1
toctree fix
NyholmNov 7, 2016
6e7a35f
Fixed typos and comments
NyholmNov 8, 2016
4415466
Added usage example on the component
NyholmNov 8, 2016
866b25a
Added example how to dump with Symfony
NyholmNov 8, 2016
dceebec
Added examples of workflows
NyholmNov 8, 2016
b959f8a
Updated state machine with an example
NyholmNov 8, 2016
b45edf2
simplify job_application
NyholmNov 8, 2016
fefdb5f
syntax
NyholmNov 9, 2016
7f0f5b0
Added comment about the service name
NyholmNov 9, 2016
c681283
Updated accoding to feedback
NyholmNov 9, 2016
86ecf0a
Added PHP config
NyholmNov 9, 2016
d002a8b
Added xml and PHP config
NyholmNov 9, 2016
b0a8855
Added workflow under guides
NyholmNov 9, 2016
4e7cf11
Removed the *why workflows* from the usage page.
NyholmNov 9, 2016
3aa433d
Documented support for DefinitionBuilder
NyholmNov 9, 2016
4f277dc
fixed typo
NyholmNov 9, 2016
2511c21
Merge pull request #1 from Nyholm/workflow-definition-builder
NyholmNov 9, 2016
c9b1656
Updated to support changes in https://github.com/symfony/symfony/pull…
NyholmNov 9, 2016
2cc2934
Updated twig example
NyholmNov 9, 2016
47dc11d
show how to configure the DI extension config
NyholmNov 11, 2016
3250621
Fixed typos
NyholmNov 11, 2016
c0bd6da
Use imperative instead of past tense.
NyholmNov 11, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added_images/components/workflow/blogpost.png
View file
Open in desktop
Loading
Sorry, something went wrong.Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View file
Open in desktop
Loading
Sorry, something went wrong.Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added_images/components/workflow/pull_request.png
View file
Open in desktop
Loading
Sorry, something went wrong.Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added_images/components/workflow/simple.png
View file
Open in desktop
Loading
Sorry, something went wrong.Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View file
Open in desktop
Loading
Sorry, something went wrong.Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 84 additions & 3 deletionscomponents/workflow.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,8 @@
The Workflow Component
======================

The Workflow component provides tools for managing a workflow or finite state
machine.
The Workflow component provides tools for managing a workflow or finite
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

isn't a Petri net instead ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@mickaelandrieu a workflow is a subset of a petri net (and a state machine a subset of workflow). The component does not support all features necessary to implement a petri net

Copy link
Contributor

@mickaelandrieumickaelandrieuDec 1, 2016
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

it's unclear to me right now, but it's not a problem in the docs: I just need to learn a little bit more about all of theses implementations ^^

Thank you@stof

statemachine.

.. versionadded:: 3.2
The Workflow component was introduced in Symfony 3.2.
Expand All@@ -19,6 +19,87 @@ You can install the component in 2 different ways:
* :doc:`Install it via Composer </components/using_components>` (``symfony/workflow`` on `Packagist`_);
* Use the official Git repository (https://github.com/symfony/workflow).

For more information, see the code in the Git Repository.
.. include:: /components/require_autoload.rst.inc

Creating a Workflow
-------------------

The workflow component gives you an object oriented way to define a process
Copy link
Contributor

@mickaelandrieumickaelandrieuNov 30, 2016
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The more I read this, the more I think we should rename - at least in docs -Workflow component toWorkflow Engine component. Am I crazy ? /c@Nyholm

or a life cycle that your object goes through. Each step or stage in the
process is called a *place*. You do also define *transitions* that describe
the action to get from one place to another.

.. image:: /_images/components/workflow/states_transitions.png

A set of places and transitions creates a **definition**. A workflow needs
a ``Definition`` and a way to write the states to the objects (i.e. an
instance of a :class:`Symfony\\Component\\Workflow\\MarkingStore\\MarkingStoreInterface`).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

please remove the empty lines (except from one)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

You should also the initial place with something like:If a definition has no explicit initial place, it uses the first place defined.

Consider the following example for a blog post. A post can have one of a number
of predefined statuses (`draft`, `review`, `rejected`, `published`). In a workflow,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I suggest to usedrafted andneeds_review instead ofdraft andreview. That allows more readability, one may needs more statuses likereviewed andneeds_correction. (I do :D). What about addingarchived too?

these statuses are called **places**. You can define the workflow like this::

use Symfony\Component\Workflow\DefinitionBuilder;
use Symfony\Component\Workflow\Transition;
use Symfony\Component\Workflow\Workflow;
use Symfony\Component\Workflow\MarkingStore\SingleStateMarkingStore;

$builder = new DefinitionBuilder();
$builder->addPlaces(['draft', 'review', 'rejected', 'published']);

// Transitions are defined with a unique name, an origin place and a destination place
$builder->addTransition(new Transition('to_review', 'draft', 'review'));
$builder->addTransition(new Transition('publish', 'review', 'published'));
$builder->addTransition(new Transition('reject', 'review', 'rejected'));

$definition = $builder->build();

$marking = new SingleStateMarkingStore('currentState');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

What aboutstatus?

$workflow = new Workflow($definition, $marking);

The ``Workflow`` can now help you to decide what actions are allowed
on a blog post depending on what *place* it is in. This will keep your domain
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

It's not about domain logic, it's more about Workflow management logic, isn'it ?

I'd say instead "This will keep your Workflow logic in one place and not spread all over your applications.", what do you think ?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Interesting. I would always consider this the domain logic because the "workflow management logic" is a part of your domain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The theory behind "Workflow management" is to put the Workflow managementoutside of your domain, if I've well understood. BlogPost entity shouldn't be modified every time the rules of publishing evolve, for instance.

I'm pretty noob of this field, so correct me if I'm wrong :)

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

BlogPost entity shouldn't be modified every time the rules of publishing evolve, for instance.

Correct, you just edit the workflow when the rules of publishing changes.

The theory behind "Workflow management" is to put the Workflow management outside of your domain, if I've well understood.

Outside the domain or outside yourmodel? The way I see it there is only three places you can put code/config:

  • In the framework
  • In your domain
  • The glue between your domain and the framework.

Can@lyrixx give some input?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I'm not sure to understand the question / debate here.
Basically, the the data are stored in the model, and you can put the places / transitions everywhere you want. I don't have a rule of thumb for that. IMHO, Simple things are always better than perfect code.

Copy link
Contributor

@unkindunkindAug 16, 2016
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

If you write an issue with a summary of your thoughts with pros and cons, I'll be happy to submit a PR for that issue.

I can't do it, because the primary purpose of this Workflow component is not obvious for me:

It would be nice to describe the purpose of the component more.

The component is designed as very generic thing, so in theory it probably may have some interesting applications. However, providedexamples don't impress. Compare it with rich domain model:

finalclass Article{private$id;private$title;private$approvedByJournalist;private$approvedBySpellchecker;private$published;publicstaticfunctionpostDraft(int$articleId,ArticleTitle$title):Article    {$draft =newself();$draft->apply(newDraftArticleWasPosted($articleId,$title));$draft->apply(newArticleWasSentForApproval($this->id));return$draft;    }privatefunction__construct() {}publicfunctionapproveByJournalist()    {if ($this->approvedByJournalist) {return;        }$this->apply(newArticleWasApprovedByJournalist($this->id));$this->publishIfItIsReady();    }publicfunctionapproveBySpellchecker()     {if ($this->approvedBySpellchecker) {return;        }$this->apply(newArticleWasApprovedBySpellchecker($this->id));$this->publishIfItIsReady();    }publicfunctionchangeTitle(ArticleTitle$newTitle)    {if ($this->title->equals($newTitle)) {return;        }$this->apply(newArticleTitleWasChanged($this->id,$newTitle));$this->apply(newArticleWasSentForApproval($this->id));    }privatefunctionpublishIfItIsReady()    {if ($this->approvedByJournalist &&$this->approvedBySpellchecker) {$this->apply(newArticleWasPublished($this->id));        }    }// ...privatefunctiononArticleWasApprovedByJournalist(ArticleWasApprovedByJournalist$event)    {$this->approvedByJournalist =true;    }privatefunctiononArticleWasSentForApproval(ArticleWasSentForApproval$event)    {$this->approvedByJournalist =false;$this->approvedBySpellchecker =false;$this->published =false;    }privatefunctiononArticleTitleWasChanged(ArticleTitleWasChanged$event)    {$this->title =$event->getNewTitle();    }}

We see use-cases (postDraft,approveBySpellchecker,approveBySpellchecker,changeTitle), events (ArticleWasApprovedByJournalist, ...,ArticleTitleWasChanged) and it's not hard to understand lifecycle of theArticle from this code. We lose this expressiveness.

Further, that sample projectchecks permissions withGuardEvent hook:

publicfunctiononTransitionJournalist(GuardEvent$event)    {if (!$this->checker->isGranted('ROLE_JOURNALIST')) {$event->setBlocked(true);        }    }

... and how you can solve it with commands:

finalclass ApproveArticleByJournalistHandler{/**     * @acl_role ROLE_JOURNALIST     */publicfunctionhandle(ApproveArticleByJournalist$command)    {$blogPost =$this->blogPostRepository->find($command->getArticleId());$blogPost->approveByJournalist();$this->blogPostRepository->save($blogPost);    }}

And again we lose expressiveness by genericGuardEvent hook. It's harder to find it in the project, your have to search for string "workflow.article.guard.journalist_approval" instead of typing class name "ApproveArticleByJournalis...".

I would like to know if I'm wrong.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

IMHO, all this debate is totally out of the scope of this PR.

Nyholm reacted with thumbs up emoji
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

How is it possible to write docs for the component without clear applications, examples?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I did not said that. But you you are telling us the Workflow component is useless and it's better to write code like your example. It's really a matter of taste (I have a strong opinion on that ; but I let people making their own choices). So I'm juste saying: The component is here, and it's useless to discuss if it's better to use CQRS / ES over Workflow Component.

For the record, the discussion is about the following sentence:

The workflow will keep your domain logic in one place and not spread all over your application

IMHO, it's more important to document how the component works.

I like the@Nyholm's work ; so let's focus on what matter.

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@unkind: I hear you. Your arguments are valid.
@mickaelandrieu: Your arguments are also valid.

This is, as Grégoire says, out of scope for this PR.@unkind, I've asked you to create an issue on the symfony/symfony repository. I amhappy to make a PR to try to improve the Workflow component regarding your input. Let's work together on this, but not in this PR.

chalasr reacted with thumbs up emoji
logic in one place and not spread all over your application.

When you define multiple workflows you should consider using a ``Registry``,
which is an object that stores and provides access to different workflows.
A registry will also help you to decide if a workflow supports the object you
are trying to use it with::

use Symfony\Component\Workflow\Registry;
use Acme\Entity\BlogPost;
use Acme\Entity\Newsletter;

$blogWorkflow = ...
$newsletterWorkflow = ...

$registry = new Registry();
$registry->add($blogWorkflow, BlogPost::class);
$registry->add($newsletterWorkflow, Newsletter::class);

Usage
-----

When you have configured a ``Registry`` with your workflows, you may use it as follows::

// ...
$post = new BlogPost();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

please prefix the example with// ... to indicate things are left out (but shown above).

// ...$post =newBlogPost();

$workflow = $registry->get($post);

$workflow->can($post, 'publish'); // False
$workflow->can($post, 'to_review'); // True

$workflow->apply($post, 'to_review');
$workflow->can($post, 'publish'); // True
$workflow->getEnabledTransitions($post); // ['publish', 'reject']

Learn more
----------

.. toctree::
:maxdepth: 1
:glob:

/workflow/*

.. _Packagist: https://packagist.org/packages/symfony/workflow
1 change: 1 addition & 0 deletionsindex.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -62,6 +62,7 @@ Topics
testing
translation
validation
workflow

Best Practices
--------------
Expand Down
50 changes: 50 additions & 0 deletionsworkflow.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
Workflow
========

A workflow is a model of a process in your application. It may be the process
of how a blog post goes from draft, review and publish. Another example is when
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

"drafted, reviewed and published"?

a user submits a series of different forms to complete a task. Such processes are
best kept away from your models and should be defined in configuration.

A **definition** of a workflow consist of places and actions to get from one
place to another. The actions are called **transistions**. A workflow does also
need to know each object's position in the workflow. That **marking store** writes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

"That marking score [...]" -> "The marking store [...]"

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I do not see where I've written "score". It supposed to be "store" everywhere.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Oh, sorry, typo from my side. I meant "That" should become "The".

to a property of the object to remember the current place.

..note::

The terminology above is commonly used when discussing workflows and
`Petri nets`_

The Workflow component does also support state machines. A state machine is a subset
of a workflow and its purpose is to hold a state of your model. Read more about the
differences and specific features of state machine in:doc:`/workflow/state-machines`.

Examples
--------

The simples workflow looks like this. It contains two places and one transition.

..image::/_images/components/workflow/simple.png

Workflows could be more complicated when they describe a real business case. The
workflow below describes the process to fill in a job application.

..image::/_images/components/workflow/job_application.png

When you fill in a job application in this example there are 4 to 7 steps depending
on the what job you are applying for. Some jobs require personality tests, logic tests
and/or formal requirements to be answered by the user. Some jobs don't. The
``GuardEvent`` is used to decide what next steps are allowed for a specific application.

By defining a workflow like this, there is an overview how the process looks like. The process
logic is not mixed with the controllers, models or view. The order of the steps can be changed
by changing the configuration only.

..toctree::
:maxdepth:1
:glob:

workflow/*

.. _Petri nets:https://en.wikipedia.org/wiki/Petri_net
37 changes: 37 additions & 0 deletionsworkflow/dumping-workflows.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
.. index::
single: Workflow; Dumping Workflows

How to Dump Workflows
=====================

To help you debug your workflows, you can dump a representation of your workflow with
the use of a ``DumperInterface``. Use the ``GraphvizDumper`` to create a
PNG image of the workflow defined above::

// dump-graph.php
$dumper = new GraphvizDumper();
echo $dumper->dump($definition);

.. code-block:: terminal

$ php dump-graph.php > out.dot
$ dot -Tpng out.dot -o graph.png

The result will look like this:

.. image:: /_images/components/workflow/blogpost.png

If you have configured your workflow with the Symfony framework, you may dump the dot file
with the ``WorkflowDumpCommand``:

.. code-block:: terminal

$ php bin/console workflow:dump name > out.dot
$ dot -Tpng out.dot -o graph.png

.. note::

The ``dot`` command is part of Graphviz. You can download it and read
more about it on `Graphviz.org`_.

.. _Graphviz.org: http://www.graphviz.org
197 changes: 197 additions & 0 deletionsworkflow/state-machines.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
..index::
single: Workflow; Workflows as State Machines

Workflows as State Machines
===========================

The workflow component is modelled after a *Workflow net* which is a subclass
of a `Petri net`_. By adding further restrictions you can get a state machine.
The most important one being that a state machine cannot be in more than
one place simultaneously. It is also worth noting that a workflow does not
commonly have cyclic path in the definition graph, but it is common for a state
machine.

Example of a State Machine
--------------------------

A pull request starts in an intial "start" state, a state for e.g. running
tests on Travis. When this is finished, the pull request is in the "review"
state, where contributors can require changes, reject or accept the
pull request. At any time, you can also "update" the pull request, which
will result in another Travis run.

..image::/_images/components/workflow/pull_request.png

Below is the configuration for the pull request state machine.

..configuration-block::

..code-block::yaml
# app/config/config.yml
framework:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

please add# app/config/config.yml

workflows:
pull_request:
type:'state_machine'
supports:
-AppBundle\Entity\PullRequest
places:
-start
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I've started with many comments, so here a resume of what I suggest for the following:

pull_request:type:'state_machine'supports:        -AppBundle\Entity\PullRequestplaces:        -started        -coding        -travis        -needs_review        -reviewed        -merged        -closedtransitions:test:from:[started, coding]to:travissubmit:from:travisto:needs_reviewrequest_change:from:[travis, needs_review, reviewed]to:codingaccept:from:needs_reviewto:reviewedreject:from:[coding, needs_review, reviewed]to:closedreopen:from:closedto:needs_reviewmerge:from:reviewedto:merged

Wdyt?

Actually when trying to dump it I've found a bug and submittedsymfony/symfony#20497 :)

-coding
-travis
-review
-merged
-closed
transitions:
submit:
from:start
to:travis
update:
from:[coding, travis, review]
to:travis
wait_for_reivew:
from:travis
to:review
request_change:
from:review
to:coding
accept:
from:review
to:merged
reject:
from:review
to:closed
reopen:
from:closed
to:review
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

please add XML and PHP formats.

<!-- app/config/config.xml--><?xml version="1.0" encoding="utf-8" ?><containerxmlns="http://symfony.com/schema/dic/services"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:framework="http://symfony.com/schema/dic/symfony"xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd        http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">    <framework:config>        <framework:workflowname="pull_request"type="state_machine">            <framework:marking-storetype="scalar"/>            <framework:support>AppBundle\Entity\PullRequest</framework:support>            <framework:place>start</framework:place>            <framework:place>coding</framework:place>            <framework:place>travis</framework:place>            <framework:place>review</framework:place>            <framework:place>merged</framework:place>            <framework:place>closed</framework:place>            <framework:transitionname="submit">                <framework:from>start</framework:from>                <framework:to>travis</framework:to>            </framework:transition>            <framework:transitionname="update">                <framework:from>coding</framework:from>                <framework:from>travis</framework:from>                <framework:from>review</framework:from>                <framework:to>travis</framework:to>            </framework:transition>            <framework:transitionname="wait_for_review">                <framework:from>travis</framework:from>                <framework:to>review</framework:to>            </framework:transition>            <framework:transitionname="change_needed">                <framework:from>review</framework:from>                <framework:to>coding</framework:to>            </framework:transition>            <framework:transitionname="accepted">                <framework:from>review</framework:from>                <framework:to>merged</framework:to>            </framework:transition>            <framework:transitionname="rejected">                <framework:from>review</framework:from>                <framework:to>closed</framework:to>            </framework:transition>            <framework:transitionname="reopened">                <framework:from>closed</framework:from>                <framework:to>review</framework:to>            </framework:transition>        </framework:workflow>    </framework:config></container>

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thank you. Im embarrassingly bad at the XML syntax for the config.

..code-block::xml
<!-- app/config/config.xml-->
<?xml version="1.0" encoding="utf-8" ?>
<containerxmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"
>
<framework:config>
<framework:workflowname="pull_request"type="state_machine">
<framework:marking-storetype="single_state"/>
<framework:support>AppBundle\Entity\PullRequest</framework:support>
<framework:place>start</framework:place>
<framework:place>coding</framework:place>
<framework:place>travis</framework:place>
<framework:place>review</framework:place>
<framework:place>merged</framework:place>
<framework:place>closed</framework:place>
<framework:transitionname="submit">
<framework:from>start</framework:from>
<framework:to>travis</framework:to>
</framework:transition>
<framework:transitionname="update">
<framework:from>coding</framework:from>
<framework:from>travis</framework:from>
<framework:from>review</framework:from>
<framework:to>travis</framework:to>
</framework:transition>
<framework:transitionname="wait_for_review">
<framework:from>travis</framework:from>
<framework:to>review</framework:to>
</framework:transition>
<framework:transitionname="request_change">
<framework:from>review</framework:from>
<framework:to>coding</framework:to>
</framework:transition>
<framework:transitionname="accept">
<framework:from>review</framework:from>
<framework:to>merged</framework:to>
</framework:transition>
<framework:transitionname="reject">
<framework:from>review</framework:from>
<framework:to>closed</framework:to>
</framework:transition>
<framework:transitionname="reopen">
<framework:from>closed</framework:from>
<framework:to>review</framework:to>
</framework:transition>
</framework:workflow>
</framework:config>
</container>
..code-block::php
// app/config/config.php
$container->loadFromExtension('framework', array(
// ...
'workflows' => array(
'pull_request' => array(
'type' => 'state_machine',
'supports' => array('AppBundle\Entity\PullRequest'),
'places' => array(
'start',
'coding',
'travis',
'review',
'merged',
'closed',
),
'transitions' => array(
'start'=> array(
'form' => 'start',
'to' => 'travis',
),
'update'=> array(
'form' => array('coding','travis','review'),
'to' => 'travis',
),
'wait_for_reivew'=> array(
'form' => 'travis',
'to' => 'review',
),
'request_change'=> array(
'form' => 'review',
'to' => 'coding',
),
'accept'=> array(
'form' => 'review',
'to' => 'merged',
),
'reject'=> array(
'form' => 'review',
'to' => 'closed',
),
'reopen'=> array(
'form' => 'start',
'to' => 'review',
),
),
),
),
));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

multiple blank lines should always be just one

You can now use this state machine by getting the ``state_machine.pull_request`` service::

$stateMachine = $this->container->get('state_machine.pull_request');
Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Ping@rufinus. Thank you for the feedback. I've added this example now.


.. _Petri net:https://en.wikipedia.org/wiki/Petri_net
Loading

[8]ページ先頭

©2009-2025 Movatter.jp