Call repository method from entity - php

Is it possible to call repository method on entity?
I mean something like this
$article = $em->getRepository('Entities\Articles')->findOneBy(array('id' => $articleId));
$category = $em->getRepository('Entities\Categories')->findOneBy(array('id' => 86));
$article->addArticleToCategory($category);
Where addArticleToCategory is method in repository (just an example code)
public function addArticleToCategory($category){
$categoryArticles = new CategoryArticles();
$categoryArticles->setArticle(!!/** This is where I want to have my variable $article from this method call **/!!);
$categoryArticles->setCategory($category);
$this->getEntityManager()->persist($categoryArticles);
$this->getEntityManager()->flush();
}
What is the best way to do it?
Also I want to know is it a good practice to put custom set/create methods in repository?

By definition you can't call a method of your repository class from an entity object... This is basic object-oriented programming.
I think you should create addArticle function in the Category entity, something like this:
function addArticle($article)
{
$this->articles[] = $article;
$article->setCategory($this);
}
And then you do
$article = $em->getRepository('Entities\Articles')->findOneBy(array('id' => $articleId));
$category = $em->getRepository('Entities\Categories')->findOneBy(array('id' => 86));
$category->addArticle($article);
$em->persist($category);
$em->flush();
If the cascades are correctly configured, this will work

You can write your own repository manager and create a method for your needs.
http://docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html#custom-repositories

Related

How to use an Interface Repository in a Laravel Nova Action?

I'm using the Laravel Repository Pattern to manage my resources and I was wondering how can I use an interface inside a Nova Action? Since an Interface cannot be instanciated, I was wondering how I could use my Interfaces within my action?
In my Controller constructor I create my repository and then I'm able to use it within my functions, but I can't figure out how to do the same thing inside a Laravel Action.
Any idea how I could do this?
An example in my Controller
private $myRepository;
public function __construct(
MyRepositoryInterface $myRepository,
)
{
$this->myRepository = $myRepository;
}
And then inside a function I can do something like
public function destroy($id)
{
$this->myRepository->delete($id);
return response()->json( array("message" => "success") );
}
Now in my Nova Action, here's what I'm trying to do
public function handle(ActionFields $fields, Collection $models)
{
foreach ($models as $model)
{
$myRepository = new MyRepositoryInterface(); // This doesn't work obviously
$myRepository->customManipulation($model->id);
$this->markAsFinished($model);
}
}
Any idea how I could use my repositories?
Thanks!
You can do $myRepository = App::make(MyRepositoryInterface::class);, IoC will resolve it and will instantiate a class instance.
I assume you have already bound the class to the interface:
App::bind('MyRepositoryInterface', 'MyRepository');

Symfony2 Entity method called in repository class

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();

Populate entity from data array without form/request

Just wondering if it is possible to only use some parts of the symfony form handling. For exampe, when creating CRUD actions via generate:doctrine:crud I get something in my Controller (for handling create User POST requests) that looks like this:
$entity = new User();
$form = $this->createForm(new UserType(), $entity,
array(
'action' => $this->generateUrl('user_create'),
'method' => 'POST',
));
$form->handleRequest($request);
//Here I have a filled Entity
But what I want is to have this in a more reusable solution. Currently I have my business logic in a service called UserModel. Here I also want to have the create method to create, validate and persist a new entity. Tough the UserModel should also be callable from some Command scripts via the console, so I probably won't always have Request nor a Form.
So now from the above code I know that Symfony is already somehow populating data to an Entity according to the UserType definition, but how could I do that manually without having a Form or a Request and instead just some array of data?
So that I don't have to take care of setting the properties myself.
Edit:
The validation is no issue for populating the entity, I'm using the validator later on the populated entity before persisting the data.
And also important for me would be that the passed related entity ids will be handled/loaded automatically.
you may still use the Form component, but instead of using handleRequest, you should use directly submit.
If you are curious, you should look up the code on github for both handleRequest and what it actually does ; you'll see that it just do some verification, takes the data from the Request, and then uses the submit method of the Form.
So, basically, you can use only the submit method with the data you wish to use. It even validates your entity. :)
UPDATE
And for the concern of creating / updating related entities, if your relation have a persist / update cascade, it should roll out from itself without you doing a single thing, except persist + flush on your main entity.
If you do not worry about handling validation like things, you can do something like I have done.
You can define a trait or include the fromArray function in your entity classes.
trait EntityHydrationMethod
{
public function fromArray($data = array())
{
foreach ($data as $property => $value) {
$method = "set{$property}";
$this->$method($value);
}
}
}
If you defined trait, you can use it in your entities like:
class User{
use EntityHydrationMethod;
}
Then from your user model you can define your create function something like:
public function create($data = array())
{
$entity = new User();
$entity->fromArray($data);
return $entity;
}
-Updated-
As you updated your question. you may achieve this by defining a trait or include the createFromArray function in your EntityRepository classes.
trait RepositoryCreateMethod {
public function createFromArray($data)
{
$class = $this->getClassName();
$object = new $class();
$meta = $this->getClassMetadata();
foreach ($data as $property => $value) {
$v = $value;
if(!empty($value) && $meta->hasAssociation($property)) {
$map = $meta->getAssociationMapping($property);
$v = $this->_em->getRepository($map['targetEntity'])->find($value);
if(empty($v)){
throw new \Exception('Associate data not found');
}
}
$method = "set{$property}";
$object->$method($v);
}
return $object;
}
}
If you defined trait, you can use it in your Repository like:
class UserRepository{
use RepositoryCreateMethod;
}
Then you can use this something like call from controller:
$user = $this->getDoctrine()
->getRepository('YourBundle:User')
->createFromArray($data);

How can i put where clause in symfony repository query in controller

Initially I am using this
$entities = $em->getRepository('AcmePanduBundle:Checklist')->findAll();
Now I want that if pid variable is present then it should filter the query with something
$entities = $em->getRepository('AcmePanduBundle:Checklist')->findAll('where pid=1')
and if its not present then findAll should work.
Can I do that in controller or do I have to make a custom function in repository class?
Of course you can do that in the controller:
$entities = (isset($pid))
? $em->getRepository('AcmePanduBundle:Checklist')->findByPid($pid)
: $em->getRepository('AcmePanduBundle:Checklist')->findAll();
However, this is the type of thing that custom repositories were made for. If you plan on replicating this logic in more than one place, I'd definitely create one.
It would look something like:
// src/Acme/PanduBundle/Repository/ChecklistRepository.php
namespace Acme\PanduBundle\Repository;
use Doctrine\ORM\EntityRepository;
class ChecklistRepository extends EntityRepository
{
public function findAllWithOptionalPid($pid = null)
{
if($pid)
return $this->findByPid($pid);
return $this->findAll();
}
}
...and don't forget to reference this repository in your Doctrine configuration. Don't know what method you're using for configuration (xml, yml, annotations), but here's the documentation for that: http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes
Once that's done, any controller calling $em->getRepository('AcmePanduBundle:Checklist')->findAllWithOptionalPid($pid); will work as you expect it to, with or without the $pid variable.
Use findBy or dynamic methods like "findByPid"
$repository = $em->getRepository('AcmePanduBundle:Checklist');
if ($pid) {
$entities = $repository->findBy(array('pid' => $pid));
// or: $entities = $repository->findByPid($pid);
} else {
$entities = $repository->findAll();
}

How can I use doctrine find method in repository

This code is working fine in controller
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('AcmeUserBundle:Child')->find($id);
Now I have custom Repository class
I want to know that how can use that in there
function getUser()
{
$em = $this->getEntityManager();
$entity = $em->getRepository('AcmeUserBundle:Child')->find($id);
}
Do I still need to use getRepository in Repository as well or not?
If the method is in Repository class, then you could just use $this.
$enity = $this->find($id);

Categories