I'm trying to create a join across multiple databases (one of them belonging to a legacy application) as described in the Doctrine blog. However, the example suggests hardcoding the name of the database right into the schema, which I'd like to avoid for obvious reasons.
Is there a way to read parameters defined in parameters.ini or config.yml and use them as a value for the annotations, like this?
/**
* #ORM\Table(name="%legacy_db_name%.%legacy_table_name%")
*/
No, it's impossible. The "%key%" form is only available in the DIC.
Why would you put these data in a yml file? Would it be useful?
Related
I'm using a standard Symfony 2.8 framework with Doctrine.
My entities' mappings are all annotated, but I would need to map a single entity by using the PHP way (by defining loadMetadata static method) . I know there's a way to override a mapping Bundle configuration like explained here, but what I would like is specifying a single Entity. Is that possible? Thanks
No you can't mix the formats
A bundle can accept only one metadata definition format. For example, it's not possible to mix YAML metadata definitions with annotated PHP entity class definitions.
see doc here:
http://symfony.com/doc/current/doctrine.html
if you really need to change the mapping format then I suggest you create a new bundle for your specific entity. I also had this problem. I wished to have different mapping format (yml and annotation in my case) but I had to create a new bundle.
I have two different bundle:
first bundle, OrderBundle , has core logic and functionalities and contains the Order entity.
second bundle, CustomerBundle depends on OrderBundle and contains the Customer entity.
I need to create a oneToMany relation between Customers and Orders (obviously one Customer do many Orders) but I need to keep the first bundle OrderBundle decoupled from the second, because OrderBundle is intended to be reused for other stuff.
I think the correct way could be something like this http://symfony.com/doc/current/cookbook/doctrine/resolve_target_entity.html but I can't figure out how to have a concrete implementation.
How to implement the relation between Order and Customer, if I can't specifically use Customer like targetEntity in the ManyToOne doctrine mapping?
Many thanks, in advance.
UPDATE
I write down the involved code, for better explanation.
\\ Order\Bundle\Entity\Order.php
class Order {
/**
* #ORM\ManyToOne(targetEntity="Order\Bundle\Model\OrderSubjectInterface", inversedBy="orders")
* #var SourceSubjectInterface
*/
protected $subject; // How to define getter ans setter for $subject ? Do I
have to use php app/console doctrine:generate:entities command?
...
\\ Customer\Bundle\Entity\Customer.php
use Order\Bundle\Model\OrderSubjectInterface;
class Customer implements OrderSubjectInterface{
/**
* #ORM\OneToMany(targetEntity="Order\Bundle\Entity\Order", mappedBy="subject")
*/
private $orders;
How to define getters, setters and the interface?
Yes, this is the right way.
As shown in the documentation you mentioned, you can specify something like OrderSubjectInterface as a targetEntity in the ManyToOne mapping.
This way, you know that your Order is related to subjects. Those subjects are, in your case, the Customers, as defined in app/config/config.yml.
It's quite hard to entirely decouple the bundles if you have entity definitions all over the place. The problem is, the Doctrine doesn't allow by default for a related entity to be missing. Let's start from the beginning.
If you want to decouple only Order entity, what you have to do is create interfaces for all its related entities (they need to implement them) and then use the ResolveTargetEntity. So instead of referencing the full entities you reference the interfaces (when you define the relations in your entities). Lastly, you can then set which interface maps to which entity in the configuration.
What this does is it allows you to pick up the Order bundle and put it in an environment which has entirely different entity structure. The important thing is that the entities related to Order must not be missing in the new environment (They can be entirely different, but they must implement the same interfaces as the originals). Then you change the settings so that the interfaces point to the entities from the new environment.
So as you see, this is not "entirely decoupled" code. I can't help you much more without some details. Is the relation bidirectional or unidirectional? What do you exactly mean by "reused for other stuff", can you be more detailed?
I'm planning to store a few global configuration values (page title, page keywords, current theme, etc.) in the database. What's the best approach to this? Would you guys create a Doctrine Entity with two columns, option_key and option_value, or would you create a column for each configuration value?
I would recommend a ConfigurationBundle with a controller to handle the config CRUD and then an entity with the 2 columns: option_name, option_value.
This way you can do calls like $optionsRepo->findOneByOptionName('some_option_name');
This will either give you the option or a null value. You can handle the result from there.
As Chausser suggested, but I would go even further.
Either:
implement DoctrineFixtures to ensure you always have a default data (link)
OR
Make sure you have the defaults stores in your parameters.yml (or some other for that matter)
If option has not been found fallback to that default
I've started a Symfony2 project from scratch where I then installed FOSUserBundle.
Then, I have written (actually, generated with ORM Designer) some entities that need to have relations between them, and with the User entity.
I have Items belonging to Users, Collections belonging to Users that group Items, and so on.
Since I used FOSUserBundle I only have a basic User class (https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md , step 3a) defined using annotations, no config/doctrine folder and no User.yml file in it.
I then created the MyBundle/Resources/config/doctrine folder and added the yml files mentioned above.
When I try to generate the entities with the command-line tool everything works fine: it will create the Entities from my yml files.
However, at this point, trying to load up in browsers the url where the login previously worked (when I only had the FOSUserBundle installed) will throw this error:
MappingException: No mapping file found named
'/var/www/concert/src/X/MyBundle/Resources/config/doctrine/User.orm.yml'
for class 'X\MyBundle\Entity\User'.
Following actions, such as generating the CRUD logic, will not work as long as I have an *.orm.yml file in the config/doctrine folder. If I remove those, CRUD generation will work, but generation of actual mysql tables won't.
Juggling with these gets me to a point where I can also get the tables, but then the actual app doesn't work if I try to use any of the url's where the newly generated CRUD is involved because since the entities are based on yml (which I remove to get things "working") it won't have any mapping knowledge.
Is this inherently wrong? To have yml-based entities in relationship with an User entity based on the FOSUserBundle and still be able to get the nice command-line generation tools?
The problem you describe stems from mixing configuration formats (yaml and I assume annotations). You can easily fix this by ditching the annotations in your models and replacing them with yaml-files like you would do in your own models.
Unfortunately the FOSUserBundle-docs only show you how to use annotations, so here is a quick transformation into yaml format when your X\MyBundle\Entity\User extends FOSUSerBundle's UserEntity:
X\MyBundle\Entity\User:
type: entity
table: fos_user
id:
id:
type: integer
strategy: { generator: "AUTO" }
The remaining stuff is taken care of by FOSUserBundle, as the BaseModel is a mapped-superclass and already describes the stuff in the User.orm.xml, but you could just as well replace the existing values or add additional values just like you would do with your own models.
If you don't use annotations throughout your app, you might also want to disable them in your app/config/config.yml to prevent side effects.
How can I tell Doctrine2 Entity Manager to use an inherited class by default, instead of the generated one?
In my new sf2 app, I generated all entities from the existing database to /src/Package/Bundle/DataBundle/Entity - of course I'd like to have generated forms as well, so I need for my foreign-key relations __toString() methods, which I don't want to put into those generated files because they get overwritten (yes they also get backuped in an extra file, so my changes aren't lost, but manually merging files is not what I want).
So I added new classes to /src/Package/Bundle/DataBundle/Model inheriting all from the entities, but with a __toString() method and surely some other tweaks in the future as well. But now, when I call $entity = $em->getRepository('PackageDataBundle:Customer')->find($id); - I get an instance of /src/Package/Bundle/DataBundle/Entity/Customer instead of /src/Package/Bundle/DataBundle/Model/Customer ..
I'd like to have the behaviour from sf1, where all custom work is done in the inherited classes and the generated ones are the "base" Classes, which can be updated any time on a schema update and aren't touched otherwise..
I hope there is some configuration for this..
Maybe as a bonus, I'd like to have my naming convention turned around: to have Model as the "abstract" generated one and Entity as the actual used one
Thanks.
I'd like to have the behaviour from sf1, where all custom work is done in the inherited classes and the generated ones are the "base" Classes, which can be updated any time on a schema update and aren't touched otherwise..
For purposes you described you should use Propel ORM - it was so in Symfony-1.4, and became even more flexible for Symfony-2.0 with Propel 1.6. It is well documented, easily installed and naturally used within Symfony-2.0
Perhaps I misunderstood your problem, but going from Propel to Doctrine i was also disappointed that there is no way to keep that "dirty" auto-generated code out of my logic.
I do not know how much it is now important to you, but I currently writing a simple bundle that implements such generation style.
$ app/console doctrine:generate:entities СompanySomeBundle --propel-style=true
Generating entities for bundle "СompanySomeBundle"
> backing up User.php to User.php~
> generating Сompany\SomeBundle\Entity\Base\User
> generating Сompany\SomeBundle\Entity\User
https://github.com/madesst/MadesstDoctrineGenerationBundle
PS: Sorry for my english =/