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();
}
Related
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 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']
In my application, I have a service that requires a constructor parameter not resolved by Autofac, that I instantiate using a delegate factory:
public class Service
{
public Service(string parameter /*, ... other dependencies */)
{
}
public delegate Service Factory(string parameter);
}
This works great! I really love this feature.
I also like the Controlled Lifetime relationship, so I can let my component depend on a Func<Owned<ISomething>> like this:
public class Component
{
private Func<Owned<ISomething>> _somethingFactory;
/* constructor omitted for brevity */
public void DoSomethingUseful()
{
using (var ownedSomething = _somethingFactory())
{
/* Lots of useful code here */
}
}
}
My problem is that now I want to combine the two. I can't have an instance of Func<Owned<Service>> injected, because it needs that parameter, so my current solution is to abstract the factory away into another service, say IServiceFactory:
public interface IServiceFactory
{
Service Create(string parameter);
}
...implemented as such:
public class ServiceFactory : IServiceFactory
{
private Service.Factory _internalFactory;
public ServiceFactory(Service.Factory internalFactory)
{
_internalFactory = internalFactory;
}
public Service Create(string parameter)
{
return _internalFactory(parameter);
}
}
My component then becomes this:
public class Component
{
Func<Owned<IServiceFactory>> _serviceFactoryFactory;
/* ... */
}
The need for such a field name leaves a bad taste in my mouth to the point that I suspect there must be a cleaner way to handle this case.
Is there another way?
You could change your injected factory to include the string parameter:
private Func<string, Owned<ISomething>> _somethingFactory;
Then you can pass the string to the factory when you want to create a new instance:
public void DoSomethingUseful()
{
using (var ownedSomething = _somethingFactory("my parameter"))
{
/* Lots of useful code here */
}
}
I've created a .NET Fiddle with a small working sample.
If there is #inject, then it means there must be #provide?
inject field gets its value from #provide method of module?
Yes if you use Module
#Module
public class SomeModule {
#Provides
Unscoped unscoped() {
return new Unscoped();
}
#Provides
#Singleton
Scoped scoped() {
return Scoped();
}
}
BUT classes with #Inject constructor get automatically appended to your scoped component even if no module is specified for it:
#Singleton
public class Scoped {
#Inject
public Scoped() {
}
}
public class Unscoped {
#Inject
public Unscoped() {
}
}
If there is #Inject annotation then it's dependency can be provided in two ways :
By Using Provides annotation in module
#Provides
TasksPresenter provide TasksPresenter(TasksRepository tasksRepository, TasksContract.View tasksView) {
return new TasksPresenter(tasksRepository,tasksView);
}
By Using Constructor Injection
#Inject
TasksPresenter(TasksRepository tasksRepository, TasksContract.View tasksView) {
mTasksRepository = tasksRepository;
mTasksView = tasksView;
}
One thing to observe here is Constructor Injection solve two thing
Instantiate object
Provides the object by adding it to Object graph.
According to this blog post it should be possible to have an init() method within the model. Like this:
class MyModel
{
public function init()
{
// prepare something
}
...
}
This does not work for me. Does anybody know if I have to set somewhere a parameter (e.g. in the config file) or if this is not possible any more in my Zend FW version (1.11.4)? I checked with error_log('something') within the init method and it does not get called at all.
UPDATE:
I have extended Adam's solution a little:
public function __construct() {
if (get_parent_class($this) != false) {
parent::__construct();
}
if(method_exists($this, 'init')) {
$this->init();
}
}
This way it can be placed in a base class and then extended. Just in case someone needs the same solution later too.
That post is very misleading. If the model classes in the application extend Zend_Db_Table or Zend_Db_Table_Row, which is not the case in the post's examples but is implied from the text, then yes you can add an init() method that will be called automatically. For this to work in your application you would need to be calling the method from whatever creates your models, or from the constructor of a base class.
Try adding a call to init() from the constructor as so:
public function __construct()
{
parent::__construct();
$this->init();
}
you have that problem because a php class does not have an init method. That init method is only applicable to Zend classes. Which mean you can only use it when you extend a Zend class. Which means you are actually overriding the init method.
E.g. here it is in the Zend_Db_Table_Abstract class:
/**
* Initialize object
*
* Called from {#link __construct()} as final step of object instantiation.
*
* #return void
*/
public function init()
{
}
So if you change your model to extend zend it will work:
class MyModel extends Zend_Db_Table_Abstract
{
public function init()
{
// prepare something
}
...
}
It's the same with Zend_Controller_Action, which is why you can also use it in your controllers.