I am new with symfony i am trying to use the constructor but it doesn't work and i don't understand why
error:
Cannot autowire service \App\Controller\OutputController argument $product of method &__construct() references class App\Entity\Product but no such service exists.
<?php
namespace App\Controller;
use App\Entity\Product;
class OutputController {
private $product;
public function __construct(Product $product)
{
$this->product = $product;
}
public function jsonFormat() {
return json_encode($this->product->toArray());
}
}
?>
thanks
You use autowiring and you try to autowire a entity. By default they are not exposed as services by this config line from the default app/config/services.yml:
App\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Tests,Kernel.php}'
As you can see, symfony exposes all files from src/* except from:
Entity,Migrations,Tests,Kernel.php
You should not expose entities as services and you should not rely on entities in your controller, Use services for that
Related
I'm making simple "MyCoreBundle" (MystertyCoreBundle) using symfony6.1 how to make bundle's doc.
I defined my bundle class vendor/mysterty/core-bundle/CoreBundle.class
<?php
namespace Mysterty\CoreBundle;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
class MystertyCoreBundle extends AbstractBundle
{
}
I defined some parameters and configuration in vendor/mysterty/core-bundle/config/services.yaml as defaults :
services:
Mysterty\CoreBundle\Controller\CoreController:
public: true
calls:
- method: setContainer
arguments: ["#service_container"]
parameters:
app.admin_email: "mymailATserver.com"
Then I made simple controller in vendor/mysterty/core-bundle/src/Controller/CoreController.php:
<?php
namespace Mysterty\CoreBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
class CoreController extends AbstractController
{
#[Route('/', name: 'mty_default')]
public function indexNoLocale(): Response
{
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
$supportedLangs = explode('|', $this->getParameter('app.supported_locales'));
$lang = in_array($lang, $supportedLangs) ? $lang : $supportedLangs[0];
return $this->redirectToRoute('mty_home', ['_locale' => $lang]);
}
Finally, i added the bundle's routes to \config\routes.yaml
mysterty_core:
resource: "../vendor/mysterty/core-bundle/src/Controller/CoreController.php"
type: annotation
prefix: /
Here is the error i have on http://127.0.0.1:8000/ :
"Mysterty\CoreBundle\Controller\CoreController" has no container set, did you forget to define it as a service subscriber?
I try to make a shared bundle with default actions and components for all my symfony projects.
Solution (thx to helpers)
define loadExtension function in MyOwnBundle.php :
<?php
namespace MyOwn\MyOwnBundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
class MyOwnBundle extends AbstractBundle
{
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
{
// load an XML, PHP or Yaml file
$container->import('../config/services.yaml');
}
}
It looks like Symfiony could not autoconfigure your controller. Try adding the #[AsController] attribute to your controller classes or add autoconfigure: true to your controller service definition in your services.yaml
I am porting a custom bundle that was created originally for symfony 2 to Symfony 5.
Inside the bundle there is a listener with this function:
public function onEarlyKernelRequest(RequestEvent $event)
{
if (!$tenant = $this->tenantStrategy->getTenant()) {
$this->dispatcher->dispatch($tEvent = new TenantEvent(null, $event), TenantEvents::TENANT_NOT_FOUND);
if (!$tEvent->getTenant()) {
return;
}
}
$this->dispatcher->dispatch(new TenantEvent($tenant, $event), TenantEvents::TENANT_FOUND);
//$this->container->set('synd_multitenant.tenant', $tenant);
}
When I remove the comment from the last line I get this error:
The "synd_multitenant.tenant" service is already initialized, you cannot replace it.
With that line commented out, When I try to get the service from the controller I get this message:
Service "synd_multitenant.tenant" not found: even though it exists in the app's container, the container inside "App\Controller\DefaultController" 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", "serializer", "session" and "twig" services. Try using dependency injection instead.
And in case it is relevant, I had to change to RequestEvent from GetResponseEvent because GetResponseEvent is not supported anymore.
Here is the controller where I am trying to use the service:
<?php
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Repository\ClientRepository;
class DefaultController extends AbstractController {
function index() {
//$entityManager = $this->getDoctrine()->getManager();
//$clientRepository = $entityManager->getRepository('App\Entity\Client');
//$client = $clientRepository->findOneBy(array('domain' => 'someclient.mysymfony.local'));
$client = $this->get('synd_multitenant.tenant');
return new Response(
'<html><body>Welcome to My Symfony 5 demo!'.
'<br>Client: ' . $client->getDomain() .
'</body></html>'
);
}
}
Here is the output of console debug:
$ php bin/console debug:container synd_multitenant.tenant
Information for Service "synd_multitenant.tenant"
=================================================
---------------- -----------------------------------------------
Option Value
---------------- -----------------------------------------------
Service ID synd_multitenant.tenant
Class Synd\MultiTenantBundle\Entity\TenantInterface
Tags -
Public yes
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired yes
Autoconfigured yes
---------------- -----------------------------------------------
The complete code is available at this github repository: https://github.com/karimmtl/Mysymfony5
Thanks
found out that the tentant service class name is
\Synd\MultiTenantBundle\Entity\TenantInterface
in the bundles service.yaml file.
Try to change your controller so that you inject the service:
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Repository\ClientRepository;
use Synd\MultiTenantBundle\Entity\TenantInterface;
class DefaultController extends AbstractController
{
function index(TenantInterface $client)
{
return new Response(
'<html><body>Welcome to My Symfony 5 demo!'.
'<br>Client: ' . $client->getDomain() .
'</body></html>'
);
}
}
I have the following class:
EmailNotification
namespace App\Component\Notification\RealTimeNotification;
use Symfony\Bridge\Twig\TwigEngine;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use App\Component\Notification\NotificationInterface;
class EmailNotification implements NotificationInterface
{
private $logNotification;
public function __construct(LogNotification $logNotification, \Swift_Mailer $mailer, EngineInterface $twigEngine)
{
$this->logNotification = $logNotification;
}
public function send(array $options): void
{
$this->logNotification->send($options);
dump('Sent to email');
}
}
I have the following service definition on my yml:
app.email_notification:
class: App\Component\Notification\RealTimeNotification\EmailNotification
decorates: app.log_notification
decoration_inner_name: app.log_notification.inner
arguments: ['#app.log_notification.inner', '#mailer', '#templating']
However, when i tried to run my app it throws an Exception saying:
Cannot autowire service
"App\Component\Notification\RealTimeNotification\EmailNotification":
argument "$twigEngine" of method "__construct()" has type
"Symfony\Bundle\FrameworkBundle\Templating\EngineInterface" but this
class was not found.
Why is that so?
Thanks!
You have to install symfony/templating
composer require symfony/templating
change a little bit config/packages/framework.yaml
framework:
templating:
engines:
- twig
I managed to do it with Twig Environment and HTTP Response
<?php
namespace App\Controller;
use Twig\Environment;
use Symfony\Component\HttpFoundation\Response;
class MyClass
{
private $twig;
public function __construct(Environment $twig)
{
$this->twig = $twig;
}
public function renderTemplateAction($msg)
{
return new Response($this->twig->render('myTemplate.html.twig'));
}
}
Most likely you don't have Templating included in your project, in Symfony 4 you have to require it explicitly:
composer require symfony/templating
I am using Symfony 3.4.0, I try to load fixtures with:
php bin/console doctrine:fixtures:load
An error occurred while creating the data, what's wrong?
This command looks for all services tagged with doctrine.fixture.orm.
There is two ways to fix this problem.
First one: any class that implements ORMFixtureInterface will automatically be registered with this tag.
<?php
namespace AppBundle\DataFixtures\ORM;
use Doctrine\Bundle\FixturesBundle\ORMFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
class LoadFixtures implements ORMFixtureInterface
{
public function load(ObjectManager $manager)
{
#your code
}
}
Second one: You need manually tag doctrine.fixture.orm to DataFixtures in sevice.yml configuration.
services:
...
# makes classes in src/AppBundle/DataFixtures available to be used as services
# and have a tag that allows actions to type-hint services
AppBundle\DataFixtures\:
resource: '../../src/AppBundle/DataFixtures'
tags: ['doctrine.fixture.orm']
I tried #Alexander's solution but it's doesn't work for me.
I had resolved the same problem by adding the tag service to the class, Symfony doc on the services.yml file bundle:
BlogBundle/Resources/config/services.yml
Services:
...
# Fixtures services
BlogBundle\DataFixtures\ORM\PostFixture:
tags: [doctrine.fixture.orm]
...
My BlogBundle/DataFixtures/ORM/PostFixture.php class :
...
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
...
class PostFixture implements FixtureInterface
{
public function load(ObjectManager $manager)
{
...
}
}
Source Inspiration : Synfony doc -> Service container -> The autoconfigure Option
Hope it'll an alternative solution
Example for reusable bundle.
src/Acme/Bundle/UserBundle/DataFixtures/ORM/DataFixtures.php
<?php
namespace Acme\Bundle\UserBundle\DataFixtures\ORM;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
class DataFixtures extends Fixture
{
/**
* Load data fixtures with the passed EntityManager
*
* #param ObjectManager $manager
*/
public function load(ObjectManager $manager)
{
#your code
}
}
in app/config/services.yml
Acme\Bundle\UserBundle\DataFixtures\:
resource: '../../src/Acme/Bundle/UserBundle/DataFixtures/'
append your fixtures data:
php bin/console doctrine:fixtures:load --append
In 4.0.1 I have to implement service configuration to show Symfony my DataFixtures folder:
in config/services.yaml
services:
...
App\DataFixtures\:
resource: '%kernel.project_dir%/src/DataFixtures'
tags: [doctrine.fixture.orm]
if my class IMPLEMENTS FixtureInterface and without this config if it is EXTENDS Fixture
~/dev/domain.lan/src/ProductBundle/DataFixtures/ORM/ProductFixture.php
<?php
namespace ProductBundle\DataFixtures\ORM;
use Doctrine\Bundle\FixturesBundle\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use ProductBundle\Entity\Product;
class ProductFixture implements FixtureInterface
{
public function load(ObjectManager $manager)
{
// create 20 products! Bam!
for ($i = 0; $i < 20; $i++) {
$product = new Product();
$product->setName('Product name' . $i);
$manager->persist($product);
}
$manager->flush();
}
}
The problem is solved it was necessary to add a service: (app/config/services.yml)
services:
# Product service
ProductBundle\:
resource: '../../src/ProductBundle/*'
exclude: '../../src/ProductBundle/{Entity,Repository,Tests}'
use Doctrine\Bundle\FixturesBundle\Fixture
class ProductFixture extends Fixture implements FixtureInterface
see documentation: http://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html
After long research, found a solution.
This work with :
doctrine/doctrine-fixtures-bundle: ^3.0,
Symfony ^3.3
First
Define your Fixture.
<?php
namespace Where\MyFixtureBundle\FileFolder\IsLocated;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Nao\UserBundle\Entity\User;
class LoadData implements FixtureInterface
{
/**
* Load data fixtures with the passed EntityManager
*
* #param ObjectManager $manager
*/
public function load(ObjectManager $manager){
$object = new Entity();
$object->setFoo(bar)
...
$manager->persist($object);
$manager->flush();
}
}
Next, define a service in the bundle's service.yml file or directly in
"app/config/service.yml" (not recommanded)
# Fixtures service
your_service.name:
class: Full\Namespce\With\TheClassFixtureName
tags: [doctrine.fixture.orm] <-- important
Don't forget, just to be sure the following
composer du -o or composer dump-autoload -o
Try to execute your command now for load your data fixtures.
I also had to update the app/AppKernel.php and added the following the the bundles array:
new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle()
After read above comment, i found solution inside #GuRu answer's :
"Second one: You need manually tag doctrine.fixture.orm to DataFixtures in sevice.yml configuration".
Then implements ORMFixtureInterface in your fixtures class.
. in fact, we have to add additionnal configuration inside services.yml to solve it.
Important to know, i notice this issue in version ~3.4 of symfony.
Best regard
I'm jumping here after several years just to document for myself the mixed of solution that I found in this thread.
I experienced the same issue and find the solution by using multiple answers and I hope it will help.
This were my code:
namespace App\DataFixtures;
use App\Entity\Book;
use App\Factory\{BookFactory, UserFactory};
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
class AppFixtures extends Fixture
{
public function load(ObjectManager $manager): void
{
UserFactory::new()->createOne([
'email' => 'user2#user.hr',
'roles' => ['ROLE_ADMIN']
]);
UserFactory::new()->createOne([
'email' => 'user3#user.hr',
'roles' => ['ROLE_USER']
]);
BookFactory::new()->createMany(25);
$manager->flush();
}
}
so I changed replaced extends Fixture ORMFixtureInterface. So new code looks like this:
namespace App\DataFixtures;
use App\Entity\Book;
use App\Factory\{BookFactory, UserFactory};
use Doctrine\Bundle\FixturesBundle\ORMFixtureInterface;
use Doctrine\Persistence\ObjectManager;
class AppFixtures implements ORMFixtureInterface
{
public function load(ObjectManager $manager): void
{
UserFactory::new()->createOne([
'email' => 'user2#user.hr',
'roles' => ['ROLE_ADMIN']
]);
UserFactory::new()->createOne([
'email' => 'user3#user.hr',
'roles' => ['ROLE_USER']
]);
BookFactory::new()->createMany(25);
$manager->flush();
}
}
then I went to services.yml and the I inserted this:
App\DataFixtures\:
resource: '%kernel.project_dir%/src/DataFixtures'
tags: ['doctrine.fixture.orm']
so services.yml file looks like this:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
App\DataFixtures\:
resource: '%kernel.project_dir%/src/DataFixtures'
tags: ['doctrine.fixture.orm']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
and then, like #Spartacvs1 suggested, in your terminal execute this
composer dump-autoload -o
i have this controller
namespace InicioBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use EntidadesBundle\Entity\Usuarios;
use Symfony\Component\HttpFoundation\Session\Session;
class DefaultController extends Controller
{
private $session;
public function __construct(){
$this->session = new Session();
}
.....
public function ver_rol($rol){
if($this->sacarRol() === $rol){
return true;
}else{
return false;
}
}
}
and in the services.yml , i got this:
parameters:
#parameter_name: value
services:
app.rolSession:
class: InicioBundle\Controller\DefaultController
arguments: ["i dont know how get paramets"]
the problem is that it doesnt work, symfony return an error FileLoaderLoadException, that the services.yml does not caontain valid YAML
There is a space before parameters: in your services.yml file, maybe remove that and your yaml should be valid.
Also if you are passing no arguments to constructor you can just delete arguments: ["null"]
One more thing, IIRC you need to add FQCN as class name, so class: InicioBundle\Controller\Default => class: InicioBundle\Controller\DefaultController
While we are at the subject, you can type hint Request in your action and use it to getSession() or maybe inject #session service to your controller