zerodahero / laravel-workflow Goto Github PK
View Code? Open in Web Editor NEWThis project forked from brexis/laravel-workflow
Use the Symfony Workflow component in Laravel
License: MIT License
This project forked from brexis/laravel-workflow
Use the Symfony Workflow component in Laravel
License: MIT License
Hi,
please review this issue with Symfony. Problem details are already explained there.
In review - they have inspected my bug report and could not reproduce it in vanilla Symfony install so their best guess is that the problem is in our event dispatcher. Could you please check?
In any workflow subscriber when calling $event->stopPropagation();
it does nothing. All further events are called.
Hello,
I use your workflow config file example (be careful, 2 comma are missing). and other fields example.
I have the message :
"The method "App\Models\BlogPost::getMarking()" does not exist." when I do that :
$post = BlogPost::find(1);
$workflow = $post->workflow_get();
$marking = $workflow->getMarking($post);
The property is 'currentPlace' in the config file but in the workflow, I show it is "marking"
$post = BlogPost::find(1);
$workflow = $post->workflow_get();
dd($workflow);
-markingStore: Symfony\Component\Workflow\MarkingStore\MethodMarkingStore {#364
-singleState: false
-property: "marking"
}
-dispatcher: Symfony\Component\EventDispatcher\EventDispatcher {#331 …3}
-name: "straight"
}
I have a field 'currentPlace in my database, I added another field ('marking') but I have always the same error message .
What is the full path of "use Workflow ;" ? I think my app don't find the good way.
I use Laravel 7. It use symfony workflow 5.0.,
I am wondering whether this behaviour is intentional. I have been debugging an issue in my project and I noticed that when applying a workflow like so:
$this->workflow_apply('prepare', 'order_shipping_states_graph');
Whereby the workflow has defined:
'prepare' => [
'from' => [ 'ready', 'being_prepared']
'to' => ['being_prepared']
],
'pick' => [
from => ['being_prepared']
to => ['ready_to_ship']
]
Then both guardPrepare
and guardPick
are being executed in the respective workflow subscriber.
I would expect that since there is the transition specified, then only that guard would execute.
sorry wrong post
Events are dispatched twice - first w/o name then with name. Is this intentional?
Only need my event listener to fire once, but get it multiple times.
Hi,
That's perhaps a little linked with #12 ...
In my application, Post objects are associated to some statuses thanks to a MorphToMany relationship (since not only Post can have statuses, but many other objects).
So I was thinking it is a little redondant to define a "marking" field on my Post model whereas the information already exists in a pivot table (morphToMany) ...
That's when the marking_store like a method could be interesting
'marking_store' => [
'type' => 'method'
'property' => 'status'
],
and on the Post model I would imagine the two getter and setter (à la Symfony)
public function getStatus(){
return $this->statusable()->first();
}
public function setStatus($status){
return $this->statusable()->sync($status)
}
But if I write this ticket, it is above all to see if you had other ideas to suggest to me for this problem?
Thanks
Hi,
I have the following test model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use ZeroDaHero\LaravelWorkflow\Traits\WorkflowTrait;
class Test extends Model
{
use HasFactory;
use WorkflowTrait;
protected $table = 'test';
protected $casts = [
'marking' => 'array',
];
}
Workflow:
'test' => [
'type' => 'workflow',
// 'marking_store' => [
// 'type' => 'multiple_state',
// ],
'supports' => [
Test::class,
],
'events_to_dispatch' => [
'workflow.announce',
],
'places' => [
'a', 'b', 'c',
],
'initial_places' => [
'a',
],
'transitions' => [
't1' => [
'from' => 'a',
'to' => 'b'
],
't2' => [
'from' => 'b',
'to' => 'c'
],
],
];
Event subscriber:
<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use Symfony\Component\Workflow\Event\AnnounceEvent;
use ZeroDaHero\LaravelWorkflow\Events\GuardEvent;
class TestSubscriber implements ShouldQueue
{
public function handleAnnounce($type, $event)
{
Log::debug('* Received Event: ' . $type);
Log::debug(gettype($event));
}
public function subscribe($events)
{
$events->listen(
'workflow.test.*',
[TestSubscriber::class, 'handleAnnounce']
);
}
}
And the following testing code:
Log::debug('---');
$test = new Test();
Log::debug('Checking transition t1: ' . $test->workflow_can('t1'));
Log::debug('Current marking: ' . $test->marking);
foreach ($test->workflow_transitions() as $transition) {
Log::debug('Enabled Transition: ' . $transition->getName());
}
Log::debug('Applying transition t1:');
$marking = $test->workflow_apply('t1');
return 0;
What I expect is to receive the event somehow so I can process it.
All of the above was discovered when I am trying to receive Announce events, in order to make automatic transitions when possible. So far I have discovered that they are not fired at all. This is issue 1.
According to current documentation, the handler in subscriber should receive Event as first argument.
Actually it receives Event only in the case when subscriber is subscribed to ZeroDaHero Events.
If subscribed to Symfony dot-style events (as in the example above), function receives string containing the event name and second parameter of type array, that contains dump of the ZeroDaHero Event. This is issue 2.
I believe this is related to latest changes in Symfony/Workflow 5.2.
here is the debug information from above code:
[2021-01-21 16:22:57] local.DEBUG: ---
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.entered
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard.t1
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: Checking transition t1: 1
[2021-01-21 16:22:57] local.DEBUG: Current marking: a
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard.t1
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: Enabled Transition: t1
[2021-01-21 16:22:57] local.DEBUG: Applying transition t1:
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard.t1
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.leave
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.leave.a
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.transition
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.transition.t1
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.enter
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.enter.b
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.entered
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.entered.b
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.completed
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.completed.t1
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard
[2021-01-21 16:22:57] local.DEBUG: array
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard.t2
[2021-01-21 16:22:57] local.DEBUG: array
"symfony/workflow": "^5.2",
"zerodahero/laravel-workflow": "^3.2"
Hello I am testing the library to make an integration, in which I intend to save all the transactions performed in the flow. But I got an unexpected behavior, and it is that when I listen to the onCompleted event, it is called three times.
This would be problematic because it would duplicate the records by three.
I have checked the code to see if I can contribute, but I don't see the problem.
workflow.php
<?php
use App\Models\Document;
return [
'document_management' => [
'type' => 'state_machine',
'marking_store' => [
'type' => 'single_state',
'property' => 'workflow',
],
'supports' => [
Document::class
],
'places' => [
'draft',
'review',
'rejected',
'published'
],
'transitions' => [
'to_review' => [
'from' => 'draft',
'to' => 'review',
'metadata' => [
'priority' => 0.5,
]
],
'publish' => [
'from' => 'review',
'to' => 'published'
],
'reject' => [
'from' => 'review',
'to' => 'rejected'
]
],
'events_to_dispatch' => [
Symfony\Component\Workflow\WorkflowEvents::LEAVE,
],
],
];
DocumentWorkflowSubscribe.php
<?php
namespace App\Listeners;
use ZeroDaHero\LaravelWorkflow\Events\LeaveEvent;
class DocumentWorkflowSubscriber
{
/**
* Handle workflow entered event.
*/
public function onLeave(LeaveEvent $event) {
$subject = $event->getSubject();
var_dump($subject->workflow);
}
/**
* Register the listeners for the subscriber.
*
* @param Illuminate\Events\Dispatcher $events
*/
public function subscribe(\Illuminate\Events\Dispatcher $events)
{
$events->listen(LeaveEvent::class, [DocumentWorkflowSubscriber::class, 'onLeave']);
}
}
Tinker shell
>>> $document->workflow_apply('to_review');
/var/www/html/app/Listeners/DocumentWorkflowSubscriber.php:16:
string(5) "draft"
/var/www/html/app/Listeners/DocumentWorkflowSubscriber.php:16:
string(5) "draft"
/var/www/html/app/Listeners/DocumentWorkflowSubscriber.php:16:
string(5) "draft"
=> Symfony\Component\Workflow\Marking {#4443}
>>>
Trying to get model transitions:
$transitions = $model->workflow_transitions();
But it's throwing an error. Here is my setup
config/workflow.php
return [
'requisitions' => [
'type' => 'workflow',
'metadata' => [
'title' => 'Requisition Workflow',
],
'marking_store' => [
'type' => 'multiple_state',
'arguments' => ['status'],
],
'supports' => ['App\Models\WorkOrder'],
'initial_marking' => 'draft',
'places' => ['draft', 'pending', 'quotation', 'procurement', 'lpo', 'declined'],
'transitions' => [
'submit' => [
'from' => 'draft',
'to' => 'pending',
],
'approve-work-orders-quotation' => [
'from' => 'pending',
'to' => 'quotation',
],
'approve-work-orders-procurement' => [
'from' => 'quotation',
'to' => 'procurement',
],
'generate-work-orders-lpo' => [
'from' => 'procurement',
'to' => 'lpo',
],
'reject-work-order' => [
'from' => 'procurement',
'to' => 'declined',
],
],
]
];
What am I doing wrong?
Is it possible to define the workflow inside the model?
I'm currently executing
Workflow::get($post, $workflowName);
Is it possible to do something like this
$post->workflow_get($workflowName)
$post->refresh();
This way I don't have to load Workflow into the controller, and just the model itself.
Meanwile it works great! Good job!
my config like this
'places' => [ 0, 1, 2, 4, ],
place 0 does not work because of this line
maybe here you need to do it differently.
like
if (! $marking && $marking !== 0) { return new Marking(); }
I am facing multiple dispatching (3 times exactly) of a same event when using workflow_apply()
method.
I'm using version 3.3.3 and here is the config of my workflow.
use App\Constants\UserTypes;
use App\Models\Factor;
'factor_wf' => [
'type' => 'state_machine',
'marking_store' => [
'type' => 'single_state',
'property' => 'status',
],
'supports' => [Factor::class],
'places' => ['open', 'submit'],
'initial_places' => ['open'],
'transitions' => [
'to_submit_by_State' => [
'from' => 'open',
'to' => 'submit',
'metadata' => [
'permission' => UserTypes::getWorkflowPermission(UserTypes::State),
],
],
]
]
Here is the subscriber.
use ZeroDaHero\LaravelWorkflow\Events\CompletedEvent;
class FactorWorkflowSubscriber
{
public function onCompleted(CompletedEvent $event)
{
if ($event->getWorkflowName() == 'factor_wf') {
(new HandleFactorWorkflow($event->getOriginalEvent()))->handle();
}
}
public function subscribe($events)
{
return [
CompletedEvent::class => 'onCompleted',
];
}
}
Note that when I use workflow.completed
instead of CompleteEvent
namespace, it resolves and I don't get repetitive dispatching.
This issue is a continuation of this.
Hello,
I have tried to define a listener with second parameter of arbitrary type, using dependency injection.
Attempt to call it fails because the listener function is called with one parameter only (the type of Event).
is it possible to add support for dependency injection?
Hello,
I know event and listener with laravel, but I don't understand how use BlogPostWorkflowSubscriber.
How to subscribe to call onleave function for example.
Could someone give a full example, please ?
Fabien
Hi,
Is there Example project for creating workflow engine in laravel via this package Like This for symfony ?
I don't understand how to use state machine and events .
Thanks For great Supports.
composer require zerodahero/laravel-workflow:2.1.0
gives me this for Laravel 6
Package manifest generated successfully.
@php artisan ide-helper:generate
Symfony\Component\Debug\Exception\FatalThrowableError : Argument 1 passed to ZeroDaHero\LaravelWorkflow\WorkflowRegistry::__construct() must be of the type array, null given, called in \laravel_test\vendor\zerodahero\laravel-workflow\src\WorkflowServiceProvider.php on line 48
at \laravel_test\vendor\zerodahero\laravel-workflow\src\WorkflowRegistry.php:59
55| * @param array $config
56| * @param array $registryConfig
57| * @throws \ReflectionException
58| */
59| public function __construct(array $config, array $registryConfig = null)
60| {
61| $this->registry = new Registry();
62| $this->config = $config;
63| $this->registryConfig = $registryConfig ?? $this->getDefaultRegistryConfig();
Exception trace:
1 ZeroDaHero\LaravelWorkflow\WorkflowRegistry::__construct([])
\laravel_test\vendor\zerodahero\laravel-workflow\src\WorkflowServiceProvider.php:48
2 ZeroDaHero\LaravelWorkflow\WorkflowServiceProvider::ZeroDaHero\LaravelWorkflow{closure}(Object(Illuminate\Foundation\Application), [])
\laravel_test\vendor\laravel\framework\src\Illuminate\Container\Container.php:799
Please use the argument -v to see more details.
Script @php artisan ide-helper:generate handling the post-autoload-dump event returned with error code 1
Installation failed, reverting ./composer.json to its original content.
Hi, can you help me?
$workflow = Workflow::get($order, 'order'); //works
$m = $workflow->getMarking($order); //raises an error
"message": "Argument 1 passed to Symfony\Component\Workflow\Marking::__construct() must be of the type array, string given, called in /app/vendor/zerodahero/laravel-workflow/src/MarkingStores/EloquentMarkingStore.php on line 44",
"exception": "TypeError",
"file": "/app/vendor/symfony/workflow/Marking.php",
"line": 26,
"trace": [
{
"file": "/app/vendor/zerodahero/laravel-workflow/src/MarkingStores/EloquentMarkingStore.php",
"line": 44,
"function": "__construct",
"class": "Symfony\Component\Workflow\Marking",
"type": "->"
},
{
Hi again,
I have stumbled upon this error:
[2021-02-06 17:02:46] local.ERROR: unserialize(): Error at offset 3683 of 3922 bytes {"exception":"[object] (ErrorException(code: 0): unserialize(): Error at offset 3683 of 3922 bytes at /Users/sag/Dropbox/code/api_v3/vendor/zerodahero/laravel-workflow/src/Events/BaseEvent.php:56)
[stacktrace]
#0 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(8, 'unserialize(): ...', '/Users/sag/Drop...', 56, Array)
#1 /Users/sag/Dropbox/code/api_v3/vendor/zerodahero/laravel-workflow/src/Events/BaseEvent.php(56): unserialize('O:37:\"Modules\\\\B...')
#2 [internal function]: ZeroDaHero\\LaravelWorkflow\\Events\\BaseEvent->unserialize('a:5:{s:16:\"base...')
#3 /Users/sag/Dropbox/code/api_v3/vendor/cloudcreativity/laravel-json-api/src/Queue/UpdateClientProcess.php(64): unserialize('O:36:\"Illuminat...')
#4 /Users/sag/Dropbox/code/api_v3/vendor/cloudcreativity/laravel-json-api/src/Queue/UpdateClientProcess.php(37): CloudCreativity\\LaravelJsonApi\\Queue\\UpdateClientProcess->deserialize(Object(Illuminate\\Queue\\Jobs\\RedisJob))
#5 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(412): CloudCreativity\\LaravelJsonApi\\Queue\\UpdateClientProcess->handle(Object(Illuminate\\Queue\\Events\\JobFailed))
#6 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(237): Illuminate\\Events\\Dispatcher->Illuminate\\Events\\{closure}('Illuminate\\\\Queu...', Array)
#7 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(195): Illuminate\\Events\\Dispatcher->dispatch('Illuminate\\\\Queu...')
#8 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(544): Illuminate\\Queue\\Jobs\\Job->fail(Object(ErrorException))
#9 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(505): Illuminate\\Queue\\Worker->failJob(Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(ErrorException))
#10 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(433): Illuminate\\Queue\\Worker->markJobAsFailedIfWillExceedMaxAttempts('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), 1, Object(ErrorException))
#11 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(410): Illuminate\\Queue\\Worker->handleJobException('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(Illuminate\\Queue\\WorkerOptions), Object(ErrorException))
#12 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(356): Illuminate\\Queue\\Worker->process('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(Illuminate\\Queue\\WorkerOptions))
#13 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(307): Illuminate\\Queue\\Worker->runJob(Object(Illuminate\\Queue\\Jobs\\RedisJob), 'redis', Object(Illuminate\\Queue\\WorkerOptions))
#14 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(116): Illuminate\\Queue\\Worker->runNextJob('redis', 'bsms', Object(Illuminate\\Queue\\WorkerOptions))
#15 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(100): Illuminate\\Queue\\Console\\WorkCommand->runWorker('redis', 'bsms')
#16 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\\Queue\\Console\\WorkCommand->handle()
#17 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/Util.php(40): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#18 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure(Object(Closure))
#19 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\\Container\\BoundMethod::callBoundMethod(Object(Illuminate\\Foundation\\Application), Array, Object(Closure))
#20 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/Container.php(610): Illuminate\\Container\\BoundMethod::call(Object(Illuminate\\Foundation\\Application), Array, Array, NULL)
#21 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Command.php(136): Illuminate\\Container\\Container->call(Array)
#22 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Command/Command.php(256): Illuminate\\Console\\Command->execute(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
#23 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Command.php(121): Symfony\\Component\\Console\\Command\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
#24 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(971): Illuminate\\Console\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#25 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(290): Symfony\\Component\\Console\\Application->doRunCommand(Object(Illuminate\\Queue\\Console\\WorkCommand), Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#26 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(166): Symfony\\Component\\Console\\Application->doRun(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#27 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Application.php(93): Symfony\\Component\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#28 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(129): Illuminate\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#29 /Users/sag/Dropbox/code/api_v3/artisan(37): Illuminate\\Foundation\\Console\\Kernel->handle(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#30 {main}
[previous exception] [object] (ErrorException(code: 0): unserialize(): Error at offset 3683 of 3922 bytes at /Users/sag/Dropbox/code/api_v3/vendor/zerodahero/laravel-workflow/src/Events/BaseEvent.php:56)
[stacktrace]
#0 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(8, 'unserialize(): ...', '/Users/sag/Drop...', 56, Array)
#1 /Users/sag/Dropbox/code/api_v3/vendor/zerodahero/laravel-workflow/src/Events/BaseEvent.php(56): unserialize('O:37:\"Modules\\\\B...')
#2 [internal function]: ZeroDaHero\\LaravelWorkflow\\Events\\BaseEvent->unserialize('a:5:{s:16:\"base...')
#3 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(95): unserialize('O:36:\"Illuminat...')
#4 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(251): Illuminate\\Queue\\CallQueuedHandler->getCommand(Array)
#5 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(213): Illuminate\\Queue\\CallQueuedHandler->failed(Array, Object(ErrorException), '7dada2bb-c2f3-4...')
#6 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(192): Illuminate\\Queue\\Jobs\\Job->failed(Object(ErrorException))
#7 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(544): Illuminate\\Queue\\Jobs\\Job->fail(Object(ErrorException))
#8 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(505): Illuminate\\Queue\\Worker->failJob(Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(ErrorException))
#9 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(433): Illuminate\\Queue\\Worker->markJobAsFailedIfWillExceedMaxAttempts('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), 1, Object(ErrorException))
#10 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(410): Illuminate\\Queue\\Worker->handleJobException('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(Illuminate\\Queue\\WorkerOptions), Object(ErrorException))
#11 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(356): Illuminate\\Queue\\Worker->process('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(Illuminate\\Queue\\WorkerOptions))
#12 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(307): Illuminate\\Queue\\Worker->runJob(Object(Illuminate\\Queue\\Jobs\\RedisJob), 'redis', Object(Illuminate\\Queue\\WorkerOptions))
#13 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(116): Illuminate\\Queue\\Worker->runNextJob('redis', 'bsms', Object(Illuminate\\Queue\\WorkerOptions))
#14 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(100): Illuminate\\Queue\\Console\\WorkCommand->runWorker('redis', 'bsms')
#15 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\\Queue\\Console\\WorkCommand->handle()
#16 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/Util.php(40): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#17 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure(Object(Closure))
#18 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\\Container\\BoundMethod::callBoundMethod(Object(Illuminate\\Foundation\\Application), Array, Object(Closure))
#19 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/Container.php(610): Illuminate\\Container\\BoundMethod::call(Object(Illuminate\\Foundation\\Application), Array, Array, NULL)
#20 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Command.php(136): Illuminate\\Container\\Container->call(Array)
#21 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Command/Command.php(256): Illuminate\\Console\\Command->execute(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
#22 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Command.php(121): Symfony\\Component\\Console\\Command\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
#23 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(971): Illuminate\\Console\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#24 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(290): Symfony\\Component\\Console\\Application->doRunCommand(Object(Illuminate\\Queue\\Console\\WorkCommand), Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#25 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(166): Symfony\\Component\\Console\\Application->doRun(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#26 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Application.php(93): Symfony\\Component\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#27 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(129): Illuminate\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#28 /Users/sag/Dropbox/code/api_v3/artisan(37): Illuminate\\Foundation\\Console\\Kernel->handle(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#29 {main}
"}
I am trying to process Queued subscriber the same way as I have already did with many others. But for some reason only this subscriber is failing. There is nothing different in model, workflow definition, nor subscriber. I have recorded the serialized data in BaseEvent and then manually unserialized it without problem.
Processing the events in synchronous manner does not reproduce the problem (removing implements ShouldQueue
from subscriber definition) but I want to process it in queue.
Can you help? I am sure something is different and I am overlooking it, but I can't find the problem by myself.
workflow definition:
'bsmsDlrOutgoing' => [
'supports' => [
OutgoingDlr::class,
],
'places' => [
'new',
'processing',
],
'initial_places' => [
'new'
],
'transitions' => [
'toProcessing' => [
'from' => 'new',
'to' => 'processing',
],
],
],
model definition:
<?php
namespace Modules\BSMS\Entities\Cdr;
use Illuminate\Database\Eloquent\Model;
use Modules\BSMS\Entities\Route\Provider\Provider;
use ZeroDaHero\LaravelWorkflow\Traits\WorkflowTrait;
class OutgoingDlr extends Model
{
use WorkflowTrait;
protected $table = 'api_v3_bsms.cdr_out_dlr';
protected $fillable = [
'data',
];
protected $casts = [
'marking' => 'array',
'data' => 'array',
];
public function message()
{
return $this->belongsTo(Outgoing::class, 'cdr_out_id');
}
public function provider()
{
return $this->belongsTo(Provider::class, 'provider_id');
}
}
subscriber:
<?php
namespace Modules\BSMS\Listeners;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use ZeroDaHero\LaravelWorkflow\Events\EnteredEvent;
class OutgoingDlrAsyncSubscriber implements ShouldQueue
{
use InteractsWithQueue;
public $queue = 'bsms';
public $tries = 1;
public $maxExceptions = 1;
public $timeout = 20;
public function anyAny($name, array $payload)
{
Log::debug('Received event: ' . $name);
// $event = $payload[0];
// $subject = $event->getSubject();
}
public function enteredProcessing(EnteredEvent $event)
{
$subject = $event->getSubject();
$subject->save();
}
public function subscribe(Dispatcher $events)
{
$events->listen('workflow.bsmsDlrOutgoing.*.*', [self::class, 'anyAny']);
// $events->listen('workflow.bsmsDlrOutgoing.entered.processing', [self::class, 'enteredProcessing']);
}
}
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Conclusion: remove laravel/framework v6.18.3
- Conclusion: don't install laravel/framework v6.18.3
- litepie/workflow 1.0.0 requires illuminate/console 5.6.* -> satisfiable by laravel/framework[5.6.x-dev], illuminate/console[5.6.x-dev, v5.6.0, v5.6.1, v5.6.10, v5.6.11, v5.6.12, v5.6.13, v5.6.14, v5.6.15, v5.6.16, v5.6.17, v5.6.19, v5.6.2, v5.6.20, v5.6.21, v5.6.22, v5.6.23, v5.6.24, v5.6.26, v5.6.27, v5.6.28, v5.6.29, v5.6.3, v5.6.30, v5.6.31, v5.6.32, v5.6.33, v5.6.34, v5.6.35, v5.6.36, v5.6.37, v5.6.38, v5.6.39, v5.6.4, v5.6.5, v5.6.6, v5.6.7, v5.6.8, v5.6.9].
- litepie/workflow 1.0.x-dev requires illuminate/console 5.6.* -> satisfiable by laravel/framework[5.6.x-dev], illuminate/console[5.6.x-dev, v5.6.0, v5.6.1, v5.6.10, v5.6.11, v5.6.12, v5.6.13, v5.6.14, v5.6.15, v5.6.16, v5.6.17, v5.6.19, v5.6.2, v5.6.20, v5.6.21, v5.6.22, v5.6.23, v5.6.24, v5.6.26, v5.6.27, v5.6.28, v5.6.29, v5.6.3, v5.6.30, v5.6.31, v5.6.32, v5.6.33, v5.6.34, v5.6.35, v5.6.36, v5.6.37, v5.6.38, v5.6.39, v5.6.4, v5.6.5, v5.6.6, v5.6.7, v5.6.8, v5.6.9].
- Can only install one of: laravel/framework[5.6.x-dev, v6.18.3].
- don't install illuminate/console 5.6.x-dev|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.0|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.1|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.10|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.11|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.12|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.13|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.14|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.15|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.16|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.17|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.19|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.2|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.20|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.21|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.22|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.23|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.24|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.26|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.27|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.28|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.29|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.3|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.30|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.31|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.32|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.33|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.34|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.35|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.36|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.37|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.38|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.39|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.4|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.5|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.6|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.7|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.8|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.9|don't install laravel/framework v6.18.3
- Installation request for laravel/framework (locked at v6.18.3, required as ^6.3) -> satisfiable by laravel/framework[v6.18.3].
- Installation request for litepie/workflow ^1.0 -> satisfiable by litepie/workflow[1.0.0, 1.0.x-dev].
Laravel: 6.18.3
PHP: 7.4.2
Environment:
Laravel Framework version 7.12.0;
"zerodahero/laravel-workflow": "3.0";
This is my code and error report:
Tips: I also found some code in (https://symfony.com/doc/current/workflow.html#installation)
### Do I need to add the code myself? I don't see these methods in the example
I am a novice. Please tell me this!
@zerodahero
If DispatcherAdapter::translateEvent(...)
is unable to determine the event to map to, it just simply returns the Symfony event instead of an event which extends ZeroDaHero\LaravelWorkflow\Events\BaseEvent
.
This causes the application to fail with the error Serialization of 'Closure' is not allowed.
if a registered event listener implements the Illuminate\Contracts\Queue\ShouldQueue
interface as the Symfony event contains Clousures and Laravel's queuing mechanism will always attempt to serialise the job.
One way to trigger this issue is to use a dot .
character in the configured workflow name, such as straight.test
.
There are a few potential solutions for this, but possibly parsing out the workflow name from the event name might be the best option (assuming that's feasible). Alternatively, disabling support for workflows with dot characters in their name is another viable option, although would be a breaking change.
Regardless of which solution is implemented, calls to DispatcherAdapter::translateEvent(...)
should also ensure that they don't return Symfony events.
WorkflowTrait:workflow_transitions should be
public function workflow_transitions($workflow = null)
{
return Workflow::get($this, $workflow)->getEnabledTransitions($this);
}
I'm in a team that we are using your software to manage a workflow. A partner created the workflow and tested in a call and all it works!! But when I pulled the branch where there the code that works and then typed in console composer install
to download the lib, in my side didn't work, Laravel shows
Argument 1 passed to ZeroDaHero\LaravelWorkflow\WorkflowRegistry::__construct() must be of the type array, null given, called in /var/www/html/vendor/zerodahero/laravel-workflow/src/WorkflowServiceProvider.php
The different here is the error say ...null given...
Notes:
php artisan workflow:dump workflow_name --format=jpg
Exception : Workflow workflow_name is not configured.
at /var/www/html/laravel/zerodahero/vendor/zerodahero/laravel-workflow/src/Commands/WorkflowDumpCommand.php:49
45| $class = $this->option('class');
46| $config = Config::get('workflow');
47|
48| if (!isset($config[$workflowName])) {
49| throw new Exception("Workflow $workflowName is not configured.");
50| }
51|
52| if (false === array_search($class, $config[$workflowName]['supports'])) {
53| throw new Exception("Workflow $workflowName has no support for class $class.".
Exception trace:
1 ZeroDaHero\LaravelWorkflow\Commands\WorkflowDumpCommand::handle()
/var/www/html/laravel/zerodahero/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32
2 call_user_func_array([])
/var/www/html/laravel/zerodahero/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32
Please use the argument -v to see more details.
hey !
i'm using this command php artisan workflow:dump workflow_name --class App\\BlogPost
to generate a workflow image,
the output folder is alwayse the root folder of my project, but i want to put it inside storage/app/public
folder
how can i do it ? what changes i should make in WorkflowDumpCommand.php
file to be able to store the output image into storage/app/public
?
In order to install the package you need to stick with Workflow 4.x while there is 5.x release. have you considered updating?
Hi,
In case I want to use the trait and send context to transition, i have to use all three parameters to workflow_apply.
However second parameter is irrelevant, because the trait is directly applied to given model.
I propose to remove the second parameter and leave context to be second optional argument.
I suggest to remove from documentation and configuration files marking_store
because it is inferred based on workflow type. You can check check details here
While trying to recreate this example I run into a weird behavior:
'test' => [
'type' => 'workflow', // or 'state_machine'
'marking_store' => [
'type' => 'multiple_state', // or 'single_state'
'property' => 'delivery_workflow', // this is the property on the model
],
'supports' => ['App\Booking\Trip'],
'places' => ['draft', 'waiting for journalist', 'approved by journalist', 'wait for spellchecker', 'approved by spellchecker', 'published'],
'transitions' => [
'request review' => [
'from' => 'draft',
'to' => ['waiting for journalist', 'wait for spellchecker']
],
'journalist approval' => [
'from' => 'waiting for journalist',
'to' => 'approved by journalist'
],
'spellchecker approval' => [
'from' => 'wait for spellchecker',
'to' => 'approved by spellchecker'
],
'publish' => [
'from' => ['approved by journalist', 'approved by spellchecker'],
'to' => 'published'
],
],
],
After quick digging I found that it happens in WorkflowRegistry
Instead of simple
$transitionObj = new Transition($transitionName, $transition['from'], $transition['to']);
$builder->addTransition($transitionObj);
we can see this:
foreach ((array)$transition['from'] as $form) { //
$transitionObj = new Transition($transitionName, $form, $transition['to']);
$builder->addTransition($transitionObj);
if (isset($transition['metadata'])) {
$metadata['transitions']->attach($transitionObj, $transition['metadata']);
}
}
I believe this was done on purpose, but it doesn't look right. What's the back thinking behind this?
I know laravel depends on symfony http-kernel which in turn depends on event-dispatcher... even still, you might want to swap out the event-dispatcher package with the event-dispatcher-contracts package instead.
Just a thought.
diff --git a/composer.json b/composer.json
index f01d06d..777bcf5 100644
--- a/composer.json
+++ b/composer.json
@@ -5,9 +5,9 @@
"license": "MIT",
"require": {
"php": ">=7.2",
"symfony/workflow": "^5.0",
"symfony/process": "^5.0",
+ "symfony/event-dispatcher-contracts": "^2.4",
- "symfony/event-dispatcher": "^5.0",
"illuminate/console": "^7.1|^8.0",
"illuminate/support": "^7.1|^8.0",
"illuminate/contracts": "^7.1|^8.0"
diff --git a/src/WorkflowRegistry.php b/src/WorkflowRegistry.php
index b1894e3..c9337d8 100644
--- a/src/WorkflowRegistry.php
+++ b/src/WorkflowRegistry.php
@@ -3,7 +3,7 @@
namespace ZeroDaHero\LaravelWorkflow;
use Illuminate\Contracts\Events\Dispatcher as EventsDispatcher;
-use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Workflow\Definition;
use Symfony\Component\Workflow\DefinitionBuilder;
use Symfony\Component\Workflow\Exception\InvalidArgumentException;
@@ -37,7 +37,7 @@ class WorkflowRegistry
protected $registryConfig;
/**
- * @var EventDispatcher
+ * @var EventDispatcherInterface
*/
protected $dispatcher;
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Conclusion: remove laravel/framework v6.18.3
- Conclusion: don't install laravel/framework v6.18.3
- zerodahero/laravel-workflow 3.x-dev requires illuminate/contracts ^7.0 -> satisfiable by laravel/framework[7.x-dev], illuminate/contracts[7.x-dev, v7.0.0, v7.0.1, v7.0.2, v7.0.3, v7.0.4, v7.0.5, v7.0.6, v7.0.7, v7.0.8, v7.1.0, v7.1.1, v7.1.2, v7.1.3, v7.2.0, v7.2.1, v7.2.2, v7.3.0].
- zerodahero/laravel-workflow v3.0.0 requires illuminate/contracts ^7.0 -> satisfiable by laravel/framework[7.x-dev], illuminate/contracts[7.x-dev, v7.0.0, v7.0.1, v7.0.2, v7.0.3, v7.0.4, v7.0.5, v7.0.6, v7.0.7, v7.0.8, v7.1.0, v7.1.1, v7.1.2, v7.1.3, v7.2.0, v7.2.1, v7.2.2, v7.3.0].
- Can only install one of: laravel/framework[7.x-dev, v6.18.3].
- don't install illuminate/contracts 7.x-dev|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.0|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.1|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.2|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.3|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.4|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.5|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.6|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.7|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.8|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.1.0|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.1.1|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.1.2|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.1.3|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.2.0|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.2.1|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.2.2|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.3.0|don't install laravel/framework v6.18.3
- Installation request for laravel/framework (locked at v6.18.3, required as ^6.3) -> satisfiable by laravel/framework[v6.18.3].
- Installation request for zerodahero/laravel-workflow ^3.0 -> satisfiable by zerodahero/laravel-workflow[3.x-dev, v3.0.0].
Laravel: 6.18.3 PHP: 7.4.2
UPDATE: My questions are:
According to the documentation of Symfony https://symfony.com/doc/current/workflow.html#storing-metadata default Workflow marking store type is inferred based on workflow type. If it is workflow, marking store should be "multiple_state". Their recommendation is to not configure the type manually:
The marking store type could be “multiple_state” or “single_state”. A single state marking store does not support a model being on multiple places at the same time. This means a “workflow” must use a “multiple_state” marking store and a “state_machine” must use a “single_state” marking store. Symfony configures the marking store according to the “type” by default, so it’s preferable to not configure it.
A single state marking store uses a string to store the data. A multiple state marking store uses an array to store the data.
The marking_store.type (the default value depends on the type value) and property (default value ['marking']) attributes of the marking_store option are optional. If omitted, their default values will be used. It’s highly recommended to use the default value.
However based on my testing I have found out that default type is "single_state" even when using type workflow (btw. state_machine dumps the workflow with transitions in squares, not with labels above the arrow which makes me believe it is workflow, not state_machine). I have to explicitly set marking: multiple_state
if I need to support multiple places and avoid errors. At the same time type: state_machine|workflow
appears to be ignored at all.
'test' => [
'type' => 'workflow',
'supports' => [
Test::class,
],
'places' => [
'a', 'b', 'c',
'a1', 'b1', 'b2',
'a2', 'c1', 'c2',
],
'initial_places' => [
'a', 'a1', 'a2'
],
'transitions' => [
't1' => [
'from' => 'a',
'to' => 'b',
'metadata' => [
'priority' => 0.5,
],
],
't2' => [
'from' => 'b',
'to' => 'c'
],
't11' => [
'from' => 'a1',
'to' => 'b1'
],
't21' => [
'from' => 'b1',
'to' => 'c1'
],
't12' => [
'from' => 'a2',
'to' => 'b2'
],
't22' => [
'from' => 'b2',
'to' => 'c2'
],
],
Results:
Symfony\Component\Workflow\Exception\NotEnabledTransitionException
Transition "t11" is not enabled for workflow "test".
And this configuration:
'test' => [
'type' => 'state_machine', /// NOTE THIS ?
'marking_store' => [
'type' => 'multiple_state',
],
'supports' => [
Test::class,
],
'places' => [
'a', 'b', 'c',
'a1', 'b1', 'b2',
'a2', 'c1', 'c2',
],
'initial_places' => [
'a', 'a1', 'a2'
],
'transitions' => [
't1' => [
'from' => 'a',
'to' => 'b',
'metadata' => [
'priority' => 0.5,
],
],
't2' => [
'from' => 'b',
'to' => 'c'
],
't11' => [
'from' => 'a1',
'to' => 'b1'
],
't21' => [
'from' => 'b1',
'to' => 'c1'
],
't12' => [
'from' => 'a2',
'to' => 'b2'
],
't22' => [
'from' => 'b2',
'to' => 'c2'
],
],
works fine and moves the workflow into expected places.
Hi
when I try to use a workflow, I get an error like this:
Call to a member function getTos() on null
my config/workflow.php file :
<?php
return [
'straight' => [
'type' => 'workflow',
'marking_store' => [
'type' => 'multiple_state',
'arguments' => ['state']
],
'supports' => ["App\Task"],
'places' => ['draft', 'review', 'publish'],
'transitions' => [
'drafting' => [
'from' => 'draft',
'to' => 'review',
],
'reviewing' => [
'from' => 'review',
'to' => 'publish',
]
],
]
];
my Controller :
public function store(Request $request)
{
// validate the given request
$data = $this->validate($request, [
'title' => 'required|string|max:255',
]);
// create a new incomplete task with the given title
$task = Auth::user()->tasks()->create([
'title' => $data['title'],
]);
$task->workflow_apply('drafting');
// flash a success message to the session
session()->flash('status', 'Task Created!');
// redirect to tasks index
return redirect('/tasks');
}
how i can initialize state of my task when i create new task?
Hi,
I have event subscriber - guard function, that is defined using Symfony style. However the guard function is called with parameter that is of type ZeroDaHero\GuardEvent
, instead of type Symfony\GuardEvent
.
My believe is that if I subscribe using Symfony naming style of events, then I should receive Symfony events.
event subscriber:
use Symfony\Component\Workflow\Event\GuardEvent;
class WorkflowTestSubscriber
{
public function guard_t1(GuardEvent $event)
{
// $originalEvent = $event->getOriginalEvent();
print "\tGuard T1";
$subject = $event->getSubject();
$event->setBlocked(true, 'test blocking reason');
}
public function subscribe($events)
{
return [
// 'workflow.*' => 'test',
'workflow.straight.guard.t1' => 'guard_t1',
];
}
}
Error message:
TypeError
App\Listeners\WorkflowTestSubscriber::guard_t1(): Argument #1 ($event) must be of type Symfony\Component\Workflow\Event\GuardEvent, ZeroDaHero\LaravelWorkflow\Events\GuardEvent given, called in /Users/sag/Documents/code/zz_api/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php on line 424
非常感谢您的贡献,加油
Hi, I started:
composer require zerodahero/laravel-workflow
I get this error:
Argument 1 passed to ZeroDaHero\LaravelWorkflow\WorkflowRegistry::__construct() must be of the type array, null given, called in /app/vendor/zerodahero/laravel-workflow/src/WorkflowServiceProvider.php on line 49
we have a listener that dumps the events fired. There is extra entered.c
event emitted.
Transitions:
$this->info ('Apply T1');
$workflow->apply($model, 't1');
$this->warn(print_r ($model->marking, true));
$this->info ('Apply T4');
$workflow->apply($model, 't4');
$this->warn(print_r ($model->marking, true));
Output:
Apply T1
string(26) "workflow.straight.guard.t1"
string(25) "workflow.straight.leave.a"
string(31) "workflow.straight.transition.t1"
string(25) "workflow.straight.enter.b"
string(25) "workflow.straight.enter.c"
string(27) "workflow.straight.entered.b"
string(27) "workflow.straight.entered.c"
string(30) "workflow.straight.completed.t1"
string(26) "workflow.straight.guard.t4"
string(26) "workflow.straight.guard.t4"
string(29) "workflow.straight.announce.t4"
string(29) "workflow.straight.announce.t4"
Array
(
[b] => 1
[c] => 1
)
Apply T4
string(26) "workflow.straight.guard.t4"
string(26) "workflow.straight.guard.t4"
string(25) "workflow.straight.leave.b"
string(31) "workflow.straight.transition.t4"
string(25) "workflow.straight.enter.d"
string(27) "workflow.straight.entered.c"
string(27) "workflow.straight.entered.d"
string(30) "workflow.straight.completed.t4"
string(26) "workflow.straight.guard.t4"
string(29) "workflow.straight.announce.t4"
string(25) "workflow.straight.leave.c"
string(31) "workflow.straight.transition.t4"
string(25) "workflow.straight.enter.d"
string(27) "workflow.straight.entered.d"
string(30) "workflow.straight.completed.t4"
Array
(
[d] => 1
)
I have the following in EventServiceProvider:
class EventServiceProvider extends ServiceProvider { protected $listen = [ 'workflow.smsNotificationIncoming.transition.toAccepted' => [IncomingListener::class], ];
When transition is applied, fails with:
{
"message": "Serialization of 'Closure' is not allowed",
"exception": "Exception",
Hi all,
I'm really grateful for this package.
I am trying to recreate some twig/blade helpers from Symfony described here https://symfony.com/doc/current/workflow.html
I.e.:
function workflow_metadata($object, $meta, $place_or_transition)
{
$workflow = $object->workflow_get();
return $workflow->getMetadataStore()->getMetadata($meta,$place_or_transition);
}
...
but I need some help to create workflow_transition_blockers
to display current blocking message that prevent to apply "next" transition on a simple state_machine workflow.
Has someone already done it? or may help with some suggestion?
MY ROUTE
Route::get('/workflow', 'BlogPostController@index');
my composer.json
{
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"require": {
"php": "^7.1.3",
"fideloper/proxy": "^4.0",
"laravel/framework": "5.8.*",
"laravel/tinker": "^1.0",
"zerodahero/laravel-workflow": "^2.0"
},
"require-dev": {
"beyondcode/laravel-dump-server": "^1.0",
"filp/whoops": "^2.0",
"fzaninotto/faker": "^1.4",
"mockery/mockery": "^1.0",
"nunomaduro/collision": "^3.0",
"phpunit/phpunit": "^7.5"
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
},
"extra": {
"laravel": {
"dont-discover": []
}
},
"autoload": {
"psr-4": {
"App\": "app/"
},
"classmap": [
"database/seeds",
"database/factories"
]
},
"autoload-dev": {
"psr-4": {
"Tests\": "tests/"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"post-autoload-dump": [
"Illuminate\Foundation\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-root-package-install": [
"@php -r "file_exists('.env') || copy('.env.example', '.env');""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi"
]
}
}
MY MIGRATION BLOGPOST
`<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTableBlogPost extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('blogpost', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
$table->string('description');
$table->dateTime('currentPlace');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('blogpost');
}
}
`
INSERT INTO BLOGPOST
insert into blogpost(id,description,created_at,updated_at)values(1,'descripcion',now(),now());
MY CONTROLLER BLOGPOST
< ? php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Workflow;
use App\BlogPost;
class BlogPostController extends Controller
{
public function index()
{
$post = BlogPost::find(1);
$workflow = Workflow::get($post);
// if more than one workflow is defined for the BlogPost class
// $workflow = Workflow::get($post, $workflowName);
//$workflow->can($post, 'publish'); // False
$workflow->can($post, 'to_review'); // True
$transitions = $workflow->getEnabledTransitions($post);
// Apply a transition
$workflow->apply($post, 'to_review');
$post->save(); // Don't forget to persist the state
// Using the WorkflowTrait
$post->workflow_can('publish'); // True
//$post->workflow_can('to_review'); // False
// Get the post transitions
foreach ($post->workflow_transitions() as $transition) {
echo $transition->getName();
}
// Apply a transition
$post->workflow_apply('publish');
$post->save();
}
}
Hi,
From the Symfony documentation (https://symfony.com/doc/4.4/workflow.html#creating-a-workflow)
and from the Symfony blog (https://symfony.com/blog/new-in-symfony-4-3-workflow-improvements#simpler-configuration) you can see that they modify a little the marking_store
property in the config file.
framework:
workflows:
article:
type: workflow
marking_store:
type: method # This will be the default value in Symfony 5.0
property: marking # This is the default value, it could be omitted
task:
type: state_machine
marking_store:
type: method # This will be the default value in Symfony 5.0
property: state
And they add a new MethodMarkingStore
class that implements the MarkingStoreInterface
.
Unfortunately in your WorkflowRegistry
you set the marking_store with the getMarkingStoreInstance()
method which doesn't take into account those Symfony modifications.
protected function getMarkingStoreInstance(array $workflowData)
{
$markingStoreData = isset($workflowData['marking_store']) ? $workflowData['marking_store'] : [];
$arguments = isset($markingStoreData['arguments']) ? $markingStoreData['arguments'] : [];
if (isset($markingStoreData['class'])) {
$className = $markingStoreData['class'];
} elseif (isset($markingStoreData['type']) && $markingStoreData['type'] === 'multiple_state') {
$className = MultipleStateMarkingStore::class;
} else {
$className = SingleStateMarkingStore::class;
}
$class = new \ReflectionClass($className);
return $class->newInstanceArgs($arguments);
}
which means we can't use the new marking_store formalism.
Do you think you can have a look on this ?
Thank !
Hi,
does Anyone use this package in their project?
How to use symfony-workflow-events in project?
if anyone create project with this package, is it possible to publish example/project (open-source form) to understand how can we use events in the projects ?
Using version ^3.3 for zerodahero/laravel-workflow
./composer.json has been updated
Running composer update zerodahero/laravel-workflow
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- zerodahero/laravel-workflow[v3.3.0, ..., 3.x-dev] require symfony/event-dispatcher ^5.0 -> found symfony/event-dispatcher[v5.0.0-BETA1, ..., 5.4.x-dev] but the package is fixed to v6.0.3 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- zerodahero/laravel-workflow[v3.3.2, ..., v3.3.3] require symfony/event-dispatcher-contracts ^2.4 -> found symfony/event-dispatcher-contracts[v2.4.0, ..., 2.5.x-dev] but the package is fixed to v3.0.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
- Root composer.json requires zerodahero/laravel-workflow ^3.3 -> satisfiable by zerodahero/laravel-workflow[v3.3.0, ..., 3.x-dev].
Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require zerodahero/laravel-workflow:*" to figure out if any version is installable, or "composer require zerodahero/laravel-workflow:^2.1" if you know which you need.
Installation failed, reverting ./composer.json and ./composer.lock to their original content.
sag@Sag-MacBook-Pro-15 zz_api % composer require zerodahero/laravel-workflow -W
Using version ^3.3 for zerodahero/laravel-workflow
./composer.json has been updated
Running composer update zerodahero/laravel-workflow --with-all-dependencies
Loading composer repositories with package information
Updating dependencies
Lock file operations: 2 installs, 2 updates, 0 removals
- Upgrading klimenttoshkov/laravel-currency (dev-master 7a55352 => dev-master fd7c21c)
- Downgrading symfony/event-dispatcher-contracts (v3.0.0 => v2.5.0)
- Locking symfony/workflow (v5.4.3)
- Locking zerodahero/laravel-workflow (v3.3.3)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 2 installs, 2 updates, 0 removals
- Downloading symfony/event-dispatcher-contracts (v2.5.0)
- Downloading symfony/workflow (v5.4.3)
- Downloading zerodahero/laravel-workflow (v3.3.3)
- Downgrading symfony/event-dispatcher-contracts (v3.0.0 => v2.5.0): Extracting archive
- Upgrading klimenttoshkov/laravel-currency (dev-master 7a55352 => dev-master fd7c21c): Source already present
- Installing symfony/workflow (v5.4.3): Extracting archive
- Installing zerodahero/laravel-workflow (v3.3.3): Extracting archive
Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
Generating optimized autoload files
First of all, thank you for your work!
When I'm trying to persist the state, I'm getting the above error.
$workflow->apply($post, 'to_review');
$post->save();
//Result: Illuminate\Database\QueryException: SQLSTATE[42S22]: Column not found: 1054Unknown column 'marking' in 'field list'
It seems that I should add some new columns to the DB tables.
Are there any other columns (beside marking
) that should be added?
Also, I think that it would be useful to specify this in the documentation.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.