I create a service inside my module with the name of an existing core service (prestashop.adapter.data_provider.product). It successfully replaces it as seen in php ./bin/console debug:container output.
In yaml:
prestashop.adapter.data_provider.product:
class: PrestaShop\Module\MyModule\Adapter\Product\ProductDataProvider
The problem now is that I have 500 errors in some pages in BO. These errors are type errors like:
Type error: Argument 4 passed to
PrestaShopBundle\Model\Product\AdminModelAdapter::__construct() must
be an instance of
PrestaShop\PrestaShop\Adapter\Product\ProductDataProvider, instance of
PrestaShop\Module\MyModule\Adapter\Product\ProductDataProvider given,
called in....
I understand now that, whenever a constructor has an argument of type ProductDataProvider, the app tries to load my service but find a differentuse statement in the class (i.e in PrestaShopBundle\Model\Product\AdminModelAdapter)
These errors can be fixed by replacing the use statement in each file containing the problem, but as you may know, touching core files must be avoided.
Is there a way of overriding an existing service, but also make the override work all across the app "bypassing the use statements of the old service".
Related
I'm stuck with a problem: I created an event according to the Laravel docs.
I created the files with php artisan event:generate
This command created two files:
Listeners/RevokeOldToken.php
Listeners/PruneOldTokens.php
After that when I hit the API, it returns this error:
Argument 1 passed to App\Listeners\RevokeOldTokens::handle() must be an instance of App\Events\Laravel\Passport\Events\AccessTokenCreated, instance of Laravel\Passport\Events\AccessTokenCreated given
What i am doing wrong? How can I create the instance said by the error?
You need import that two class in listener.
use Laravel\Passport\Events\AccessTokenCreated;
use Laravel\Passport\Events\RefreshTokenCreated;
I think you didn't import them, so laravel think your listener is expecting that two wrong classes, App\Events\Laravel\Passport\Events\AccessTokenCreated and App\Events\Laravel\Passport\Events\AccessTokenCreated
tl;dr
Artisan generates an incorrect use path for the event classes in the listener files so you have to fix them, by removing the App\Events part from the front.
Explanation
The Generating Events & Listeners subsection under the documentation's Registering Events & Listeners section mentions that the event and listener classes are generated based on the app/Providers/EventServiceProvider.php class' listen attribute.
This is a nice feature, but there is a little problem with it: if the array's keys (the event file paths) in the $listen attribute reference an event from the vendor folder (Laravel\Passport\Events in this case) then in the generated listener file, the imported event's path will be prefixed with App\Events\. This is the thing that you have to remove.
Because of this, the use path now references a non existing class that doesn't raise an error like "using non existing class", so when the code gets executed and the event is fired, then thanks to the mappings in the EventServiceProvider.php file, the proper event listener will be found for the event, but when the listener's handle method is called with the event, it will raise a type error (which is a PHP thing), because the argument's type hinting references a different (non existing) class.
Catching the bug in action
If we dig deep into the framework, we can find the Illuminate/Foundation/Console/EventGenerateCommand.php class the gets executed when you call php artisan event:generate. You can see that it parses the EventServiceProvider class' listen attribute then starts to generate event and listener files.
The listener generation will happen in the Illuminate/Foundation/Console/ListenerMakeCommand.php file, that will create the generated file based on the stub found in Illuminate/Foundation/Console/stubs/listener.stub.
The dummy import path will be replaced in the buildClass function. The new path has been calculated just before the replace took place and that is where the error happens:
if (! Str::startsWith($event, [
$this->laravel->getNamespace(),
'Illuminate',
'\\',
])) {
$event = $this->laravel->getNamespace().'Events\\'.$event;
}
In our case $event will start with Laravel\Passport\Events and not with App\, Illuminate or \ so the path will be prefixed with App\Events\. That is the thing you should remove in the generated files.
I hope this is official enough.
I have configured Laravel 5 to use a custom logging configuration (default is way too simple). I've added monolog's IntrospectionProcessor to log the file name and line number of the log call.
The problem is that all lines get the same file and line number:
[2015-06-29 17:31:46] local.DEBUG (/home/vagrant/project/vendor/laravel/framework/src/Illuminate/Log/Writer.php#201): Loading view... [192.168.10.1 - GET /loans/create]
Is there a way to config the IntrospectionProcessor to print the actual lines and not the facade ones?
If I do Log::getMonolog()->info('Hello'); it works and prints the correct file and line number... but I don't know how safe is to avoid calling the Writer.writeLog function because it fires a log event (is it safe to not fire that event?).
(Only tried in Laravel 4.2!)
When pushing the Introspection Processor to Monolog it is possible to give an skipClassesPartial array as second parameter in the IntrospectionProcessor contructor. With this array it is possible to skip the Laravel Illuminate classes and the logger logs the class calling the log method.
$log->pushProcessor(new IntrospectionProcessor(Logger::DEBUG, array('Illuminate\\')));
also see: https://github.com/Seldaek/monolog/blob/master/src/Monolog/Processor/IntrospectionProcessor.php
I know this is an old question but I thought I'd give a quick update because it's pretty easy to get this done now.
I haven't tried with Laravel but My own logging mechanism is within a LoggingService wrapper class. As such the introspection was only giving details about the service rather than the caller.
after reading Matt Topolski's answer, I had a look in the IntrospectionProcessor.php. the constructor looks like this:
__construct($level = Logger::DEBUG, array $skipClassesPartials = array(), $skipStackFramesCount = 0)
All I had to do was add the processor like this:
log->pushProcessor(new IntrospectionProcessor(Logger::DEBUG, array(), 1));
This is actually the expected functionality unless you're having the handler process the logs directly (check out the comments at the top of IntrospectionProcessor.php). My guess is you have a wrapper function around the logger and you're calling it from Writer.php -- BUT
If you look at the code for IntrospectionProcessor.php you'll see a bit of code on lines 81 to 87 that decides how to format that stack trace, and it still has access to the stack. If you bump the $i values for $trace[$i - 1] / $trace[$i] up one (aka $trace[$i]/$trace[$i + 1] respectively) you can 'climb' the stack back to where you want.
It's important to note that the 'class' and 'function' parts of the trace need to be one level of the stack higher than the 'file' and 'line.'
On a personal (plz dont mod me bruhs) note, I'd like to see functionality to include a stack offset when throwing the log in. I know what function I want to blame if an error shoots out when I write the error_log('ut oh') but I might(will) forget that by the time the 'ut oh' comes.
This is a continuation of my last question.
Hi,
I'm implementing, in a Symfony2 application, a custom authentication provider in order to authenticate against the Wordnik REST API.
On application load, no matter what request path, this is the exception I get:
( ! ) Fatal error: Cannot access parent:: when current class scope has no parent in /[..]/WordRot/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php on line 43
You can see the full stacktrace here.
Second to last line in the trace reveals that it is loading the DaoAuthenticationProvider:
18 0.0217 1922792 Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider->__construct( ) ../appDevDebugProjectContainer.php:3071
But none of my configuration refers to that provider, or anything that extends it. My custom provider directly implements the AuthenticationProviderInterface.
So I assume that my configuration is wrong, and somewhere I need to be explicitly setting the WordnikProvider, but I'm not sure where! Research has not provided any clues to this issue.
Any help would be much appreciated!
Files
/app/config/config.yml
/app/config/security.yml
/src/WordRot/PlayBundle/Security/Authentication/Provider/WordnikProvider.php
/src/WordRot/PlayBundle/Security/Authentication/Token/WordnikUserToken.php
/src/WordRot/PlayBundle/Security/Firewall/WordnikListener.php
/src/WordRot/PlayBundle/DependencyInjection/Security/Factory/WordnikFactory.php
the line return $this->authenticationManager->authenticate(new WordnikUserToken($username, $password, $this->providerKey)); in the WordnikListener goes to
Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager (classes.php)
authenticate.
$this->providers are DaoAuthentificationProvider, WordnikProvider and AnonymousAuthentificationProvider.
From the DaoAuthentificationProvider it only uses the method supports($token):
return $token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey();
which returns false so next in line is WordnikProvider.
Oh..misread: the error is in the constructor:
parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions); seems to fail. Running PHP 5.4.10 or so I DON'T have an error!!
Either rm -rf vendor and run composer install again or try using a different PHP version!!
A had to create something like this a week ago.
At the and, I created a custom user provider, where I simply call the api and with the response i create the user or not.
I would advise to read this:
http://symfony.com/doc/2.0/cookbook/security/custom_provider.html
I'm converting an old PHP project to the Symfony2 framework. Some of the pages are now handled by my Symfony2 front controller (index.php), but many pages have not yet been converted.
The problem is that, within Symfony, all of my Doctrine entity annotations must begin with the ORM\ prefix, but outside of Symfony, that prefix does not appear to be enabled, and so I get the following error:
Class MyProject\MyBundle\Entity\MyClass is not a valid entity or mapped super class.
I've tried to duplicate whatever magic Symfony does to set this up, including following these instructions [doctrine-project.org], and actually including app/autoload.php entirely into my legacy bootstrap process. But nothing works.
Does anyone know how I can manually replicate whatever it is that Symfony does to enable the ORM\ prefix for my Doctrine annotations?
I got the answer from the Symfony2 Google group. The problem is that the Doctrine configuration shown in the documentation uses SimpleAnnotationReader behind the scenes, but you need regular AnnotationReader to use the ORM\ namespace prefix. I got it to work by replacing this:
$config = new Doctrine\ORM\Configuration();
$driver = $config->newDefaultAnnotationDriver('/path/to/my/entities');
with this:
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
// ...
$config = new Doctrine\ORM\Configuration();
$reader = new AnnotationReader();
$driver = new AnnotationDriver($reader, '/path/to/my/entities');
I ended up with:
Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration($paths, $devMode, null, null, false);`
The 3rd and 4th null arguments are default. The 5th false argument tells it to make a standard AnnotationReader rather than a basic one.
I'm using Doctrine 2.5.6.
Explanation
I found I couldn't get Ian's solution working without calling Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration before making my own config. I was getting this error:
'[Semantical Error] The annotation "#Doctrine\ORM\Mapping\Entity" in class My\Class does not exist, or could not be auto-loaded.'
I was really confused so I took a look at the source code.
It turns out createAnnotationMetadataConfiguration calls Doctrine\ORM\Configuration::newDefaultAnnotationDriver rather than creating the annotation driver directly. This calls AnnotationRegistry::registerFile(__DIR__ . '/Mapping/Driver/DoctrineAnnotations.php'); which seems to be critical. After that, newDefaultAnnotationDriver just creates a new AnnotationDriver().
When I generate a WSDL file with ./symfony webservice:generate-wsdl (where is 'frontend', is 'soap' and is 'http://localhost ') I get a nice soap.wsdl file which works like it should. Except, the methods are not named 'justAMethod' but 'soapService_justAMethod' (where soapService is the module which holds the SOAP methods). How do I omit the module name in the SOAP method names? I know this is possible since the previous release of the software had no module name in the SOAP method names.
Found it: the option '-h' on './symfony webservice:generate-wsdl' creates a custom soapHandler, effectively omitting the module name in the SOAP methods. This is not in the documentation however.