getEntityManager() and getDoctrine() in Symfony2 - symfony

Is there any difference between these two statements:
$this->getDoctrine()->getEntityManager()->getRepository();
$this->getDoctrine()->getRepository();
Does the difference relate to any OOP concept I am missing out?

In general, no difference, since
$this->getDoctrine()->getRepository();
is just a helper for
$this->getDoctrine()->getEntityManager()->getRepository();
You can have several entity managers, and then there will be a slight difference in getting a repository from one:
$this->getDoctrine()->getRepository($entityName, $enityManagerName);
$this->getDoctrine()->getEntityManager($entityManagerName)->getRepository($entityName);
But again, no difference in the result you'll get.
All other things being equal, I'd go with the shortest one.

The result is the same, but if you need the entityManager for more than just getting the repository, it might be handy to store it and then recieve the repository as well as do other operations such as flush:
$_em = $this->getDoctrine()->getEntityManager();
$repository = $_em->getRepository();
//...
$_em->flush();
As said before, if you only need to get the Repository, go with the second statement, which is shorter and as easy to read as the first one.

There is no difference. If you look at the source code of AbstractManagerRegistry.php. You can see this code:
public function getRepository($persistentObjectName, $persistentManagerName = null)
{
return $this->getManager($persistentManagerName)->getRepository($persistentObjectName);
}
As you can see, when you call getRepository(), it first calls getManager() and then getRepository(). I would suggest using the second one as it gives intellisense in IDEs such as PHPStorm. Hope it helps.

Related

how to start one flux after completion of another?

how can i start Flux after completion of Flux? Flux doesn't depend on result of Flux.
I thought operation then() should do the work, but it just return mono. So what is the correct operator?
Flux.thenMany is the operator that you need
abstract Flux<Integer> flux1();
abstract Flux<String> flux2();
public Flux<String> flux2AfterFlux1(){
return flux1().thenMany(flux2());
}
My reply is late, so you have probably either figured this out, or moved on. I need to do the same thing, so I seem to have achieved this by using Flux.usingWhen(). I need to obtain IDs from my database that exhibit a certain property. After retrieving these IDs, then I need to get some information about these IDs. Normally, a join would work, but I am using MongoDB, and joins are horrible, so it is better to do separate, sequential queries. So let's say I have a Mongo reactive repository with a method called Flux<String> findInterestingIds(). I have another method in the same repository called Flux<String> findInterestingInformation(String[] interestingIds) that I need to feed the IDs found in the call to the previous method. So this is how I handle it:
Mono<List<String>> interestingIdsMono = myRepo.findInterestingIds()
.collectList();
Flux.usingWhen(interestingIdsMono,
interestingIds -> myRepo.findInterestingInformation(interestingIds),
interestingIds -> Flux.empty().doOnComplete(() -> log.debug("Complete"));
The cleanup function (third parameter) was something that I don't quite yet understand how to use in a good way, so I just logged completion and I do not need to emit anything extra when the flux completes.
ProjectReactor used to have a compose function that is now called transformDeferred, and I had some hopes for that, but I do not quite see how it would apply in this type of situation. At any rate, this is my attempt at it, so feel free to show me a better way!

Discouraged Class Usage PHPCS

Let's say I have these classes:
Old_Class
New_Class
If this exists ->something(new Old_Class()) or Old_Class::staticMethod() or $oldClass->methodCall() I want a code sniff to warn "Old_Class usage found, recommend using New_Class instead".
I found this sniff Generic.PHP.ForbiddenFunctions but it only seems to catch built-in php functions is_array, is_null, etc.
Do I need to write a custom sniff for this?
If so, what token should I added to the register() function to catch on?
I couldn't use a built-in one. I had to write one using T_STRING.
public function register()
{
return [
T_STRING,
];
}
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if ($tokens[$stackPtr]['content'] === 'Old_Class') {
$error = 'Old_Class usage found, consider using New_Class instead.';
$phpcsFile->addWarning($error, $stackPtr);
}
}
I know this is a fairly old question, but there are two possible solutions I'm aware of:
The Slevomat coding standard for Codesniffer includes a sniff to report usage of any of an array of forbidden classes
Static analysis tools are another approach for this. If you mark a class with the #deprecated annotation, I know from personal experience that Psalm will flag it with the DeprecatedClass issue, and if you can't fix them all at once, you can add them to the baseline, which will suppress the issue, but keep track of it, so you can still use Psalm in continuous integration and not break on existing issues. I believe PHPStan has similar functionality.

Trying to add virtual property to query result in Symfony2 with JMS

I have a simple task ahead of me, yet I find myself pretty much incapable of completing it.
My model is pretty complex, so I'll try to simplify for the sake of being specific.
I have two entities, Call and Caller, with entity repositories that I access via custom services. I am using JMS Serializer Bundle. All entities are mapped correctly, the the whole thing is working pretty fine. But I have this idea that I just can't make happen. To the point...
These are my entities described:
--Call--
#call_id
location
date_created
Caller
--Caller--
#caller_id
phone_num
The idea is to have a list of all calls with their fields for example:
New York, 2015.12.12. 20:07:06, Novak Djokovic, 3816976548 [YY]
London, 2015.12.13. 20:07:06, Jelena Jankovic, 3811116333 [XX]
Fields YY and XX represent the number of calls already in a database with that specific number.
I have a query that returns the list without YY and XX values, and I also have a separate query that returns number of calls from a specific number. The thing gets complicated when I try to join them. Not sure how to do that.
I read about VirtualProperty annotation for JMS, but failed to actually see how to use it this time (since it's not a good practice to access your repository or service from an Entity).
These are my methods:
1 - get list of all calls with callers
public function findAllCalls()
{
$callerAlias = "c";
//getAlias method returns the alias of the current entity (call)
$qb = $this->createQueryBuilder($this->getAlias());
$qb->leftJoin($this->getAlias() . '.caller', $callerAlias);
return $qb->getQuery()->getResult();
}
2 - get number of calls from a specific number based on a call as a parameter
public function getNumberOfCalls(Call $call) {
$callerAlias = "c";
$qb = $this->createQueryBuilder($this->getAlias());
$qb->leftJoin($this->getAlias() . '.caller', $callerAlias);
$qb->select("COUNT(" . $this->getAlias() . ".call_id)");
$qb->where($callerAlias.".phonenbr = ".$call->getPhoneNumber());
return $qb->getQuery()->getScalarResult();
}
Hoping to hear your opinions on this, 'cause I really struggled to find the sollution.

Symfony2 $em->createQuery() also selects removed objects

Foreword: My script is a bit complicated so I try to reduce the complexity down to a simple example.
Imagine we have an entity "company". We have also a repository-function that looks like this:
public function delete(){
// get company-objects to delete
[...]
// delete some companies
$this->getEntityManager()->remove($company1);
$this->getEntityManager()->remove($company2);
// do other things
[...]
// get companies via createQuery (I really need to do it via
// createQuery because of different reasons that would be too
// complicated to explain for this problem)
$query = $this->getEntityManager()
->createQuery('
SELECT company
FROM MyOwnBundle:Company company
WHERE [...irrelevant...]
');
$companies = $query->getResult();
dump($companies);
exit;
}
The problem: The createQuery also selects the removed companies.
My thoughts:
I thought that the entityManager knows that the companies are removed and therefore doesn't select them in a query. But this thought was wrong... (But why is this? Isn't the entityManager a global singleton-object?)
I know that when I would persist the data with flush() before using createQuery the results would be fine. But I can't persist the data here because then the whole process wouldn't be in a transaction.
I also can't manipulate the where-part of createQuery to exclude the already deleted companies because the whole process is separated into many functions and it would be hard to transport an array with the removed companies through the whole process.
The Question: How can I get the companies via createQuery without the removed ones?
You could wrap your code like below to make your whole process be in a transaction. This way you could flush right after remove the data.
$this->getEntityManager()->transactional(function($em) {
// put your code here
// $em is instanceof EntityManager
});

Readable exception information when testing DateTime objects in PHPUnit

When testing DateTime objects in PHPUnit (3.7.22), I am making the assertion like this:
$this->assertEquals(date_create('2014-01-01'), $myobject->getDate());
Works nicely till you get an exception, and the exception in not clear enough (like for primitives where is clearly states for example that 1 does not equal the excepted 2).
PHPUnit_Framework_ExpectationFailedException : Failed asserting that two objects are equal.
I could pass the $message parameter to the assertEquals method, with a string containing the object value, but I feel it could go easier.
Any ideas?
You could do something like
$expected_date = new DateTime('2014-01-01');
$this->assertEquals($expected_date->format('Y-m-d'), $myobject->getDate()->format('Y-m-d');
This would make you error message say something like "failed asserting that '2014-02-03 matches expected 2014-01-01'
I had a poke around the phpUnit source, and don't see any hook to allow better display. What I usually do is what you already mention in your question:
$this->assertEquals(date_create('2014-01-01'), $myobject->getDate(), print_r($myobject,true) );
OR:
$this->assertEquals(date_create('2014-01-01'), $myobject->getDate(), print_r($myobject->getDate(),true) );
depending on which is more useful, case-by-case.
I do this anyway, because often I want to include other helpful data in the message, perhaps some previous calculations, to give it context. I.e. to know why a test is failing I often need to know more than just the two objects that should've been equal.

Resources