I need to decide which approach to choose for my MySQL DB.
Example:
PHOTO ALBUM
User - can own photoalbum
Group - can own photoalbum
(maybe more entities could own photoalbum)
Now how to represent this in DB so it will:
Work nicely with Propel (join selects etc.)
I believe one approach is called polymorphic associations. But it has its own problem and I cannot find any resource talking about polymorphic associations with propel.
Second approach would be to represent everything separated. Meaning group_photoalbum user_photoalbum. It would be cleaner in MySQL and there will be no problem with Propel, but it would double most of the code and therefore any changes will be done twice.
Can Propel work with polymorphic associations? (any source)
Is there any other approach I don't know about?
Which would you choose?
Propel inheritance. Should have read the docs whole.
propel inheritance
Propel does not support polymorphic relationships.
You are best off using another ORM, if possible.
I mean, who uses XML 2018.
#Turnadiev Nursultan, he asked whether they support the relationship,
not if you can hack your way(which is a hack).
Related
We are doing our own framework with ORM capability. The database tables are classes now, but how about records? Lets imagine two tables:
Users
ID,USERNAME
Emails
USER_ID,ADDRESS
so, a record object will have getID(), getUSERNAME() methods, etc but if the two tables are JOIN-ed, it cant have two types right? Since there is no multiple inheritance. And what about field collision?
DBIx::Class handles this by having a Class for each table, and joins are represented by a method that gets an object matching the other table..
$myAddress = $myUser->emails->address;
I think every class should represent a record and a whole table should be an array (or some other collection) of objects. Take a look at http://www.doctrine-project.org/ to get some ideas.
And for JOIN, you should have some mechanism for defining aliases. That way, you can deal with field collision.
And for getters and setters, you can use __call, __get and __set. See http://php.net/manual/en/language.oop5.overloading.php for more info.
I'm providing some insight based on the Model/ORM implementation of this PHP UI Framework . Here are some suggestions from me:
Don't decide blindly to map functions into fields. Why not use get('field') and set('field'). There is no downside (apart from lack of IDEs hinting), but you can avoid code generation or catch-all which usually is slower.
When joining you wouldn't necessarily want multiple objects. In my ORM a single Model can work with joined tables. This introduces transparency and when you call $model->set('address') it might be associated with joined table. Im still using sub-instance of a dynamic query for sub-selects but for joins there is no need.
I've see a lot of power of inheritance and ability to re-shape parent models in parent model. Each table can have multiple models depending on your business uses.
Models and ORM should be separated but should play together very closely. I've also managed to make everything play well with generic views and generic controllers, which is a great time-saver.
Hopefully this would help find your own way or to decide on not implementing your own ORM. It's not an easy task.
I'm in the process of writing a very light-weight ActiveRecord implementation in PHP. I have the basics working, but I want to implement eager loading of at least the one-to-one relationships. I've been brainstorming on a clean way to do this.
If I'm eager loading a single one-to-one relationship, I will have to know the columns for both tables and will have to alias the columns following some convention that will allow me to map the results back into the correct objects.
I'm looking for suggestions on how to alias the columns from each table such that mapping them back to their respective objects is as painless as possible.
My initial thoughts are to alias the base table's columns as "base_column_name" and the related tables columns as "user_email" (if "User" is the name of the related object). Is there a better way to do this that I'm overlooking?
A second option I have considered is to get all of the objects off of the base table, and then gather the related objects in one "WHERE IN" using the keys from the base table. But, would this cause performance problems?
CakePHP uses php's flexible associative arrays in its ActiveRecord implementation. So a one to many relationship could be
array('Tablename'=>array('columnname'=>'columnvalue'),
'AssociatedTable'=>array('0',
array('columnname'=>'columnvalue')));
It does put one more layer in everything so you have to do $data['tablename']['columnname'];
I'm building a web app and would like to use an ORM to map the data from db with objects.
I have been struggling with this for a few days, and tried various implementations, including: Codeigniter ORM, Kohana ORM, PHP.ActiveRecords and Doctrine.
The last two I can't really use, because they depend on PHP 5.3 which is not installed (and can not be) on my shared hosting server.
The problem with all these ORM-s is inheritance (except for Doctrine, but I can' use it).
I know a lot of developers just do db-s without inheritance, but here is my problem:
My db needs to be multilingual, I designed my db by the following example:
Table Product -> id, category_id, price... (everything that is not translatable)
Table ProductTranslation-> id, language_id, name, description... (same id as product, adds language FK, and fields that are translatable)
Maybe there is a better approach, but I really like this, because its very flexible (can add new languages) and does not put a lot of NULL-s in the db, also joining is not that costly because the tables are relatively small (unlike the approach to put all translations in a single table, and reference that table from all other tables).
The only workaround, I found, to support ORMs is to put a has_one relation between
Product->ProductTranslation.
This way I could access the translated fields with something like:
DB::get_product_by_id(4)->translation->name
Nevermind the syntax, but the real problem with this approach is that I have to define new objects(models) for translation tables, and logically they don't belong there. They are not entities, just additional data for the entities.
So, my question here are:
Is there a better way to organize languages in the db, which is more ORM friendly ?
Are there any other PHP ORM-s (<5.3) which support inheritance ? - Btw. I found the Kohana ORM ihertiance module but it seems out-of-date, and doesn't work with the current framework version
Are there any other workaround for the inheritance problem?
Doctrine 2.0 requires PHP 5.3, but Doctrine 1.2.x works fine on PHP 5.2.3 or newer.
why not use Propel's i18n behavior ?
I am not suggesting that all models are tables.
What I am asking is whether every single table must also have its own class defined specifically for it when using Zend? Is there any way of getting away from this awkward boiler-plate coding. We're just starting to look into Zend (hoping to leave procedural PHP land!) and my colleague thinks this could end up being pretty time-consuming.
Is this the reason for people using ORM solutions? Is there any other way around this?
Thanks for your replies.
The Zend Table classes follow the Table Data Gateway pattern, which by definition
... holds all the SQL for accessing a single table or view: selects, inserts, updates, and deletes. Other code calls its methods for all interaction with the database.
In the book, Fowler is not that rigid about that, saying that
for very simple cases, you can have a single TDG that handles all methods for all tables. You can even have one for views or even for interesting queries that aren't kept in the database as views.
However, except for being able to use Views, Zend_Db_Table does not accomodate for this. You can create queries to multiple tables, but those would have to be made through the Zend_Db_Adapter directly or - when using joins - by switching off the integrity check. Otherwise, you have to use the API offered by Zend_Db_Table Relationships
So yes, one instance should correspond to one table or view. You do not need to create classes for that though if you dont plan on extending the classes. Zend_Db_Table_Definitions allow you to configure Zend_Db_Table instances on the fly.
Note that TDG is a DataSource Architectural Pattern and not an Object-Relational pattern. It's purpose is not to help with impedance-mismatch, but with separating database access code from business logic.
What is the method to save and update Many to Many relationship in Yii framework?
There is a better implementation as behavior.
http://www.yiiframework.com/forum/index.php?/topic/6905-please-test-my-ar-enhancement-automatically-sync-many-many-table-when-calling-save/
Unless you create a model for the table between the two main tables, your only option is to use DAO (Database Access Object) and specify SQLs with it.
Have a look at how blog demo accomplishes this task.
use MANY_MANY relationship type to setup many to many connection between Models (An associative table is needed to break a many-to-many relationship into one-to-many relationships)
And now you can use all relational functions of Active Records
Yii Framework - The Definitive Guide to Yii: Working with Databases-Relational Active Record
The following extension does what you want...
Yii Framework - Extension: cadvancedbehavior
An important thing to note: On each update, the extension clears all previous records and creates new ones. So I wouldn't use it when the intermediatry table contains extra data other than the foreign keys.
you could set that up in mysql level..by going to relational view under each table in phpmyadmin and provide necessary relational condition..and use MANY_MANY in the model class inside relations..
The question is too common.
Usually data components with MANY to MANY relationships appear sequentially and independently. So you just need to do one insert action after another.
If your relationship needs dependent update you should user SQL triggers on the DataBase level. That'll ensure integrity of data and give a quite good separation in business logic of the application.
CREATE TRIGGER some_trigger
AFTER UPDATE ON some_table
...
END IF;
A similar way is to incapsulate relational data in one logical model on PHP level (and e.g. manipulate with 2-3 AR models there) and emulate SQL triggers logic in it.