I have few lookup tables which are listed below. As of my understanding we need a Model for each database table, but does this also apply to lookup / mapping tables? what is the best practice used while creating models? Below is a sample of my lookup tables...
Transaction Customer Transaction_Lookup
id Id transection_id
date name customer_id
active active
I have created models corresponding to Transaction and Customer tables, do I need to create a corresponding model for Transaction_Lookup as well?
Also I am using Data Mapper pattern which means I will also have to create a Mapper class for each model...
Thanks for your help in advance....
One remark I would make is to not think of models as corresponding one-to-one with tables. That can be very limiting in your OOP design. That said it is true often your models will align to a single table. Look-up tables being an obvious scenario where this is true.
As for needing a concrete model for each lookup table... I would consider writing a generic Model that could be used for all objects corresponding to 'lookup' tables. You could then use that generic class, or write it as an abstract and extend it and create named concrete classes. The amount of unique code needed there could be very limited, leveraging what you already have on the parent class. If you wanted a look up table specific abstract you could abstract the fields key(id), value, friendly name, active? and map the corresponding fields on the tables to those generic properties. Really a number of ways to go about that, hope I explained it well.
I typically write two styles of mappers, ones that are essentially table row gateways like Zend_Db_Table and another that is more custom, where perhaps I use a stored procedure or complex Zend_Db_selects joining off multiple tables. Using the table row gateway style mappers I usually just need to specify a table name, adapter, and mapped object for the mapper to work with. On the custom mappers I usually need to write more of the implementation code from scratch on a case by case.
I like this approach of using a Data Mapper. Can be both convenient and powerful.
Related
I have an application that has only two tables: products and type - where each product can have multiple types as attributes. I decided to normalize the database and created another table where I intend to keep the relations between the products and types.
(Disclaimer: I'm relatively new to object oriented programming). I have a class for products, and a class for types. I have been told that I should have a class for every table that I have in the database. Does this also apply to a table created for normalization purposes? If so - what is the best way of dealing with this - should I somehow call both other classes in this third class, or keep it an independent class, and just manage the exchange of information through actual forms on the webpage, etc?
If your product_types table only holds foreign keys there is no need to map it to its own class. Since this is defining a many to many relationship between the tables you can just provide a method in your product class to get the types.
getTypes() {
// retrieve the types for this product and return
}
Then add the opposite method in the types object to get the products.
getProducts() {
// retrieve the products for this type and return
}
I have been told that I should have a class for every table that I have in the database. Does this also apply to a table created for normalization purposes?
Usually when you're designing a database, the first thing you need to do is create a conceptual data model. This will allow you do define your entities as well as defining relationships between them. Then you create a logical data model to characterize and refine your entities. The last step is the physical data model, which is the closest model there is to a database. Now in this model your entites are now tables, and some of them may or may not relate to your application domain.
For example you could have a travel agency application, where you'd have tables for destinations, flight companies etc... These would map directly to your application because they represent concrete classes. On the other hand you'd also have configurations, sparse data (billing...) or associative tables (like you have here). They don't map to your current application. This concept is called impedance mismatch. See this diagram I found online :
Finally to answer your question : no you don't need to map it to a class, because it has nothing to do in the application domain. Of course you still need to handle it some way (using DAO and SQL basically). You could also use an ORM, like suggested in the comments by #RobW, which can abstract and map directly your database.
Put simply about Table Data Gateway (TDG) implementation: you create separate TDG class that contains SQL for CRUD operations with concrete table. So, your models communicate not directly with a datasource (for example database) but via those abstracted ones - TDG classes. So, it's just an approach for making another level of abstraction and it's just a wrapper for communicating with database - get and modify the data. IMHO TDG classes should not contain members, only methods. Here's a good schema that visualizes the use TDG pattern. When using TDG approach, SQL should be moved from model classes to datasource (TDG) classes. And all data that I retrieve from DB through TDG classes are stored in my model members.
Now, what about active record implementation? If I would merge data access and my model class into one model class then would I implement active record? I was unable to find a clear distinction or how those patterns look in PHP and differ from each other.
Often, I'm having one singleton database class and then separate model class for each database table. Each model class has CRUD + several custom (count, avg and etc.) operations. Some classes have members for persisting results from CRUD or custom operations - thats's done upon the need. Could this approach be identified as active record? Also, if I would move SQL from my model classes to TDG classes would this be Table Data Gateway?
From http://martinfowler.com/eaaCatalog/index.html
Table Data Gateway: An object that acts as a Gateway (466) to a database table. One instance handles all the rows in the table.
Active Record: An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.
The obvious main difference is that TDGs wrap access to a table and only returns row data, while ARs wrap access to a row in the table and adds business logic to it.
Unless you have very low impedance mismatch, having a TDG is preferred because with AR your business/domain objects follow the structure in the database, which us usually not how your domain objects should be modeled. A Row may know how to persist itself, but a Person should not know. It is more maintainable in the long run to to separate persistence logic and domain logic.
Regarding your Singleton DB object have a look at Is there a use-case for singletons with database access in PHP?.
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 have a family of complex select queries which I need to call from different parts of the application. I think I should group them all into a model class, but would like to verify this.
The queries all work off the same set of 5 tables. Each of these tables has its own Table Data Gateway class and Row Data Gateway class, but my new class for the queries would not be implementing any such pattern (since it doesn't wrap a table or row). My new class would be calling on the Table and Row Data Gateways already established.
In addition, the values that come from users can't be susbstituted into the queries directly, so I plan to do some pre-processing in the new class as well. This pre-processing includes accessing the DB for lookup values, etc.
Does this sound fair? I think it's exactly how models should be used, but I can be spectacularly wrong about such things so would appreciate any comments or advice. (FYI, I'm using Zend Framework).
Queries don't go in the Model part. They are persistence related (the model doesn't handle persistence).
These complex queries should be in the Persistence layer, which is here the Table Data Gateway classes.
I would name the Table Data Gateway classes "DAO" (Data Access Object). A Table Data Gateway is a kind of DAO, since you can have a DAO that help you get things from files, webservices...
So you can keep your actual classes, and add a DAO to manage these complex queries. This DAO is not providing you access to a specific DB table, but it is still providing you access to a data source (composed by several DB tables).
Edit :
I suggest you to create a DAO interface (it may be empty). You DB Tables will implement this interface. Your new class will also implement this interface, but not extend Zend_Db_Table.
In short, you are redefining/renaming your persistence layer, from "Zend Db Table" to "DAO" (which makes it more generic). Zend Db Table is a kind of DAO.
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.