Get entity proxy in Doctrine2 - doctrine-orm

I have an entity Dog with OneToOne relation to Collar.
Say I create a new Dog entity and I have the Collar id I want to relate to it. Not the Collar object itself, only it's id number.
$collar = 12;
$dog = new Dog();
$dog->setCollar(?);
Do I need to actually fetch the Collar object from the DB, only to set it's id (which is already given), or is there a way to create a proxy Collar object?

Yes there actually is
You can use your entity manager to get a Proxy Reference instead of an actual Entity which just gives you a proxy object representing the Entity without actually fetching it from the database.
Check the code below for an example
$collarId = 12;
// First param is the Entity classname, second is the Entity id
$collar = $entityManager->getReference('Collar', $collarId);
$dog = new Dog();
$dog->setCollar($colar);
$entityManager->persist($dog);
$entityManager->flush();

Related

Add properties to Google Datastore entity dynamically

I have a below use case:
I have a method that accepts a list of strings. For each of the strings, I need to create a property under an existing google data store entity A
Example: I have an existing entity Person with properties fname and lname.
If the input list has strings - address, city, I need to update the entity Person to include these new properties address and city.
I'm coding this use case in Python. Any suggestions on how I can achieve this?
So the best way to do this is to let your class inherit ndb.Expando. The difference between Expando and Model is that you can always add attributes to an Expando entity and be able to store it in the Datastore.
Knowing this, there are several ways to proceed, but I am guessing you’re also going to need to use Python’s setattr(object, name, value) method to pass the attribute name from a string.
Take a look at the Expando model class: https://cloud.google.com/appengine/docs/standard/python/ndb/creating-entity-models#creating_an_expando_model_class
class Person(ndb.Expando):
pass
person = Person(fname='some', lname='body')
person_key = person.put()
...
person = person_key.get()
person.city = 'San Francisco'
person.address = '1234 Main St.'
person.put()

Google App Engine KeyProperty

what's the benefits of KeyProperty ? if i can connect two entity using user_id and id
class User(ndb.Model):
name = ndb.StringProperty()
class Attend(ndb.Model):
user_id = ndb.IntegerProperty()
date = ndb.DateProperty()
User(id=1,name="xyz)
Attend(user_id = 1, date = "xyz")
There are a couple of minor benefits of storing a KeyProperty over an ID:
It is easier to do x.user_key.get() than ndb.Key(Attend, x.user_id).get()
The key is fully specified so there is no doubt about the entity it refers to but for the ID you also need to know the entity type.
These are both really minor so you can do either one. I sometimes store keys and sometimes store IDs based on other factors.

how to copy an object using multi table inheritance in django

I am trying to copy an object that extends another object through multi table inheritance.
The parent is Group and the child is Location
The problem is that the parent object is changed instead of creating a new parent and child object.
Here is what I am doing:
location = get_object_or_404(Location, pk=pk)
location.pk = None
location.name = location.name+' - child object'
location.save()
Instead of creating a new location and group row in their respective tables, this updates the group table to have the name = name + ' - child object'.
how can I have this process create a new location and group row instead of updating the Group row?
Thanks!
The key here is that multi-table inheritance in Django is implemented using foreign keys, so an object that "inherits" another model is simply ForeignKey'ed to that other model. You'll need to duplicate both.
For how to do so, check out the solution in this answer.

Doctrine - QueryBuilder, select query with where parameters: entities or ids?

I have a Product entity and a Shop entity.
A shop can have 0 to n products and a product can be in only one shop.
The product entity table is thus refering to the Shop entity through a shop_id table field.
When querying for the products of a given shop using doctrine query builder, we can do this:
$products = $this->getDoctrine()->getRepository('MyBundle:Product')
->createQueryBuilder('p')
->where('p.shop = :shop')
->setParameter('shop', $shop) // here we pass a shop object
->getQuery()->getResult();
or this:
$products = $this->getDoctrine()->getRepository('MyBundle:Product')
->createQueryBuilder('p')
->where('p.shop = :shopId')
->setParameter('shopId', $shopId) // we pass directly the shop id
->getQuery()->getResult();
And the both seem to work... I'm thus wondering: can we always pass directly entity ids instead of entity instances in such cases (ie: on a doctrine entity field that refers to another entity)?
I initially thought that only the first example would work...
According to the Doctrine documentation, you can pass the object to setParameter() if the object is managed.
extract from the documentation:
Calling setParameter() automatically infers which type you are setting as value. This works for integers, arrays of strings/integers, DateTime instances and for managed entities.
for more information, please see:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/query-builder.html#binding-parameters-to-your-query
I might be wrong, but I think that if you pass object instance instead of id number, Doctrine will automatically call $instance->getId() making your two queries the same when translated into SQL (even DQL).

How to convert entity leaving it id

There are some entities (Region, Country, City) which used STI (or even CTI). How it possible convert Country to City leaving old id?
This is not supported in Doctrine 2 because type casting user objects is not supported by PHP.
With that said, Doctrine uses the discriminator column to determine what type of object to hydrate. If you change the value of the discriminator column in the database with a SQL UPDATE, the object type will be changed the next time the object is loaded. This works for STI, but CTI would be more complicated.
It may not be possible by standard using Doctrine, but you can work around it.
If you use the Class Metadata you can select your discriminator column.
Take a look at the Trait that I've created to solve the problem within my app:
namespace App\Doctrine\Repository;
trait DiscriminatorTrait
{
abstract public function getClassMetadata();
abstract public function getEntityManager();
private function updateDiscriminatorColumn($id, $class)
{
$classMetadata = $this->getClassMetadata();
if (!in_array($class, $classMetadata->discriminatorMap)) {
throw new \Exception("invalid discriminator class: " . $class);
}
$identifier = $classMetadata->fieldMappings[$classMetadata->identifier[0]]["columnName"];
$column = $classMetadata->discriminatorColumn["fieldName"];
$value = array_search($class, $classMetadata->discriminatorMap);
$connection = $this->getEntityManager()->getConnection();
$connection->update(
$classMetadata->table["name"],
[$column => $value],
[$identifier => $id]
);
}
}
I do have to warn you though, when your sub-classes have (a lot of) extra fields you will need to fill or clear them manually afterwards.