Service "fos_elastica.finder.app.user" not found - symfony

Symfony can't find service for fos_elastica
Service "fos_elastica.finder.app.user" not found: even though it exists in the app's container, the container inside "App\Controller\DevController" is a smaller service locator that only knows about the "doctrine", "form.factory", "http_kernel", "parameter_bag", "request_stack", "router", "security.authorization_checker", "security.csrf.token_manager", "security.token_storage", "session" and "twig" services. Unless you need extra laziness, try using dependency injection instead. Otherwise, you need to declare it using "DevController::getSubscribedServices()".
my config
# Read the documentation: https://github.com/FriendsOfSymfony/FOSElasticaBundle/blob/master/Resources/doc/setup.md
fos_elastica:
clients:
default: { host: localhost, port: 9200 }
# indexes:
# app: ~
indexes:
app:
client: default
types:
user:
properties:
username: ~
# mappings:
# email: ~
persistence:
# the driver can be orm, mongodb, phpcr or propel
# listener and finder are not supported by
# propel and should be removed
driver: orm
model: App\Entity\User
provider: ~
listener: ~
finder: ~
my controller:
/**
* #Route("/search")
*/
public function searchElastic(){
/** var array of App\Entity\User */
$finder = $this->container->get('fos_elastica.finder.app.user');
return new response('N/A');
}
command php bin/console fos:elastica:populate didn't throw any errors and in phpstorm it isn't highlighted (it mean phpstorm found it)
Please help me.

You should use Dependency Injection like so:
Add use statement in the controller class use FOS\ElasticaBundle\Manager\RepositoryManagerInterface;, then your action should look like this:
/**
* #Route("/search")
*/
public function searchElastic(RepositoryManagerInterface $finder) {
$someResult = $finder->getRepository(User::class)->find(...);
return new response('N/A');
}

Related

symfony 4.2 load doctrine service in connection wrapper class

iam new to symfony and created some project based on 4.2 as i have to dynamically switch the db and there seems to be a bug in this version, i followed some instruction to setup a wrapper class for connecting to the db, this works fine. But iam struggeling with getting the doctrince method getConnections() here to work, to be able to double check the sended parameter against my db config. Everything i tried by initializing the doctrine as service container etc. doesn't work.
Hope someone could give me a hint, also my first post, so please no hate (:
Greetings
doctrine:
dbal:
default_connection: db_name
connections:
my_connection:
wrapper_class: App\Doctrine\DynamicConnection
url: '%env(DATABASE_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
services:
# default configuration for services in *this* file
_defaults:
public: false
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
App\Doctrine\:
resource: '../src/Doctrine'
tags: ['doctrine.service_arguments']
doctrine.entity_manager:
public: true
class: App\Doctrine\DynamicConnection
arguments: [ '#doctrine.orm.entity_manager' ]
namespace App\Doctrine;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class DynamicConnection extends Connection
{
public function __construct(array $params = array(), Driver $driver = null, $config = null, $eventManager = null)
{
#$request = Request::createFromGlobals();
#$dbname = $request->query->get('db_name');
$containerBuilder = new ContainerBuilder();
var_dump($containerBuilder->getServiceIds());
$doctrine = $containerBuilder->get('doctrine.entity_manager');

How to setup console application with autowire commands?

Please help me with config Console App, in first - config
#!/usr/bin/env php
<?php
use ....
...
$container = new ContainerBuilder();
$config = new YamlFileLoader($container, new FileLocator(__DIR__));
$config->load('config.yml');
$output = $container->get('symfony.console_output');$logger = $container->get('logger');
//I want automatic injection!!!!
$helloCommand = new HelloCommand($container, $logger);
$application = $container->get('symfony.application');
$application->add($helloCommand);
$application->run(null, $output);
And my config.yml
services:
logger:
class: Symfony\Component\Console\Logger\ConsoleLogger
arguments:
- '#symfony.console_output'
symfony.application:
class: Symfony\Component\Console\Application
calls:
//by this variant autowire not working
- [add, [ '#app.command.hello_command' ]]
- [setDispatcher, ['#symfony.event_dispatcher']]
...
app.command.hello_command:
class: App\Command\HelloCommand
autowire: true
tags:
- { name: console.command }
So my HelloCommand has constructor with ContainerInterface and LoggerInterface and it work only if i set this arguments directly, other i have error about wrong constructor
Or may be exists another way for configuration with config.yml
for only logger - its will be simple by set ['#logger'] as arguments, but how can i set current container as argument?
Or i`ll have to install full symfony with httpkernel (but it does not need)
HelloCommand
http://pastebin.com/VRr3FM7Q
THE DECISION
app.command.hello_command:
class: App\Command\HelloCommand
arguments:
- '#service_container'
- '#logger'
tags:
- { name: console.command }
The problem lies in how you configure your command:
app.command.hello_command:
class: App\Command\HelloCommand
autowire: true
tags:
- { name: console.command }
This misses the 2 constructor arguments required: $container, $logger and is probably why you get the exception. You can add constructor arguments like this:
app.command.hello_command:
class: App\Command\HelloCommand
arguments:
- '#service_container'
- '#logger'
[...]
I'm not sure if the id for the service_container is right. I never pass the container or make things ContainerAware, but you get the general idea. ;)

Example on how to config google cloud storage with KnpGaufetteBundle

I am trying to configure a KnpGaufretteBundle to use Google Cloud Storage for storing my files. This is the config:
## definition of the GCS service
app.google_cloud_storage.service:
class: \Google_Service_Storage
factory_class: Knp\Bundle\GaufretteBundle\DependencyInjection\Factory\GoogleCloudStorageAdapterFactory
factory_method: 'create'
arguments:
- "123#developer.gserviceaccount.com"
- "http://localhost/file.p12"
- "pwd"
## config of knp_gaufrette
knp_gaufrette:
stream_wrapper: ~
adapters:
gcs_minn_images:
google_cloud_storage:
service_id: 'app.google_cloud_storage.service'
bucket_name: 'minn-images'
filesystems:
gcs_minn_images_fs:
adapter: gcs_minn_images
The error message I got is:
ContextErrorException in GoogleCloudStorageAdapterFactory.php line 16:
Catchable Fatal Error: Argument 1 passed to Knp\Bundle\GaufretteBundle\DependencyInjection\Factory\GoogleCloudStorageAdapterFactory::create() must be an instance of Symfony\Component\DependencyInjection\ContainerBuilder, string given, called in /home/amine/NetBeansProjects/tuto/app/cache/dev/appDevDebugProjectContainer.php on line 724 and defined
According to the error message, I gave a string of stead of ContainerBuilder. Great! Let's add the ContainerBuilder to the arguments as follows:
## definition of the GCS service
app.google_cloud_storage.service:
class: \Google_Service_Storage
factory_class: Knp\Bundle\GaufretteBundle\DependencyInjection\Factory\GoogleCloudStorageAdapterFactory
factory_method: 'create'
arguments:
- #service_container
- "123#developer.gserviceaccount.com"
- "http://localhost/file.p12"
- "pwd"
The result is again an error:
Catchable Fatal Error: Argument 1 passed to Knp\Bundle\GaufretteBundle\DependencyInjection\Factory\GoogleCloudStorageAdapterFactory::create() must be an instance of Symfony\Component\DependencyInjection\ContainerBuilder, instance of appDevDebugProjectContainer given, called in /home/amine/NetBeansProjects/tuto/app/cache/dev/appDevDebugProjectContainer.php on line 724 and defined
So now, the error is telling me that I provide an instance of appDevDebugProjectContainer in stead of ContainerBuilder!!
Ok, let's have a look to /home/amine/NetBeansProjects/tuto/app/cache/dev/appDevDebugProjectContainer.php on line 724...
class appDevDebugProjectContainer extends Container{
// ...
/**
* Gets the 'app.google_cloud_storage.service' service.
*
* This service is shared.
* This method always returns the same instance of the service.
*
* #return \Google_Service_Storage A Google_Service_Storage instance.
*/
protected function getApp_GoogleCloudStorage_ServiceService()
{
return $this->services['app.google_cloud_storage.service'] =\Knp\Bundle\GaufretteBundle\DependencyInjection\Factory\GoogleCloudStorageAdapterFactory::create($this, '123#developer.gserviceaccount.com', 'http://localhost/file.p12', 'pwd');
}
I am really lost...
So, is there any complete example to config google cloud storage?
I finally found the solution. You have to create your own factory class as described in the documentation of the bundle:
Factory class
<?php
namespace Minn\AdsBundle\Factory;
/**
* Description of GoogleCloudStorageServiceFactory
*/
class GoogleCloudStorageServiceFactory {
public function createService() {
// creating the google client
$client = new \Google_Client();
// setting the service acount credentials
$serviceAccountName = '123#developer.gserviceaccount.com';
$scopes = array(
'https://www.googleapis.com/auth/devstorage.read_write',
);
$privateKey = file_get_contents('http://localhost/f.p12');
$privateKeyPassword = 'pwd';
$credential = new \Google_Auth_AssertionCredentials(
$serviceAccountName, $scopes, $privateKey, $privateKeyPassword);
// set assertion credentials
$client->setAssertionCredentials($credential);
// creating and returning the service
return new \Google_Service_Storage($client);
}
}
The config.yml file
app.google_cloud_storage.service:
class: \Google_Service_Storage
factory: [Minn\AdsBundle\Factory\GoogleCloudStorageServiceFactory, createService]
knp_gaufrette:
stream_wrapper: ~
adapters:
gcs_images:
google_cloud_storage:
service_id: 'app.google_cloud_storage.service'
bucket_name: 'images'
filesystems:
gcs_images_fs:
adapter: gcs_images
vich_uploader:
db_driver: orm
storage: gaufrette
mappings:
motors_files:
upload_destination: gcs_images_fs
namer: vich_uploader.namer_origname
delete_on_remove: true
That's was it...
Hope it will help others...

FosElasticaBundle: define mapping for GUID / UUID fields

How do I define the mappings in config_yml if my entities uses GUID field type as identifier?
Details
I have a project with Symfony 2.7.3 and FosElasticaBundle 3.1.4.
I have configured the mapping and everything works fine when I use the populate command or if I edit an existing entity; but when creating a new entity I get an exception
"expected a simple value for field [_id] but found [START_OBJECT]]"
Checking the JSON response I have noticed that _id is set to an empty object ..."_id":{}....
The Uuid class already has a __toString method which I expect should do the trick, but I am probably missing something.
Current mappings
fos_elastica:
clients:
default: { host: %elasticsearch_host%, port: %elasticsearch_port%, logger: true }
indexes:
app:
types:
user:
mappings:
name: ~
surname: ~
persistence:
driver: orm
model: AppBundle\Entity\User
provider: ~
listener: ~
finder: ~
Thank you.
There are no specific mappings for UUID/GUID fields.
The identifier is retrieved using the standard Symfony property accessor, so the solution to my problem was to change the getId() method in my entity, and make it cast to string be
public function getId()
{
return (string)$this->id;
}

Change service parameter value dynamically for FOSUserBundle

I asked about using multiple entity manager for FOSUserBundle before, and it turns out that FOSUserBundle has (partially) supported that. All I need to do is to specify the connection / manager I want to use in the model_manager_name parameter, as explained here
fos_user:
# ........
model_manager_name: account1
Sample app/config/config.yml
With this FOSUserBundle will use account1 connection, and use user information in that connection's database.
doctrine:
dbal:
default_connection: default
connections:
account2:
dbname: account2
user: account2
password: password2
driver: pdo_mysql
host: localhost
port: ~
charset: UTF8
account1:
dbname: account1
user: account1
password: password1
driver: pdo_mysql
host: localhost
port: ~
charset: UTF8
default:
dbname: account
user: account
password: password
driver: pdo_mysql
host: localhost
port: ~
charset: UTF8
My app require that when a user goes to (for example) http://myapp.com/a/account1, the app will use account1 connection, and going to http://myapp.com/a/account2 will use account2's connection. For my application's logic, this is easily done from my controllers as I could use something like the following;
$em = $this->get('doctrine')->getManager('account2');
$repository = $this->get('doctrine')->getRepository($class, 'account2')
For the login part though, it's not that easy. FOSUserBundle runs as a service container, and I don't know where/how to dynamically change the model_manager_name's value. I do know though that in FOS\UserBundle\DependencyInjection\FOSUserExtension I can manually change its value the following way;
class FOSUserExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$processor = new Processor();
$configuration = new Configuration();
$config = $processor->processConfiguration($configuration, $configs);
$config['model_manager_name'] = 'account2';
// .................
Any thoughts?
The configuration is stored inside the container, in the fos_user.model_manager_name to be exact.
You can write a compiler pass. This will be executed just before freezing the container, it is the last place where you can change the container and it is the place to change the container based on other services.
Your compiler pass will look like this:
// src/Acme/DemoBundle/DependencyInjection/Compiler/ChangeModelManagerPass.php
namespace Acme\DemoBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class ChangeModelManagerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$request = $container->get('request');
$uri = $request->getUri();
// check if the uri matches some pattern which will cause a change in the
// `model_manager_name` setting
if (...) {
// ... do some stuff to get the correct model manager name
// set the setting
$container->setParameter('fos_user.model_manager_name', ...);
}
}
}
Read more about compiler passes in the docs or in this great blog post by Richard Miller.

Resources