I need to create an like/dislike system which can be used on any entity. I'm going to create a Like entity with an 'Id', 'Entity' (can be anything), 'author' (ManyToOne with User class) and 'like' (boolean).
I just want to know if there is a good way to do it ?
I can't use the table inheritance (mappedsuperclass) because this entity will be part of a bundle (SocialBundle) which can be used on several project (It will be a vendor).
I have no code to show you because i'm still in the analysis part.
Thanks !
Create an interface for that entity and later you can map this interface to any entity using addResolveTargetEntity method. See this.
Related
Without scrutinizing why I want this (it may sound like a bad approach, but I have good reason) I want to know if there is a way in the standard-framework-edition 3.1+ to create a relational association to an entity that may not exist...
Firstly I do realize this determines the schema and that's fine. So if an entity does not exist, it doesn't create a foreign key and the field is always null, or if the target entity does exist, it creates the foreign key and the field works like a normal association...
Secondly, this only changes project to project, and may change down the line as an update to which I realize a manual schema update could be necessary.
Preferably without 3rd party bundle dependencies... hoping for the standard framework to do this,
Anybody?
Thanks in advance
Edit
I am using annotations in my entities with doctrine ORM
Furthermore
The simplest version of why I am doing this is because certain bundles are optional project-to-project, and bundle A may make use of entities in bundle B only if it is present. I have considered using services and if container->has then container->get, or the XML on-invalid="null" approach, but that doesn't address property persistence. I was happy with storing a non-mapped value as a custom relational field, which is fine, just lengthier and wondered if perhaps there was a way Doctrine could ignore a missing targetEntity...
Hm, perhaps I misunderstand your question, but this sounds like a normal 'nullable' association to me?
Create your assocation via annotation:
/**
*
* #var Child
* #ORM\ManyToOne(targetEntity="Child")
*/
private $child;
and use
setChild(Child $child = null)
{
$this->child = $child;
}
as a Setter to allow nullable values.
And your getter might look like:
getChild()
{
return $this->child;
}
In case there isn't any child it will return null.
I will keep the other answer as it responds to the question for a 'nullable association target' live data.
This is the answer for a 'nullable association target' meta data which is a different thing.
OP asks to provide a targetEntity in the metadata which cannot exist in his case, e.g. is not there in a different bundle (or whatever OP's mysterious reason might be).
In that case I recommend to build upon Doctrine's TargetEntityListener which is able to resolve the targetEntity during runtime and targetEntity can be set to an Abstract Class or an Interface:
/**
* #ORM\ManyToOne(targetEntity="Acme\InvoiceBundle\Model\InvoiceSubjectInterface")
* #var InvoiceSubjectInterface
*/
protected $subject;
InvoiceSubjectInterface will then be replaced during runtime by a specific class provided by config e.g.:
# app/config/config.yml
doctrine:
# ...
orm:
# ...
resolve_target_entities:
Acme\InvoiceBundle\Model\InvoiceSubjectInterface: AppBundle\Entity\Customer
So this should be eiter an extendable behaviour for providing no class or implementing an own solution.
I'm working on an events site and have a one to many relationship between a production and its performances, when I have a performance object if I need its production id at the moment I have to do
$productionId = $performance->getProduction()->getId();
In cases when I literally just need the production id it seems like a waste to send off another database query to get a value that's already in the object somewhere.
Is there a way round this?
Edit 2013.02.17:
What I wrote below is no longer true. You don't have to do anything in the scenario outlined in the question, because Doctrine is clever enough to load the id fields into related entities, so the proxy objects will already contain the id, and it will not issue another call to the database.
Outdated answer below:
It is possible, but it is unadvised.
The reason behind that, is Doctrine tries to truly adhere to the principle that your entities should form an object graph, where the foreign keys have no place, because they are just "artifacts", that come from the way relational databases work.
You should rewrite the association to be
eager loaded, if you always need the related entity
write a DQL query (preferably on a Repository) to fetch-join the related entity
let it lazy-load the related entity by calling a getter on it
If you are not convinced, and really want to avoid all of the above, there are two ways (that I know of), to get the id of a related object, without triggering a load, and without resorting to tricks like reflection and serialization:
If you already have the object in hand, you can retrieve the inner UnitOfWork object that Doctrine uses internally, and use it's getEntityIdentifier() method, passing it the unloaded entity (the proxy object). It will return you the id, without triggering the lazy-load.
Assuming you have many-to-one relation, with multiple articles belonging to a category:
$articleId = 1;
$article = $em->find('Article', $articleId);
$categoryId = $em->getUnitOfWork()->getEntityIdentifier($article->getCategory());
Coming 2.2, you will be able to use the IDENTITY DQL function, to select just a foreign key, like this:
SELECT IDENTITY(u.Group) AS group_id FROM User u WHERE u.id = ?0
It is already committed to the development versions.
Still, you should really try to stick to one of the "correct" methods.
So I'm working on some unit tests and relational fixtures.
I'm creating a model dynamically like:
$model = CActiveRecord::model('Post');
$post = $model->findByPk(1);
But after that I cannot for some reason get $post->id. I traced the problem to CActiveRecord class:
public function __get($name)
{
if(isset($this->_attributes[$name]))
return $this->_attributes[$name];
...
Where $name = "id". It says that $this->_attributes[$name] does not exist! As a matter of fact _attributes is empty.
My Post class does not define id (or any other properties) as a public property and I don't want to do so either. I just let the AR map it to table columns for me.
What am I missing?
Edit 1
My fixtures are regular Yii fixtures - nothing really special about them.
What differs is the way I load them really. I extended the CDbFixtureManager to be able to specify the order in which they should be loaded by overloading load() method. Only thing of interest that actually fails is that in the fixtures that have foreign keys I use the following:
'comment1' => array('post_id' => $this->getRecord('Post', 'post1')->id);
That's where it fails. getRecord returns the actual Post record (since I know the Post fixture has already been successfully loaded and exists in DB), but on the ->id part I get an exception about that attribute not existing.
If I go into Post model and add public $id; to it, then everything works! But I'm not sure if it's good practice to go about declaring all properties public like that.
If you look at this page carefully:
http://www.yiiframework.com/doc/guide/1.1/en/test.unit
you'll see that they use an array form for retrieving fixtures:
$this->posts['sample1']['id']
There is an alias defined in their fixture array for each record and fixture items aren't loaded as models really ...
Does that help? If not, it would be helpful to see your fixture file :-)
I think I found the root cause of this issue for me. While my FixtureManager was using the testdb DBConnection, the models still used the regular one.
For whatever reason, my debugger was giving me misleading errors like the one described in my original post.
Once I was able to set the DBConnection of all Models in the unit test the puzzle snapped into place and everything is now working smoothly!
I was looking for a built-in method to urlize/slugify a string, instead of copying a strandard one found on google.
Thus I found this : http://sourcecookbook.com/en/recipes/59/call-the-slugify-urlize-function-from-doctrine , referencing to this Doctrine Class http://www.tig12.net/downloads/apidocs/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Doctrine_Inflector.class.html , with the method urlize() which is exactly what I'm looking for.
But, in my Doctrine Bundle from Symfony 2, in \vendor\doctrine\common\lib\Doctrine\Common\Util my Inflector class is pretty empty.
What happened to this urlize() method ? Do I have to recode it ?
There's https://github.com/Behat/Transliterator which includes the urlize function from Doctrine1
This is the part taken from Doctrine 1.2.3
Doctrine inflector has static methods for inflecting text
You could just composer require behat/transliterator
and have a HelperClass extending Behat\Transliterator.
And then be able to do: MyStringHelper::urlize("isn't that great?")
The file you are looking at (Doctrine\Common\Util\Inflector) is supposed to be used internally by Doctrine, to convert between table names (underscore separated), property names (camelCase), and class names (CamelCase).
What you are looking for can be achieved with the sluggable doctrine extension. You can ingtegrate it easily into a symfony2 application with stof/StofDoctrineExtensionsBundle.
I am converting a project from Backbone (w/ Backbone Relational for ORM) to Ember and I cannot find in the documentation an example of how to use DS.belongsTo to reference an object of the same type.
In otherwords, I have the following model definition (generic pseudo-code for clarity).
BoxModel
Text = String
BoxParent = BoxModel (referenced by id)
I want to re-create this structure in Ember for client-side manipulation etc.
I am also using requirejs so all my object targets for DS.belongsTo have to be included in the define statement and made available as parameters to the anonymous function.
As such, I doubt I can use something like this:
define ([ 'textbox' ]), function(TextBox) {
return DS.Model.extend({
BoxParent: DS.belongsTo(TextBox)
});
});
The reference to the current class definition is not likely to work. In Django, this type of relationship is handled with the special target of "self" but I cannot find any equivalent solution in Ember. Any help would be very much appreciated.
As a final note, this relationship can also be null because not all TextBoxes must have a parent (this is inevitable with this type of relationship unless you have infinite circular references.
Thanks!
Steve
You need to wrap your model name around quotes to use a non initialized model name.
App.Box = DS.Model.extend([
parent: DS.belongsTo('App.Box')
});