php MongoDB\Driver\Manager not found when executing Symfony command - php

Ok, so I have a project my mongo connection works fine when viewing pages etc. But when I try to load the manage class in command (ContainerAwareCommand) I get class not found exception:
[Symfony\Component\Debug\Exception\ClassNotFoundException]
Attempted to load class "Manager" from namespace "MongoDB\Driver".
Did you forget a "use" statement for another namespace?
I'm using symfony 3.2
Here's what I do:
class TestCommand extends ContainerAwareCommand {
protected function configure() {
$this->setName('testcommand:test')
->setDescription('Test...')
->setHelp('Test...');
}
protected function execute(InputInterface $input, OutputInterface $output) {
$db = new Manager("mongodb://localhost:27017");
$output->writeln([
'Test',
'========================',
'',
]);
}
}
I import the driver with:
use MongoDB\Driver\Manager;
PhpStorm recognizes the import.
Any ideas what stops the class from loading? Once again, it loads normally when I navigate my pages etc.
Thanks!
UPDATE (As requested) !
Registered a service:
services:
test.service:
class: AppBundle\Test\TestService
public: true
The service:
namespace AppBundle\Test;
use MongoDB\Driver\Manager;
class TestService {
public function foo() {
$manager = new Manager("mongodb://localhost:27017");
}
}
added this to execute method:
$ts = $this->getContainer()->get("test.service");
$ts->foo();
result:
[Symfony\Component\Debug\Exception\ClassNotFoundException]
Attempted to load class "Manager" from namespace "MongoDB\Driver".
Did you forget a "use" statement for another namespace?
What am I missing?
ANOTHER UPDATE
I also noticed that I couldn't switch to production because of the same, but more general, error.
Turns out I can't use namespaces but can get the class (Manager) via fully qualified name at RUN TIME ONLY!!!

I had had the same problem and was somewhat distracted by the error message, this problem occurs while executing the script in the CLI context where not all extension has been properly installed.
Check whether all your extension, escpecially for MongoDb are installed.

Related

Symfony 4 : Override public services in container

I am migrating our project to Symfony 4. In my test suites, we used PHPUnit for functional tests (I mean, we call endpoints and we check result). Often, we mock services to check different steps.
Since I migrated to Symfony 4, I am facing this issue: Symfony\Component\DependencyInjection\Exception\InvalidArgumentException: The "my.service" service is already initialized, you cannot replace it.
when we redefine it like this : static::$container->set("my.service", $mock);
Only for tests, how can I fix this issue?
Thank you
Replacing is deprecated since Symfony 3.3. Instead of replacing service you should try using aliases.
http://symfony.com/doc/current/service_container/alias_private.html
Also, you can try this approach:
$this->container->getDefinition('user.user_service')->setSynthetic(true);
before doing $container->set()
Replace Symfony service in tests for php 7.2
Finally, I found a solution. Maybe not the best, but, it's working:
I created another test container class and I override the services property using Reflection:
<?php
namespace My\Bundle\Test;
use Symfony\Bundle\FrameworkBundle\Test\TestContainer as BaseTestContainer;
class TestContainer extends BaseTestContainer
{
private $publicContainer;
public function set($id, $service)
{
$r = new \ReflectionObject($this->publicContainer);
$p = $r->getProperty('services');
$p->setAccessible(true);
$services = $p->getValue($this->publicContainer);
$services[$id] = $service;
$p->setValue($this->publicContainer, $services);
}
public function setPublicContainer($container)
{
$this->publicContainer = $container;
}
Kernel.php :
<?php
namespace App;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
public function getOriginalContainer()
{
if(!$this->container) {
parent::boot();
}
/** #var Container $container */
return $this->container;
}
public function getContainer()
{
if ($this->environment == 'prod') {
return parent::getContainer();
}
/** #var Container $container */
$container = $this->getOriginalContainer();
$testContainer = $container->get('my.test.service_container');
$testContainer->setPublicContainer($container);
return $testContainer;
}
It's really ugly, but it's working.
I've got a couple of tests like this (the real code performs some actions and returns a result, the test-version just returns false for every answer).
If you create and use a custom config for each environment (eg: a services_test.yaml, or in Symfony4 probably tests/services.yaml), and first have it include dev/services.yaml, but then override the service you want, the last definition will be used.
app/config/services_test.yml:
imports:
- { resource: services.yml }
App\BotDetector\BotDetectable: '#App\BotDetector\BotDetectorNeverBot'
# in the top-level 'live/prod' config this would be
# App\BotDetector\BotDetectable: '#App\BotDetector\BotDetector'
Here, I'm using an Interface as a service-name, but it will do the same with '#service.name' style as well.
As I understood it, it means that class X was already injected(because of some other dependency) somewhere before your code tries to overwrite it with self::$container->set(X:class, $someMock).
If you on Symfony 3.4 and below you can ovverride services in container regardless it privite or public. Only deprication notice will be emmited, with content similar to error message from question.
On Symfony 4.0 error from the question was thown.
But on Symfony 4.1 and above you can lean on special "test" container. To learn how to use it consider follow next links:
https://symfony.com/blog/new-in-symfony-4-1-simpler-service-testing
https://dev.to/nikolastojilj12/symfony-5-mocking-private-autowired-services-in-controller-functional-tests-24j4

PHP Symfony error: "did you forget to use a use statement", regardless of class/function

I have started building a new Web App using Symfony, but am having issues using classes.
PhpStorm is able to find the functions within the classes (due to the fact that it gives suggestions when you type $className->.
Also, to prove this is not the same as the other similar questions, I have over simplified it, and even so, the error still occurs.
I have the below in my DefaultController:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use testBundle;
use AppBundle\domainionClasses\firstlevelchecks;
class DefaultController extends Controller
{
/**
* #Route("/register",name="register")
*/
public function registerAction(){
$testClass = new firstlevelchecks();
$testing = $testClass->donothing(); //the IDE knows that the function donothing() exists, in fact it suggests it.
return new Response('');
}
}
The below is the php class located in AppBundle/domainionClasses/test1.php
<?php
namespace AppBundle\domainionClasses;
class firstlevelchecks
{
function donothing(){
return null;
}
}
When loading the /register route, the below Symfony error is displayed:
Attempted to load class "firstlevelchecks" from namespace "AppBundle\domainionClasses".
Did you forget a "use" statement for another namespace?
It is attempting to load the class from the correct name space, and I have used a use statement.
Is there anything I am missing here, or is there a problem with Symfony? This is the first time I used the new version of PhpStorm, and have just downloaded the plugin, also the first time I have experienced this issue :(
Because your file is named test1.php, how can the autoloader know which file to include ?
You shoud rename it to firstlevelchecks.php (= the name and case of your class).

namespaceing for service class in symfony2 project

I am facing one problem I do not know what is a reason of this I add class with location in my project src/ApiMaps/ApiMapBundle with this name space
<?php
namespace ApiMaps\ApiMapService;
class ApiMapService {
private $transport;
public function __construct() {
$this->transport = 'sendmail';
}
// ...
}
when i give in
src/config/service.yml
app.test:
class: ApiMaps\ApiMapService\ApiMapService
arguments: ["#doctrine.orm.entity_manager"]
and when i run it from some other class for example
src/ApiMaps/ApiMapBundle/Command/GetApiCommand.php
class GetApiCommand extends ContainerAwareCommand
{
protected function execute(InputInterface $input, OutputInterface $output)
{
$number = $this->getContainer()->get('app.test');
}
}
it give me error
Fatal error: Class 'ApiMaps\ApiMapService\ApiMapService' not found in D:\xampp\htdocs\ProjectMapApiData\a
pp\cache\dev\appDevDebugProjectContainer.php on line 325
[2016-02-01 08:25:20] php.CRITICAL: Fatal Error: Class 'ApiMaps\ApiMapService\ApiMapService' not found {"
type":1,"file":"D:\xampp\htdocs\ProjectMapApiData\app\cache\dev\appDevDebugProjectContainer.php","
line":325,"level":-1,"stack":[]}
[Symfony\Component\Debug\Exception\ClassNotFoundException]
Attempted to load class "ApiMapService" from namespace "ApiMaps\ApiMapService".
Did you forget a "use" statement for another namespace?
Note--
one thing to mention that when i try to make service from the built-in class of symfony2 classes it does not give me such error. I do know where I need to add the namespace of the class which i recently added with my project that it able to know the class...
You mention that your service in file:
src/ApiMaps/ApiMapBundle
but in config you wrote:
ApiMaps\ApiMapService\ApiMapService.
I think you should house you service in file: src/ApiMaps/ApiMapBundle/ApiMapService/ApiMapService.php,
take namespace: ApiMaps\ApiMapBundle\ApiMapService
and write in config: ApiMaps\ApiMapBundle\ApiMapService\ApiMapService.
Truly believe it'll help you...

Laravel 4: Target Interface is not instantiable

I've been comparing my code to this question and many other guides online but with little success. Everything works fine until I try to inject the the interface in my controller. When I do inject it, I get the Target Interface is not instantiable error.
app\models\Interfaces\InterviewInterface.php
<?php namespace app\models\Interfaces;
interface InterviewInterface {
public function fetch($id);
}
app\models\Interview.php
use app\models\Interfaces\InterviewInterface;
class Interview extends Eloquent implements InterviewInterface {
public function fetch($id)
{
return Interview::find($id);
}
}
routes.php
App::bind('app\models\Interfaces\InterviewInterface');
composer.json
"psr-4": {
"Blog\\Articles\\" : "app/lib/Blog/Articles",
"app\\models\\Interfaces\\" : "app/models/Interfaces/InterviewInterface.php"
}
AdminInterviewController.php
use app\models\Interfaces\InterviewInterface as InterviewInterface;
class AdminInterviewController extends BaseController {
public function __construct(InterviewInterface $interview)
{
$this->interview = $interview;
$this->beforeFilter('auth');
}
}
As soon as I add the
use app\models\Interfaces\InterviewInterface as InterviewInterface;
and
__construct(InterviewInterface $interview)
$this->interview = $interview;
lines, it gives me the error. I pull them out, no error.
I have run php composer.phar dump-autoload and php artisan dump-autoload commands multiple times and they succeed.
Any ideas? I really appreciate it.
You need to bind the interface to a class in order to resolve it from the IOC:
In routes.php, assuming it is not namespaced:
App::bind('app\modesl\Interfaces\InterviewInterface', 'Interview');

Why is Symfony2 (ezpublish5) not recognizing my controller as a service?

I'm trying to create a menu for my page with ezpublish5. I followed this tutorial http://partialcontent.com/Code/working-with-ez-publish-5-subrequests.
I'm pretty new to Symfony, but I have my own bundle there and running, at least it is using my own pagelayout.html.twig.
I understand, what routing does, but I as far as I'm concerned in order to create a menu I need something else, probably a service, so I can do this in my twig-template
{{ render( controller( "myMenuController:myFunction" ) ) }}
So I add this to my my\Bundle\Resources\config\services.yml
parameters:
my_root.menucontroller.class: my\Bundle\Controller\MenuController
services:
my_root.controller:
class: %my_root.menucontroller.class%
arguments: [#ezpublish.view_manager]
calls:
- [setContainer, [#service_container] ]
myalias:
alias: my_root.controller
When I open it in the browser it says:
You have requested a non-existent service "myalias".") in "{% extends "Bundle::pagelayout.html.twig" %}
I checked other repos of ezp5 installations on github, they have pretty much the same yml-setup.
I also realized, that when I make syntax errors on purpose in my services.yml it (while leaving out the call to the controller in the template) it doesn't change anything.
Also I realized, that when I do the same in my\Bundle\DependencyInjection\myBundleExtension.php (which is supposed to load my services.yml file) it doesn't happen anything either.
So I'm getting the feeling something with bundle-setup is wrong, that somehow not everything is loaded correctly. But what could it be?
Somewhere in the docu of symfony2 it says that the load-method in the Bundle\DependencyInjection\xyzExtension.php gets called automatically.
Would anyone have an idea of what could possibly be wrong with my setup? I'm really running out of ideas.
And for the ezpublish5 part.. is this really the best way to create a menu right now?
It does seem like your services are not being loaded.
Symfony relies on a naming convention to load xyzExtension.php. It's tripped me up a few times. You can stick a die statement in xyzExtension.load just to verify it is indeed being called.
If it is not being called than you can either change the extension class name to meet the convention or do what I do and just override the convention in your bundle class.
namespace Cerad\Bundle\GameV2Bundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Cerad\Bundle\GameV2Bundle\DependencyInjection\GameExtension;
class CeradGameV2Bundle extends Bundle
{
public function getContainerExtension()
{
return new GameExtension();
}
}
And of course xyzExtension should have something like:
namespace Cerad\Bundle\GameV2Bundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\Config\FileLocator;
class GameExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
public function getAlias() { return 'cerad_game_v2'; }
}
From the command line you can verify your service is getting picked up:
app/console container:debug : grep my_root

Categories