I'm writing a Symfony 4 application. Its core is a process with some nested sub-processes. In general, the idea, how to handle it looks like this:
There are some processes (hierarchy of the main processes and its sub-processes). Every process has a set of states. Every process has a set of allowed events.
The facade of this mechanism is the SystemEventHander. It registers the handled processes, analyses the incoming requests, and find and execute the appropriate handler for the current event.
services.yaml
# events
App\Process\SystemEventHandlerInterface:
class: 'App\Process\SystemEventHandler'
tags:
- { name: kernel.event_listener, event: general:user_message_received, method: handle }
- { name: kernel.event_listener, event: process_a:foo, method: handle }
- { name: kernel.event_listener, event: process_a.process_b:foo, method: handle }
- { name: kernel.event_listener, event: process_a.process_c:bar, method: handle }
- { name: kernel.event_listener, event: process_a.process_d:baz, method: handle }
- { name: kernel.event_listener, event: process_a.process_d.process_e:buz, method: handle }
So my all custom events are initially handled by only one handler: the SystemEventHandler().
The proble is, that for every single event I have to write nearly the same line:
- { name: kernel.event_listener, event: process_name:event_name, method: handle }
Only process_name:event_name varies, the rest is static.
Image I have a big number of events -- 30? 50? 100? How can I avoid explicitly writing a new line for every single one?
Related
I'm using Guzzle as a http client in a Symfony app. With the following code I'm able to log all requests and responses. Is there a way to log also response time?
I tried on_stats but it should be added to each client call and it is not an option.
services:
app.client.default:
class: 'GuzzleHttp\Client'
lazy: true
arguments:
- handler: '#app.handler_stack.default'
app.handler_stack.default:
class: 'GuzzleHttp\HandlerStack'
factory: [ GuzzleHttp\HandlerStack, create ]
calls:
- [ push, [ '#app.middleware.log_default', 'log_default' ] ]
app.middleware.log_default:
class: callback
factory: [ GuzzleHttp\Middleware, log ]
arguments:
- '#logger'
- '#app.log_formatter.default'
app.log_formatter.default:
class: 'GuzzleHttp\MessageFormatter'
arguments:
- ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}"
app.service:
class: 'App\Service'
arguments:
- '#app.client.default'
use GuzzleHttp\Client;
class Service {
private $httpClient;
public function __construct(Client $httpClient) {
$this->httpClient = $httpClient;
}
public function apiRequest() {
$response = $this->httpClient->get('https://www.google.com');
// ...
}
}
I have searched quite a bit and couldn't find any answer that solved my problem. So I am posting this question.
My issue is very similar to this question. Angular 2.0.1 Router EmptyError: no elements in sequence
But I couldn't resolve it even by adding pathMatch: 'full',.
I am getting an intermittent zonewaware error when try to navigate from a list table (navigates to detail view)
below is my module.
#NgModule({
imports: [
CommonModule,
RouterModule.forChild([
{
path: 'teams',
component: TeamsListComponent,
pathMatch: 'full',
resolve: {
TeamTemplate: TeamListTemplatesResolver
},
canActivate: [AuthenticatedGuard]
}, {
path: 'teams/:id',
component: TeamFormComponent,
pathMatch: 'full',
resolve: {
team: TeamFormTeamResolver,
resources: TeamFormResourcesResolver
},
canActivate: [AuthenticatedGuard]
}
]),
my authGuard service has a canActivate method which just returns a boolean.
public canActivate(): boolean {
if (this.authService.isLoggedIn()) {
return true;
}
this.router.navigate(['/logout', { redirect: location.pathname }]);
return false;
}
And here is the error:
Zone aware error
I could get a router event log with {enableTracing: true}:
Router Event: NavigationStart
Router Event: RoutesRecognized
Router Event: GuardsCheckStart
Router Event: GuardsCheckEnd
Router Event: ResolveStart
Router Event: NavigationError
Thanks for anyone who looked at this issue. I got the answer to my question.
As I described, I have few resolvers while I route to the detail page. On one of those resolvers there's a logic to get elements.
public resolve(_route: ActivatedRouteSnapshot, _state: RouterStateSnapshot): Observable<T[]> {
return this.service.browse({}).first();
}
https://stackoverflow.com/a/42346203/5162622 - As mentioned here, the first() is sending error notification as there's no values. So I replaced it with take(1) and all looks good.
As I mentioned above in the comment, it was good to know how to do event tracking while routing. That's how I could track this down.
I made a command that automatically writes in routing.yml.
My problem is that when I try to browse one of the routes
api:
resource: "."
type: "api"
prefix: /api
I get this exception
Cannot load resource "."
I tried to add a cache:clear to my command but I get the same exception.
I added a cache warmup that runs after the command termination that way Symfony dumps routes into generated code .
class TerminateListener {
public function onConsoleTerminate(ConsoleTerminateEvent $event) {
if ($event->getCommand()->getName() == ('my:command')) {
$app = new Application();
$cache_clear_command = $event->getCommand()->getApplication()->find('cache:warmup');
$cache_clear_command->setApplication($app);
$event->getOutput()->setVerbosity('VERBOSITY_QUIET');
$cache_clear_command->run($event->getInput(), $event->getOutput());
}
}
}
services:
warmup.listener:
class:TerminateListener
tags:
- { name: kernel.event_listener, event: console.terminate , method: onConsoleTerminate }
I am working on a Symfony 2 web app and I would like to inject a Monolog logger using a specific channel to a service:
The Config:
monolog:
handlers:
main:
type: stream
path: %kernel.root_dir%/%kernel.environment%.log
level: error
#channels: [!alert]
alert:
type: stream
path: %kernel.root_dir%/%kernel.environment%.alert.log
level: info
channels: [alert]
Service Config:
services:
some_service:
class: Some\Service
arguments: [#logger]
tags:
- { name: monolog.logger, channel: alert }
The Service:
class SomeService {
protected $logger;
public function __construct($logger) {
$this->logger = $logger;
$this->logger->info('Log this!');
}
The prod.log file:
[2016-03-28 11:25:47] alert.INFO: Log this!
The Problem: Although I specifically inject the logger using the alert channel, the message is handled by the main handler. Thus the messages are logged into the prod.log file instead of the prod.alert.log file.
When I leave the line channels: [!alert] as comment, the message is logged to prod.log. When I activate this line by removing the comment, the message is not logged at all (main handler ignores the channel correctly).
What have I to to, in order to use a specific handler to target a specific log file, mailer, etc? Messages to alert channel should be handled by the alert handler while all other handlers are ignored.
Use special service created for Monolog handler:
services:
some_service:
class: Namespace\Some\Service
arguments: ["#monolog.logger.alert"]
I want to get User (FOSuserBundle) in Listener With Symfony (2.7).
My Listener service :
utilisateur_cabinet_listener:
class: UtilisateurBundle\Listener\Cabinet
arguments: [#router, #utilisateur_cabinet_repository]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
In Stackoverflow, you recommend to import container service, but the subjects date. Do you have another solution ?