When trying to do a simple search method with Algolia. The search method will query Algolia to get matching results and then will create a doctrine collection. I get this error:
I injected my indexManager in my controller :
class ProductController extends Controller
{
protected $indexManager;
public function __construct(IndexManagerInterface $indexingManager)
{
$this->indexManager = $indexingManager;
}
public function displayAction(Request $request) {
$em = $this->getDoctrine()->getManagerForClass(Product::class);
$posts = $this->indexManager->search('query', Product::class, $em);
return $this->render('ProductBundle:Default:postDisplay.html.twig', array(
'posts' => $posts));
}
}
Can you make sure the autowire feature is set to true?
https://symfony.com/doc/current/service_container/autowiring.html
Symfony should resolve the dependency automatically.
Related
Hi I want to render a form in symFony2 with dynamic fields added to it.
So I have wrote code in controller as:
public function getDataAction(){
$handler = new AnotherClass();
$object = $handler->getForm($getAdditionalData);
}
and "AnotherClass" defined as following:
class AnotherClass extends Controller implements requiredInterface{
public function getForm($formData){
//Here i want to write Logic to render a dynamic form with dynamic fields
$form = $this->createFormBuilder($formData)
->setAction($this->generateUrl('me_route_go'))
// Set form field of additional data
foreach ($formData as $k => $v) {
$form->add($k, 'text');
}
//Create form and submit button
$form = $form->add('submit', 'submit')->add('Cancel', 'reset')->getForm();
$form = $form->getForm();
}
}
}
But here I am getting following error:
Error: Call to a member function get() on a non-object.
return $this->container->get('form.factory')->createBuilder($type, $data, $options);
Please suggest what could be the issue.
thanks in advance..
Your controller AnotherClass requires the Dependency Injection Container since you are extending the base Controller class, you have to set it after you instantiate it :
public function getDataAction(){
$handler = new AnotherClass();
$handler->setContainer($this->container);
$object = $handler->getForm($getAdditionalData);
}
You can also create it as a service :
services.yml
name.of.your.service:
class: Path\To\AnotherClass
calls:
- [setContainer, [ "#service_container" ]]
And then :
public function getDataAction(){
$handler = $this->get('name.of.your.service');
$object = $handler->getForm($getAdditionalData);
}
I have a controller that renders a form that is suppose to have a dropdown with titles mapped against a client_user entity. Below is code I use in my controller to create the form:
$builder = $this->get(form.factory);
$em = $this->get('doctrine.entity_manager');
$form = $builder->createBuilder(new ClientUserType($em), new ClientUser())->getForm();
Below is my ClientUserType class with a constructor that I pass the entity manager on:
<?php
namespace Application\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
class ClientUserType extends AbstractType
{
protected $entityManager;
public function __construct($entityManager)
{
$this->entityManager = $entityManager;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', EntityType::class, array(
'class' => '\\Application\\Model\\Entity\\Title',
'em' => $this->entityManager
))
->add('name')
->add('surname')
->add('contact')
->add('email');
}
public function getName()
{
return 'client_user_form';
}
}
I keep on getting this catchable fatal error below and have no idea what I need to do in order to get a dropdown with titles from a database with doctrine.
Catchable fatal error: Argument 1 passed to Symfony\Bridge\Doctrine\Form\Type\DoctrineType::__construct() must be an instance of Doctrine\Common\Persistence\ManagerRegistry, none given, called in D:\web\playground-solutions\vendor\symfony\form\FormRegistry.php on line 90 and defined in D:\web\playground-solutions\vendor\symfony\doctrine-bridge\Form\Type\DoctrineType.php on line 111
Reading from that error I have no idea where I need to create a new instance of ManagerRegistry registry as it appears that the entity manager does not work. I am also thinking perhaps I need to get the ManagerRegistry straight from the entity manager itself.
Can someone please help explain the simplest way to get this to work? What could I be missing?
Seems that doctrine-bridge form component is not configured.
Add class
namespace Your\Namespace;
use Doctrine\Common\Persistence\AbstractManagerRegistry;
use Silex\Application;
class ManagerRegistry extends AbstractManagerRegistry
{
protected $container;
protected function getService($name)
{
return $this->container[$name];
}
protected function resetService($name)
{
unset($this->container[$name]);
}
public function getAliasNamespace($alias)
{
throw new \BadMethodCallException('Namespace aliases not supported.');
}
public function setContainer(Application $container)
{
$this->container = $container;
}
}
and configure doctrine-bridge form component
$application->register(new Silex\Provider\FormServiceProvider(), []);
$application->extend('form.extensions', function($extensions, $application) {
if (isset($application['form.doctrine.bridge.included'])) return $extensions;
$application['form.doctrine.bridge.included'] = 1;
$mr = new Your\Namespace\ManagerRegistry(
null, array(), array('em'), null, null, '\\Doctrine\\ORM\\Proxy\\Proxy'
);
$mr->setContainer($application);
$extensions[] = new \Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension($mr);
return $extensions;
});
array('em') - em is key for entity manager in $application
For others that may find this: If you want to use the EntityType and you're not using a framework at all, you need to add the DoctrineOrmExtension to your FormFactoryBuilder like so:
$managerRegistry = new myManagerRegistry(
'myManager',
array('connection'),
array('em'),
'connection',
'em',
\Doctrine\ORM\Proxy\Proxy::class
);
// Setup your Manager Registry or whatever...
$doctrineOrmExtension = new DoctrineOrmExtension($managerRegistry);
$builder->addExtension($doctrineOrmExtension);
When you use EntityType, myManagerRegistry#getService($name) will be called. $name is the name of the service it needs ('em' or 'connection') and it needs to return the Doctrine entity manager or the Doctrine database connection, respectively.
In your controller, try to call the service like that:
$em = $this->get('doctrine.orm.entity_manager');
Hope it will help you.
Edit:
Sorry, I thought you was on Symfony... I have too quickly read...
Ok, I was trying to create twig extension with dependencies on other service (security.context) and got some troubles. So, here is my service declaration:
acme.twig.user_extension:
class: Acme\BaseBundle\Twig\UserExtension
arguments: ["#security.context"]
tags:
- { name: twig.extension }
and here's my class
// acme/basebundle/twig/userextension.php
namespace Acme\BaseBundle\Twig;
use Symfony\Component\Security\Core\SecurityContext;
use Acme\UserBundle\Entity\User;
class UserExtension extends \Twig_Extension
{
protected $context;
public function __construct(SecurityContext $context){
$this->context = $context;
}
public function getFunctions()
{
return array(
'getAbcData' => new \Twig_SimpleFunction('getAbcData', $this->getAbcData()),
);
}
public function getAbcData()
{
if ( !is_object($user = $this->context->getToken()->getUser()) || !$user instanceof User){ return null; }
return array(
'data_array' => $user->getData(),
);
}
public function getName()
{
return 'user_extension';
}
}
Finally, I have an error:
FatalErrorException: Error: Call to a member function getUser() on a non-object in \src\Acme\BaseBundle\Twig\UserExtension.php line 27
I guess that security.context service is not initialized yet, then i get an error.
Could anyone tell, please, is there are ways to load service manually, or any better solutions for an issue?
Thanks a lot.
I use Symfony 2.5.*
UPD:
I've also found this notice in symfony docs
Keep in mind that Twig Extensions are not lazily loaded. This means that there's a higher chance that you'll get a CircularReferenceException or a ScopeWideningInjectionException if any services (or your Twig Extension in this case) are dependent on the request service. For more information take a look at How to Work with Scopes.
Actually, I have no idea about how to do it correct..
You are calling $this->getAbcData() when constructing Twig_SimpleFilter. But you have to pass a callable as argument.
public function getFunctions() {
return array (
'getAbcData' => new \Twig_SimpleFunction( 'getAbcData', array( $this, 'getAbcData' ))
);
}
Leo is also right. You should check first if getToken() is returning an object before trying getToken()->getUser().
You can also pass the user to the function as a parameter in twig: {{ getAbcData(app.user) }}. This way the function is more generic and could be used for any user, not just the currently logged in one.
This should probably work. The error message means that getToken() is not an object so you have to test if getToken() is an object before testing if getUser() is also is an object.
public function getAbcData()
{
$token = $this->context->getToken();
if (!is_object($token) || !is_object($token->getUser())) {
return null;
}
return array(
'data_array' => $user->getData(),
);
}
You need to change your twig extension to have the container not the security context passed into the constructor.
Twig_Extensions are special in that the normal rule of don't pass in the container but instead pass in only what you need often doesn't apply as it causes problems due to scope issues.
So change your extension to be like this.
// acme/basebundle/twig/userextension.php
namespace Acme\BaseBundle\Twig;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\SecurityContext;
use Acme\UserBundle\Entity\User;
class UserExtension extends \Twig_Extension
{
/**
* #var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
public function __construct(ContainerInterface $container){
$this->container = $container;
}
public function getFunctions()
{
return array(
'getAbcData' => new \Twig_SimpleFunction('getAbcData', $this->getAbcData()),
);
}
public function getAbcData()
{
if ( !is_object($user = $this->container->get('security.context')->getToken()->getUser()) || !$user instanceof User){ return null; }
return array(
'data_array' => $user->getData(),
);
}
public function getName()
{
return 'user_extension';
}
}
I want to add a custom property to the serialized entity's representation, which takes an existing entity property and formats it in a user friendly way by using an existing service.
I defined a subscriber class and injected the service used for formatting the existing entity property and subscribed to serializer.pre_serialize as follows:
class UserSerializationSubscriber implements EventSubscriberInterface
{
private $coreTwigExtension;
private $user;
public function setCoreTwigExtension(TwigExtension $coreTwigExtension)
{
$this->coreTwigExtension = $coreTwigExtension;
}
public function setUserService(UserService $user)
{
$this->user = $user;
}
public static function getSubscribedEvents()
{
return array(
array(
'event' => 'serializer.pre_serialize',
'method' => 'onObjPreSerialize',
'class' => 'Some\Bundle\Entity\EntityClass',
'format' => 'json'
)
);
}
public function onObjPreSerialize(PreSerializeEvent $event)
{
$context = $event->getContext();
$context->attributes->get('groups')->map(
function(array $groups) use ($event) {
if (in_array('somegroup', $groups)) {
$obj= $event->getObject();
if ($obj->getConfirmedOn()) {
$contextualDate = $this->coreTwigExtension->getContextualDate($obj->getConfirmedOn());
$event->getVisitor()->addData('displayConfirmedOn', $contextualDate);
}
}
}
);
}
}
Subscriber registration:
some_bundle.handler.serialization:
class: Some\Bundle\Handler\ObjectSerializationSubscriber
calls:
- [setCoreTwigExtension, ['#bundle_core.twig.extension']]
- [setUserService, ['#some_bundle.service.user']]
tags:
- { name: jms_serializer.event_subscriber }
When I serialize an array/collection of entity Some\Bundle\Entity\EntityClass I get the following error:
There is already data for "displayConfirmedOn".
How do I resolve this? The only thing stopping me from using #VirtualProperty in the entity is that the virtual property output depends on a service, and no dependencies should be injected into an entity.
The error is due to the fact that the entity itself already exposes an attribute displayConfirmedOn for serialization. When your event listener runs it is not allowed to add an attribute with the same name to the output and you get this error.
Simply stop exposing the attribute in your entity and then the listener can add a property of the same name.
I need to use a productRepository method from within a custom twig extension. I can use standard methods like 'findOneBy' but if I define a custom method in productRepository (say returnVariants() ) then I get this error:
An exception has been thrown during the rendering of a template ("Undefined method 'returnVariants'. The method name must start with either findBy or findOneBy!") in SyliusWebBundle:Frontend/Homepage:main.html.twig at line 16.
The code of the custom twig extension:
namespace Sylius\Bundle\WebBundle\Twig;
use Symfony\Bridge\Doctrine\RegistryInterface;
class ProductExtension extends \Twig_Extension
{
public function __construct(RegistryInterface $doctrine)
{
$this->doctrine = $doctrine;
}
public function getFunctions()
{
return array(
'product_func' => new \Twig_Function_Method($this, 'productFunc'),
);
}
public function productFunc($id)
{
/* This works */
$product = $this->doctrine->getRepository('SyliusCoreBundle:Product')
->findOneBy(array('id' => $id));
/* This doesn't */
$product = $this->doctrine->getRepository('SyliusCoreBundle:Product')->returnVariants();
return $product->getPrice();
}
Thank you very much for your help!
Make sure your entity is using the custom Repository
/**
* #ORM\Entity(repositoryClass="Sylius\...\ProductRepository")
**/
class Product { ... }
Also try clearing your cache
I would suggest not making a custom twig function.
Call this function in the controller and pass the results to twig