Doctrine discriminator is not discriminating - doctrine

DQL Code:
$dql = "SELECT a, FIELD(a.id, ".$implodedIds.") as HIDDEN field "
. "FROM \activity\models\Entities\Activity a "
. "WHERE a.id IN (".$implodedIds.") "
. "ORDER BY field ASC ";
$em = \Zend_Registry::get('em');
$doctrineConfig = $em->getConfiguration();
$doctrineConfig->addCustomStringFunction('FIELD', 'DoctrineExtensions\Query\Mysql\Field');
$query = $em->createQuery($dql);
$docResults = $query->getResult();
General Gist of Entity Structure: (Single Table Inheritance)
Activity
Opinion extends Activity
Comment extends Activity
Counter extends Activity
This dql code is returning Activity entities, however I want it to automatically discriminate the entities it returns into Opinions, Comments, and Counters. Doctrine does this without any issues in other instances, but not here for some reason. (I.E. in other cases where I make a query asking for Activity, it gives me an array of Opinions, Comments and Counters)
Can anybody tell me why this time, it's not discriminating them automatically?

You ask the "activities", and he returns to them! According to your schema options are "activities" ... If you ask your options, you are more specific, and not get the other children of "activity" ... So to differentiate, use "instanceOf"!

Related

Laravel relationship gives me "?" instead of email

I'm setting this relationship
public function nonAcceptedContracts()
{
return $this->belongsToMany(UserContract::class, 'invite', 'email', 'usercontract')->where('status', 'pending');
}
And calling it like that.
$user->loadMissing('nonAcceptedContracts');
dd($user->nonAcceptedContracts()->toSql());
What I get is
"select * from `usercontract` inner join `invite` on `usercontract`.`id` = `invite`.`usercontract` where `invite`.`email` = ? and `status` = ? and `usercontract`.`deleted_at` is null"
The query seems to be the one I'm looking for but why do I get this question mark there? Shouldn't be there the email of my user model? Also the "status" value, should be "pending" and there is another question mark.
That's just how toSql() works. What you are seeing is a parameterized query. These parameterized queries allow type-specific value when replacing the ? with their respective value. They are frequently used when executing dynamic SQL from a program.
You can read more on this topic here: https://scotch.io/tutorials/debugging-queries-in-laravel
If you really want to see the actual queries, try enabling the query log. One thing to note here is that this logfile can grow very large on a busy server.

Doctrine where condition for many to one

I have a many to one association mapping where many Exams have one subject
If I have to update marks property of all subject with exam id xxxx
I use
Update namespace/Exam e set e.marks = 4 where e.subject.id = xxxx
it is not working
can you please he
help me to do that in a proper way ?
You can not access e.subject.id without a join in your query. But a join is not possible in a Doctrine update statement, since its MySQL specific.
What should work is to compare the whole entity:
$subject = $this->getEntityManager()->getRepository('namespace\subject')
->find(xxx);
$query = $this->getEntityManager()->createQueryBuilder()
->update('namespace\Exam', 'e')
->set('e.marks', '4')
->where('e.subject = :subject')
->setParameter('subject', $subject);
Or, if you don't want to have another database query and the primary key of your subject entity consists only of one column (e.g. id), you could also compare with this primary key:
$query = $this->getEntityManager()->createQueryBuilder()
->update('namespace\Exam', 'e')
->set('e.marks', '4')
->where('e.subject = :id')
->setParameter('id', xxx);
Also have a look at this question, the user wasn't able to join in his update statement too.
Edit: added more general approach

SimpleJpaRepository Count Query

I've modified an existing RESTful/JDBC application i have to work with new features in Spring 4... specifically the JpaRepository. It will:
1) Retrieve a list of transactions for a specified date. This works fine
2) Retrieve a count of transactions by type for a specified date. This is not working as expected.
The queries are setup similarly, but the actual return types are very different.
I have POJOs for each query
My transactions JPA respository looks like:
public interface MyTransactionsRepository extends JpaRepository<MyTransactions, Long>
//My query works like a charm.
#Query( value = "SELECT * from ACTIVITI_TMP.BATCH_TABLE WHERE TO_CHAR(last_action, 'YYYY-MM-DD') = ?1", nativeQuery = true )
List< MyTransactions > findAllBy_ToChar_LastAction( String lastActionDateString );
This returns a list of MyTransactions objects as expected. Debugging, i see the returned object as ArrayList. Looking inside the elementData, I see that each object is, as expected, a MyTransactions object.
My second repository/query is where i'm having troubles.
public interface MyCountsRepository extends JpaRepository<MyCounts, Long>
#Query( value = "SELECT send_method, COUNT(*) AS counter FROM ACTIVITI_TMP.BATCH_TABLE WHERE TO_CHAR(last_action, 'YYYY-MM-DD') = ?1 GROUP BY send_method ORDER BY send_method", nativeQuery = true )
List<MyCounts> countBy_ToChar_LastAction( String lastActionDateString );
This DOES NOT return List as expected.
The object that holds the returned data was originally defined as List, but when I inspect this object in Eclipse, I see instead that it is holding an ArrayList. Drilling down to the elementData, each object is actually an Object[2]... NOT a MyCounts object.
I've modified the MyCountsRepository query as follows
ArrayList<Object[]> countBy_ToChar_LastAction( String lastActionDateString );
Then, inside my controller class, I create a MyCounts object for each element in List and then return List
This works, but... I don't understand why i have to go thru all this?
I can query a view as easily as a table.
Why doesn't JPA/Hibernate treat this as a simple 2 column table? send_method varchar(x) and count (int or long)
I know there are issues or nuances for how JPA treats queries with counts in them, but i've not seen anything like this referenced.
Many thanks for any help you can provide in clarifying this issue.
Anthony
That is the expected behaviour when you're doing a "group by". It will not map to a specific entity. Only way this might work is if you had a view in your database that summarized the data by send_method and you could map an entity to it.

Linq: Polymophic entity fetch in select list

I want to do the following...
FROM o IN orders
SELECT new OrderContainer { Contact = (PostalContact) o.Contact }
So hopefully you can see that the order's 'Contact' will be of a derived type. Unfortunately however it doesn't seem to do a polymorphic fetch! Is there anyway of achieving this?
Cheers, Ian.
Try using the extention method .OfType()
from o in orders
select new OrderContainer { Contact = o.Contact.OfType<PostalContact>().FirstOrDefault() }
Edit:
a way to get the full object data, but i doubt that this is good enough for your needs.
from c in contacts.OfType<PostalContact>()
where c.Orders.Any(o=>o.Contact.Id == c.id)
select new OrderContainer { Contact = c }
on the other hand, if you set the base class (entity) to abstract, you may find that entity will load the full objects. but this is not recomended due to the queries that are generated. if you are looking into this you may want to look at (TPH) Table per Hierarchy for your contacts

Doctrine toarray does not convert relations

I followed doctrine documnetation to get started. Here is the documentation.
My code is
$User = Doctrine_Core::getTable("User")->find(1);
when I access relations by $User->Phonenumbers, it works. When I convert User object to array by using toArray() method, it does not convert relations to array. It simply display $User data.
Am I missing something?
By using the find method you've only retrieved the User data which is why the return of toArray is limited to that data. You need to specify the additional data to load, and the best place to do this is usually in the original query. From the example you linked to, add the select portion:
$q = Doctrine_Query::create()
->select('u.*, e.*, p.*') // Example only, select what you need, not *
->from('User u')
->leftJoin('u.Email e')
->leftJoin('u.Phonenumbers p')
->where('u.id = ?', 1);
Then when toArray'ing the results from that, you should see the associated email and phonenumber data as well.
I also noticed an anomaly with this where if you call the relationship first then call the ToArray, the relationship somehow gets included. what i mean is that, taking your own eg,
$User = Doctrine_Core::getTable("User")->find(1);
$num= $User->Phonenumbers->office; // assumed a field 'office' in your phone num table
$userArray = $user->toArray(true);
In the above case, $userArray somehow contains the whole relationship. if we remove the $num assignment it doesn't.
am guessing this is due to doctrine only fetching the one record first, and it's only when you try to access foreign key values that it fetches the other related tables

Resources