How Can I add get container in form builder symfony? - forms

How Can I add get container in form builder symfony ?
I would like use $get->container in form builder...

One issue is to pass container as parameter to your FormType file from the controller:
$form_type = new MyFormType($this->container);
And add a construct method in your FormType file:
protected $container;
public function __construct($container)
{
$this->container = $container;
}
Then you can access to container by: '$this->container';
Hope it will help you ;)

Injecting the whole container into a form type is a bad practice. Please consider injecting only required dependencies to your form type. You can simply define your form type as a service and inject required dependencies.
src/AppBundle/Form/TaskType.php
use Doctrine\ORM\EntityManagerInterface;
// ...
class TaskType extends AbstractType
{
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
// ...
}
src/AppBundle/Resources/config/services.yml
services:
AppBundle\Form\TaskType:
arguments: ['#doctrine.orm.entity_manager']
tags: [form.type]
To inject a repository class there are two ways. The second approach is more clean.
Inject an EntityManager class and get repository class from EM:
$this->em->getRepository(User::class)
Register repository class as a service using EM factory and inject it to your form type:
services:
AppBundle\Repository\UserRepository:
factory: ['#doctrine.orm.entity_manager', getRepository]
arguments: ['AppBundle\Entity\User']

Related

Dagger2 Android subcomponent injection in nonAndroid classes

Learning Dagger2 and maybe going off the rails here. I have a class - MapRoute that may or may not be needed in a Fragment. If MapRoute is needed, I want to create it and when the MapRoute is instantiated I want to inject it with dependencies created at the application level. I am also using Builder pattern to populate MapRouter.
Perhaps the generic question is when you are in nonAndroid classes (not Activity/Fragment/...) how can you inject dependencies from above? How to you construct the nonAndroid injector in place of AndroidInjection.inject(this)?
So my fragment is:
public class ActivityMapFragment extends DaggerFragment ... {
#Inject
MapRoute.Builder mapRouteBuilder;
private void plotRouteForMap(Cursor csr){
MapRoute.Builder builder = new MapRoute.Builder();
builder.setSupportMapFragment(supportMapFragment)
.setLocationExerciseRecord(ler)
.setMapType(mapType)
.setUseCurrentLocationLabel(useCurrentLocationLabel)
.setCursor(csr)
.setTitle(activityTitle)
.setActivityPhotosCallback(this);
mapRoute = builder.build();
mapRoute.plotGpsRoute();
}
...
MapRoute is: (Edit) added Builder code snippet
public class MapRoute ... {
#Inject
public DisplayUnits displayUnits; <<< Created at app level
#Inject
public PhotoUtils photoUtils; <<<< Create at app level
public MapRoute() {
// Use subcomponent builder
MapRouteSubcomponent component =
DaggerMapRouteSubComponent.builder().build(); <<< Want to do this
component.inject(this);
}
public static class Builder {
SupportMapFragment supportMapFragment;
LocationExerciseRecord ler;
boolean useCurrentLocationLabel;
int mapType;
Cursor cursor;
ActivityPhotosCallback activityPhotosCallback;
String title;
#Inject
public Builder() {
}
public Builder setSupportMapFragment(SupportMapFragment supportMapFragment){
this.supportMapFragment = supportMapFragment;
return this;
}
....
MapRouteSubcomponent best guess:
#Subcomponent(modules = {MapRouteModule.class, ApplicationModule.class})
public interface MapRouteSubcomponent {
// allow to inject into our MapRoute class
void inject(MapRoute mapRoute);
#Subcomponent.Builder
interface Builder extends SubComponentBuilder<MapRouteSubcomponent> {
Builder mapRouteModule(MapRouteModule mapRouteModule);
}
#Module
public class MapRouteModule {
// What to put here?
}
And finally a subcomponent builder:
// from https://github.com/Zorail/SubComponent/blob/master/app/src/main/java/zorail/rohan/com/subcomponent/SubComponentBuilder.java
public interface SubComponentBuilder<V> {
V build();
}
At this point I am at a stand on where to go from here.

How to instance doctrine entity manager in a symfony2 class

I am new with Symfony 2 and Doctrine.
I have created a new class on my symfony project, which is located in:
project_folder/src/Libraries/Validarcontenido/Validarcontenido.php
I need to get the Doctrine Entity Manager instance in this class.
I have reading docs about it, and everyone says that i must add the class into the services.yml file, but didn't work.
Here is my code:
<?php
namespace Libraries\Validarcontenido;
use AdminBundle\Entity\Aportes;
use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpFoundation\Request;
class Validarcontenido
{
private $request, $post, $em;
public function __construct()
{
$this->request = Request::createFromGlobals();
$this->post = $this->request->request->all();
// gets doctrine instance
$this->em = $this->getContainer()->get('doctrine');
}
}
And the services.yml:
# Learn more about services, parameters and containers at
# http://symfony.com/doc/current/book/service_container.html
parameters:
# parameter_name: value
services:
validarcontenido.service:
class: Libraries\Validarcontenido\Validarcontenido
arguments: [#doctrine.orm.entity_manager]
But Symfony returns me this error message:
Attempted to call an undefined method named "getContainer" of class "Libraries\Validarcontenido\Validarcontenido".
500 Internal Server Error - UndefinedMethodException
What i am doing wrong? Thank you so much.
You have to use the constructor to set the entity manager:
class Validarcontenido
{
private $request, $post, $em;
public function __construct(EntityManager $em)
{
$this->request = Request::createFromGlobals();
$this->post = $this->request->request->all();
$this->em = $em;
}
}
You need to create your class as a service in the service.yml as you already did, only you were almost there.
You need to change your class as this:
<?php
namespace Libraries\Validarcontenido;
use AdminBundle\Entity\Aportes;
use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpFoundation\Request;
class Validarcontenido
{
private $request, $post, $em;
public function __construct(EntityManager $em)
{
$this->request = Request::createFromGlobals();
$this->post = $this->request->request->all();
// gets doctrine instance
$this->em = $em;
}
}
Heres a working example (that provides the container): https://codedump.io/share/tpxgpEMJnaiW
Ok, the problem was that when i create the service instance in the controller i used this:
$my_class = new My_class();
And now i know that i have to use this:
$my_class = $this->get('service_name');
Thank you so much!

Injecting Handlers in Custom Widget

I have a handler classes, I need to inject it in the custom widgets.
I tried the bind() method in ClientModule class, but it is not getting injected.
What am I supposed to do, do get the class injected.
public class ExtendedTextBoxBase extends TextBox {
public ExtendedTextBoxBase() {
super.addBlurHandler(textBoxBlurHandler);
}
#Inject
TextBoxBlurHandler textBoxBlurHandler; /* custom handler */
}
custom handler:
public class TextBoxBlurHandler implements BlurHandler {
#Inject
public TextBoxBlurHandler() {
}
#Override
public void onBlur(BlurEvent event) {
}
}
Thanks,
Bennet.
Initial reaction: did you include and #Inject statement in the method (likely constructor) where you would like to inject the handler?
If yes: could you be more specific with some code snippets?
I see two potential errors:
1. You have code in constructor:
super.addBlurHandler(textBoxBlurHandler);
so you should inject handler by constructor not by field.
Gin first crate object than inject fields into class, so your handler textBoxBlurHandler is null.
2. You crate your ExtendedTextBoxBase by uibinder. If yes, you should add annotation uiField provided=true, and inject this field:
#Inject
#UiField(provided=true)
ExtendedTextBoxBase extendedTextBoxBase;

MongoDbBundle how to access manager in an arbitray class

in Symfony2 samples I can find how to access mongodb in from the Controller class:
$dm=$this->get('doctrine_mongodb')->getManager();
how to do it in an arbitray class?
You should use Dependency Injection to inject the doctrine_mongodb service into your class like this.
Create your class like this:
use Doctrine\Common\Persistence\ObjectManager;
class MyClass
{
protected $documentManager;
// ObjectManager is the interface used only for type-hinting here
// DocumentManager or EntityManager are the actual implementations
public function __construct(ObjectManager $om)
{
// The property $documentManager is now set to the DocumentManager
$this->documentManager=$om;
}
public function findSomething()
{
// now do something with the DocumentManager
return $this->documentManager->getRepository('YourBundle:SomeDocument')->findBy(array(/* ... */));
// ...
}
Then declare this class as a service:
# app/config/config.yml
services:
your_service_name:
class: Namespace\Your\SomeClass
arguments: ['#doctrine.odm.mongodb.document_manager']
In order to access your class from a controller it's service name to get it from the container (the DocumentManager will then be injected automatically into the constructor)
// Vendor/YourBundle/Controller/SomeController.php
public function doWhatever()
{
$myClassService = $this->get('your_service_name');
$something = $myClassService->findSomething();
}

how to inject a uiBinder with #Inject (instead of GWT.create())?

Firstly, is doing such thing a good practice ?
I tried what seems to be the right way for me but wasn't successful :
public class FormViewImpl extends CompositeView implements HasUiHandlers<C>, FormView {
public interface SettlementInstructionsSearchFormViewUiBinder extends UiBinder<Widget, SettlementInstructionsSearchFormViewImpl> {}
#Inject
static FormViewImpl uiBinder;
#Inject
static Provider<DateEditorWidget> dateEditorProvider;
#UiField(provided = true)
MyComponent<String> myComp;
#UiField
DateEditorWidget effectiveDateFrom;
// .. other fields
#Inject
public FormViewImpl () {
myComp = new MyComponent<String>("lol");
if (uiBinder == null)
uiBinder = GWT.create(SettlementInstructionsSearchFormViewUiBinder.class);
initWidget(uiBinder.createAndBindUi(this));
}
#UiFactory
DateEditorWidget createDateEditor() {
return dateEditorProvider.get();
}
}
What other things than a class with no arguments is required ? In my company's project the same kind of code works at some other place. Sorry from the high level of noob here...
If you guys had any pointers it would be nice.
Thanks
Two issues:
First, two of your #Inject fields are static - have you done anything to make static fields be injected? Static fields don't get set when Gin (or Guice) creates new instances, those have to be set once and done. As they are static, they will never be garbage collected - this may be okay with you, or it might be a problem, and you should change them to instance fields. If you want to keep them static, then you must invoke requestStaticInjection in your module to ask Gin to initialize them when the ginjector is created.
Next, if you do choose to remove static, the uiBinder field must still be null in that constructor, because the fields can't have been injected yet! How do you set a field on an object that you haven't yet created? That's what you are expecting Gin to be able to do. Instead, consider passing that as an argument into the #Inject decorated constructor. You don't even need to save it as a field, since the widget will only use it the one time.
To have a class generated by GIN (doesn't matter if it is a uiBinder or not) it is not necessary for it to have a default constructor (i.e. the one without parameters). The class you want to inject must have the constructor annotated with #Inject:
#Inject
public InjectMeClass(Object a, Object b)
The other class which is injected, suppose it is a UiBinder, must have the injected fields annotated with #UiField(provided=true):
public class Injected extends Composite {
private static InjectedUiBinder uiBinder = GWT
.create(InjectedUiBinder.class);
interface InjectedUiBinder extends UiBinder<Widget, Injected> {
}
#UiField(provided=true)
InjectMeClass imc;
public Injected(final InjectMeClass imc) {
this.imc=imc;
initWidget(uiBinder.createAndBindUi(this));
}
So, back to your case:
#UiField(provided = true)
MyComponent<String> myComp;
#Inject
public FormViewImpl (MyComponent<String> myComp) {
this.myComp = myComp;
and for example:
public class MyComponent<T> extends Composite {
private T value;
#Inject
public MyComponent(T t) {
this.value = t;
...
}
...
}
In the GIN module you can have a provider:
#Provides
#Singleton
public MyComponent<String> createMyComponent() {
return new MyComponent<String>("lol");
}