Symfony2 Entity method called in repository class - php

How can I call method from entity class in repository class.
I had tried to do something like this, but no success.
class ProfileConnectionsListRepository extends EntityRepository
{
public function connectionUserNames($userId)
{
$connections = $this->_em
->findOneBy(array('user1Id' => $userId))
->getUser2Id();
}
}
so if this is invalid can do something like that on doctrine way without using raw queries.

You might need to get repository first.
$connections = $this->_em
->getRepository(UserEntity::class)
->findOneBy(array('user1Id' => $userId))
->getUser2Id();

Related

Symfony 3.0: Reuse entity in repository

On my Symfony 3.0 project I have a Entity named ImageGroups and a repository I made ImageGroupsRepository that Use ImageGroups entity. I also made an Images entity with a ImagesRepository
In ImageGroupsRepository I have a method named getUserImageGroups and on ImagesRepository I have a method named add.
What I want to ask is How to use the getUserImageGroups method from ImageGroupsRepository into add from ImagesRepository?
The answer given by A.L is correct, I just wanted to offer an alternative method to access the entity manager without having to call the function again, via $this->_em:
class ImagesRepository extends EntityRepository
{
public function add()
{
$imagesGroups = $this->_em
->getRepository('AcmeBundle:ImageGroups')
->getUserImageGroups();
// …
}
}
If you look at the documentation for EntityRepository you'll see that the getEntityManager() function simply returns the protected $_em member of the EntityRepository class.
In your repository, you can get the entity manager with $this->getEntityManager(), this allow to call getRepository() in order to get another repository:
class ImagesRepository extends EntityRepository
{
public function add()
{
$em = $this->getEntityManager();
$imagesGroups = $em
->getRepository('AcmeBundle:ImageGroups')
->getUserImageGroups();
// …
}
}

Laravel eloquent build child object from parent with mongo

I am using laravel 5.1 and jenssegers mongodb and I am having some issues with such structure
class ServiceProvider extends Eloquent {
protected $collection = 'service_provider';
protected $connection = 'mongodb';
public static function factory($serviceId) {
switch ($serviceId) {
case self::SERVICE_PROVIDER_CHILD_CARE : {
return new ChildCareServiceProvider();
}
break;
}
}
public static get_by_service_id($service_id) {
return self::find($serviceId)->first();
}
}
class ChildCareServiceProvider extends ServiceProvider implements IServiceProvider
{
protected $collection = 'service_provider';
protected $connection = 'mongodb';
public function availabilityTimes()
{
return $this->hasMany('App\Models\ServiceProvider\ServiceProviderAvailabilityTime');
}
}
When I am saving or updating service provider I know what kind of service it is , so I can use factory method to get child and save it. But when I am getting service by id - I dont know service type yet, I only know its id. So I do have a method in ServiceProvider which makes query to mongo collection and getting record by its id. In this case that record will be an instance of object ServiceProvider. Is there an easy way to create ChildCareServiceProvider object from ServiceProvider object data? I tried something like
$data = ServiceProvider::find($serviceId)->first()->attributesToArray();
$serviceProvider = new ChildCareServiceProvider($data);
but in this case $serviceProvider object internal structure is little bit different in terms of its internal properties, which somehow affects my availabilityTimes relationship
I am sorta new to laravel and mongo, any advice would be greatly appreciated
Take a look at PHP's magic methods. What you can do is set the entity and then for example the __get() and __set() methods, set/get the value from/to the entity.

How to map Laravel/Eloquent results to custom class

I'm looking for a way to map the results of Laravel / Eloquent database queries to custom classes, rather than the default Eloquent class.
Does Laravel / Eloquent include any built-in facility for doing this? If not, is there a suitable place to 'hook' into the result generation code and do the necessary mapping?
As an example, this is roughly what I'd like to achieve:
class User extends Eloquent {}
class MyUser
{
protected $name;
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
return $this;
}
}
$users = User::all();
// $users should now contain an array of MyUser instances
Motivation / Reason for question
The motivation behind this question is to find a way in which queries can produce objects or arrays of objects that are completely framework-independent. This is because the Laravel app in question needs to be able to pass its results to other non-Laravel systems, so hence Plain Old PHP Objects (such as MyUser) make the most sense.
Laravel will not give you something like that, but you can do with PHP. Inject your Eloquent User class into your custom class, Laravel will inject it for you automatically. Use the object inside your class as you wish and, if you need to call one or another Eloquent method, you can just provide fallbacks to the Eloquent User object.
A good option is to use the repository pattern, where your class will expect to receive an implementation of a repository interface, for that you have to:
Create the interface for your user repository, all repositories, including your Eloquent model, must implement this interface. This is a contract to let you switch the implementation of the repository whenever you want, without having to touch your class. It also will make your class framework agnostic.
interface UserRepositoryInterface {
}
Your implementations of this repository could be:
class EloquentUser extends Eloquent implements UserRepositoryInterface {
}
class DoctrineUser extends DoctrineWhatever implements UserRepositoryInterface {
}
Create your class
class User extends Eloquent {}
class MyUser
{
protected $name;
public function __construct(UserRepositoryInterface $user)
{
$this->userRepository = $user;
}
public function __call($name, $arguments)
{
return call_user_func_array(array($this->userRepository,$name), $arguments);
}
public static function __callStatic($name, $arguments)
{
return call_user_func_array(array('User',$name), $arguments);
}
public function getName() {
return $this->userRepository->name;
}
public function setName($name) {
$this->name = $name;
return $this;
}
}
Now in Laravel to select the implementation you just have to
App::bind('UserRepositoryInterface', 'EloquentUser');
To switch to doctrine, you just have to
App::bind('UserRepositoryInterface', 'DoctrineUser');
And if you need to use this class outside Laravel, you just have to instantiate it, passing whatever implementation of the repository you want:
$user = new MyUser(new DoctrineUser);
No more ties to Laravel.
for Eloquent models, you might want to take advantage of ->toArray() method then typecast it using (object) to get POPO.
e.g.
$user = (object) User::find(1)->toArray();
print_r($user);
you should get:
stdClass Object
(
[id] => 1
[name] => John Doe
[email] => fakeuser0#mail.com
[active] => 1
...
[created_at] => 2017-10-26 17:45:53
[updated_at] => 2017-10-26 17:45:53
[deleted_at] =>
)
I also wanted to have custom class for this pre-defined class "User".
class User extends Model implements UserInterface, RemindableInterface {
to UserModel class:
class UserModel extends Model implements UserInterface, RemindableInterface {
So rather than hacking through the codes and classes, actually there is config for it.
Open app/config/auth.php
Make sure you change:
'model' => 'UserModel', // change to UserModel or your custom named class
'table' => 'User', // change if your table is non default "User"
It should be good to go.
:)

Zend framework 2 translator in model

How to get translator in model?
Inside view we can get translator using this code
$this->translate('Text')
Inside controller we can get translator using this code
$translator=$this->getServiceLocator()->get('translator');
$translator->translate("Text") ;
But how to get translator in model?
I'd tried so many ways to get service locator in models
2 of those
1)Using MVC events
$e=new MvcEvent();
$sm=$e->getApplication()->getServiceManager();
$this->translator = $sm->get('translator');
if i pring $sm it is showing null. but it works fine in Model.php onBootstrap
2)Created one model which implements ServiceLocatorAwareInterface
SomeModel.php
<?php
namespace Web\Model;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class SomeModel implements ServiceLocatorAwareInterface
{
protected $services;
public function setServiceLocator(ServiceLocatorInterface $locator)
{
$this->services = $locator;
}
public function getServiceLocator()
{
return $this->services;
}
}
and used that inside my model
$sl = new SomeModel();
$sm=$sl->getServiceManager();
var_dump($sm); exit;
$this->translator = $sm->get('translator');
this is also printing null.
If you don't need the servicemanager instance in your model, simply inject translator instance to it.
For example:
// Your model's constructor
class MyModel {
// Use the trait if your php version >= 5.4.0
use \Zend\I18n\Translator\TranslatorAwareTrait;
public function __construct( $translator )
{
$this->setTranslator( $translator );
}
public function modelMethodWhichNeedsToUseTranslator()
{
// ...
$text = $this->getTranslator()->translate('lorem ipsum');
// ...
}
}
When you creating your model first time on service or controller level
class someClass implements ServiceLocatorAwareInterface {
public function theMethodWhichCreatesYourModelInstance()
{
// ...
$sm = $this->getServiceLocator();
$model = new \Namespace\MyModel( $sm->get('translator') )
// ...
}
}
If you need to instantiate your model (new MyModel();) on multiple methods/classes, consider to writing a factory for it.
Here is a nice article about Dependency Injection and PHP by Ralph Schindler for more detailed comments about this approach.
For your Model class to be ServiceLocatorAware, you not only need to implement the interface, you also need to make your model a service of the service manager, and fetch the model from there.
Add your model to the service manager, since it doesn't appear to need any constructor params, it's invokable, so you can add it to the invokables array in service manager config. You can do that by using the getServiceConfig() method in your Module class...
class Module
{
public function getServiceConfig()
{
return array(
'invokables' => array(
'SomeModel' => 'Fully\Qualified\ClassName\To\SomeModel',
),
);
}
}
Then, instead of calling the new keyword to create your model instance, you fetch it from the service manager, for instance, by calling the getServiceLocator() method in a controller action...
public function fooAction()
{
$sm = $this->getServiceLocator();
$model = $sm->get('SomeModel');
}
When your model is fetched from the service manager, a service initializer will look to see if it implements the ServiceLocatorAwareInterface and automatically call setServiceLocator() if it does, passing it an instance of the service manager.

MVC, DI (dependency injection) and creating Model instance from Controller

My Dispatcher is "choosing" correct Controller; then creating Controller's instance (DependencyInjectionContainer is passed to Controller constructor); then calling some Controller's method...
class UserController extends Controller
{
public function __construct(DependencyInjectionContainer $injection) {
$this->container = $injection;
}
public function detailsAction() {
...
}
}
DependencyInjectionContainer contains DB adapter object, Config object etc.
Now let's see what detailsAction() method contains...
public function detailsAction() {
$model = new UserModel();
$model->getDetails(12345);
}
As you see I'm creating new instance of UserModel and calling getDetails methods.
Model's getDetails() method should connect to db to get information about user. To connect to DB UserModel should be able to access DB adapter.
What is the right way to pass DependencyInjectionContainer to the UserModel?
I think that this way is wrong...
public function detailsAction() {
$model = new UserModel($this->container);
$model->getDetails(12345);
}
Instead of injecting the entire DI Container into your classes, you should inject only the dependencies you need.
Your UserController requires a DB Adapter (let's call this interface IDBAdapter). In C# this might look like this:
public class UserController
{
private readonly IDBAdapter db;
public UserController(IDBAdapter db)
{
if (db == null)
{
throw new ArgumentNullException("db");
}
this.db = db;
}
public void DetailsAction()
{
var model = new UserModel(this.db);
model.GetDetails(12345);
}
}
In this case we are injectiing the dependency into the UserModel. In most cases, however, I would tend to consider it a DI smell if the UserController only takes a dependency to pass it on, so a better approach might be for the UserController to take a dependency on an Abstract Factory like this one:
public interface IUserModelFactory
{
UserModel Create();
}
In this variation, the UserController might look like this:
public class UserController
{
private readonly IUserModelFactory factory;
public UserController(IUserModelFactory factory)
{
if (factory == null)
{
throw new ArgumentNullException("factory");
}
this.factory = factory;
}
public void DetailsAction()
{
var model = this.factory.Create();
model.GetDetails(12345);
}
}
and you could define a concrete UserModelFactory that takes a dependency on IDBAdapter:
public class UserModelFactory : IUserModelFactory
{
private readonly IDBAdapter db;
public UserModelFactory(IDBAdapter db)
{
if (db == null)
{
throw new ArgumentNullException("db");
}
this.db = db;
}
public UserModel Create()
{
return new UserModel(this.db);
}
}
This gives you better separation of concerns.
If you need more than one dependency, you just inject them through the constructor. When you start to get too many, it's a sign that you are violating the Single Responsibility Principle, and it's time to refactor to Aggregate Services.
I'd use a singleton object for all config parameters :
You set it up in your bootstrap, then choose to use it directly or pass it as parameter in your objects.
The idea being to have one method all around to retrieve your config data.
You may then provide an abstract class for db manipulation which uses your config. singleton.
DependancyInjection can still be used to override your default data.
The above link in the comment (possible 'duplicate') concludes on using constructor injection : this is close to your current method.
However if I try to figure how your model works, I guess you will have many other model classes other than "userModel". Thus an abstract class using a config singleton might be a good solution : all your next model classes will just extend this abstract class, and you don't have to worry about your config.
On the other hand, your solution is good to me as long as your dependanceInjectionContainer changes often.

Categories