Is there a best practice in getting data from multiple database tables using Zend? I would like to know rather than end up wanting to refactor the code I write in the near future. I was reading the Zend documentation and it said that:
"You can not specify columns from a
JOINed tabled to be returned in a
row/rowset. Doing so will trigger a
PHP error. This was done to ensure
the integrity of the Zend_Db_Table is
retained. i.e. A Zend_Db_Table_Row
should only reference columns derived
from its parent table."
I assume I therefore need to use multiple models -- is that correct? If, for example, I want to get out all orders for a particular user id where the date is in between two dates what would I do?
I know that it would be possible to access the two different models from a controller and then combine their respective data in the action but I would not feel happy doing this since I have been reading survivethedeepend.com and it tells me that I shouldn't do this...
Where, why, and how? :)
Thanks!
If you're reading ZFSTDE, in chapter 9 (http://www.survivethedeepend.com/zendframeworkbook/en/1.0/implementing.the.domain.model.entries.and.authors) this problem is addressed by using a data mapper.
Also, you can join 2 tables, just be sure to first call on the select object the setIntegrityCheck(false) method. The docs say that a row should reference a parent table, doesn't mean it can not :)
Stop thinking about Zend_Db_Table as your "model".
You should write your own, rich, domain-centric model classes to sit between your controllers (and views), and your persistence logic (anything that uses Zend_Db/Zend_Db_Table/Zend_Db_Select) to load/store data from the database.
Sure, you can query several db tables at the same time. Take a look at the official ZF docs here http://framework.zend.com/manual/en/zend.db.select.html#zend.db.select.building.join
As for your example with getting all orders of a single user, table relationships are the answer http://framework.zend.com/manual/en/zend.db.table.relationships.html
Related
I was given this project to work on with absolutely no documentation or contact developer. I noticed in the database dump that they are storing what looks like PHP Namespaces for Eloquent models in a couple tables. For example an address table has a string column named "object_type" with the value always being "App\Entities\Client". I searched through the whole project for the PHP code that would use this value. Hopefully to give me insight to it's purpose. Not to my surprise, the project never uses this value. I just see it hard-coding these values upon insert into the DB.
My question is, is this some sort of Database and/or ORM modeling design practice? If so, could you explain how this could be used in a simple practical sense?
Maybe this was some concept the developer had and it never evolved. It's interesting idea but, the idea of joining through MySQL on a string conditional sounds like torture.
Sounds like Laravel polymorphic relationships:
Custom Polymorphic Types.
By default, Laravel will use the fully qualified class name to store the type of the related model.
And, yes, this is a valid modeling technique, though purists rightly argue this technique abuses normal form.
I am not sure what the developers where thinking.
But imagining we are in a forum with thread and replies to each thread. We maybe want to have a Favourites table where we can save replies and threads.
A way to do it would be to have a column in the favourites table called "object_type" (just to use the same term you have in your case) and then when we save an object into the database with eloquent we can use:
$favourite->object_type = get_class($thread); //or get_class($reply) in case we want a reply
$favourite->save();
This way will save the namespace of that class into the database. But laravel will recognise it when we get it from the database.
Hope this cold be helpful.
In my application, member entities choose a from a pre-defined set of question entities.
I save and iterate over them as a shared list ($member->sharedQuestion).
Now I need to rank them, so I add another column via the link bean (member_question) called 'position'.
My question is - can I make redbean retrieve the questions ORDERed by the column 'position'?
I currently do a
foreach($member->sharedQuestion as $question){.......}
I know I could get the array property and run it through a custom sort handler before I start iterating, but that seems expensive.
Does anyone know of a Redbean method to append some sql (i.e. "ORDER BY position") to a sharedList for example?
Despite having read the Redbean documentation many times, I had missed the (very simple) solution.
Prepending the ->with() method applies extra sql to the query. So what I need to do is;
foreach($member->with("ORDER BY position")->sharedQuestion as $question){.......}
and my problem is elegantly solved!
I am using the Data Mapper Pattern and I am wondering what is the best way to handle relationships with that pattern. I spent a lot of time searching for solutions in Google and Stack overflow, I found some but I am still not completely happy about them, especially in one special case that I will try to explain.
I am working with PHP so the examples of code that I will put are in PHP.
Let's say I have a table "team" (id, name) and a table "player" (id, name, team_id). This is a 1-N relationship.
By implementing the Data Mapper pattern, we will have the following classes: Team, TeamMapper, Player and PlayerMapper.
So far, everything is simple. What if we want to get all players from a team?
The first solution I found is to create a method getAllPlayers() in the Team class which will handle that with lazy loading and proxies. Then, we can retrieve the players of a team like that:
$players = $team->getAllPlayers();
The second solution I found is to directly use the PlayerMapper and pass the team ID as parameter. Something like:
$playerMapper->findAll(array('team_id' => $team->getId()));
But now, let's say that I want to display a HTML table with all the teams and with a column 'Players' with all of the players of each team. If we use the first solution I described, we will have to do one SQL query to get the list of teams and one query for each team to get the players, whcih means N+1 SQL queries where N is the number of teams.
If we use the second solutions I described, we can first retrieve all team IDs, put them in an array, and then pass it to the findAll method of the player mapper, something like that:
$playerMapper->findAll(array('team_id' => $teamIds));
In that case, we need to run only 2 queries. Much better. But I am still not very happy with that solution because the relationships are not described into the models and it is the developer who must know about them.
So my question is: are there others alternatives with the Data Mapper pattern? With the example I gave, is there a good way to select all teams with all players in just 2 queries with the description of the relationships into the model?
Thank you in advance!
If you look at Martin Fowler's text that describes how the DataMapper works, you'll see that you can use one query to get all the data that you need and then pass that data to each mapper, allowing the mapper to pick out only the data that it needs.
For you, this would be a query that joins from Team to Player, returning a resultset with duplicated Team data for each unique Player.
You then have to cater for the duplication in your mapping code by only creating new objects when the data changes.
I've done something similar where the equivalent would be the Team mapper iterating over the result set and, for each unique team pass the result set to the Player mapper so that it can create a player and then add the player to the team's collection.
While this will work, there are problems with this approach further downstream...
I have a possible solution to this problem that I have implemented successfully in one of my projects. It is not so complex and would use only 2 queries in the example described above.
The solution is to add another layer of code responsible for handling relationships.
For instance, we can put that in a service class (which can be used for other stuff as well, not only handling relationships).
So let's say that we have a class TeamService on top of Team and TeamMapper. TeamService would have a method getTeamsWithRelationships() which would return an array of Team objects. getTeamsWithRelationships() would use TeamMapper to get the list of teams. Then, with the PlayerMapper, it would get in only one query the list of players for these teams and set the players to the teams by using a setPlayers() method from the Team class.
This solution is quite simple and easy to implement, and it works well for all types of database relationships. I guess that some people may have something against it. If so, I would be interested to know what are the issues?
I`ve been wondering this one thing about creating models.
If I make for example Page model. Is it the both: It can retrieve one row from the table or all the rows. Somehow Im mixing the objects and the database.
I have thought it like this:
I would have to make a Page-class that would represent one row in the table. It also would have all the basic CRUD-methods.
Then I would have to do a Pages-class (somekind of collection) that would retrieve rows from the table and instantiate a Page object from each row. Is this kind of weird?
If someone could explain to me the idea of model throughout.. Im again confused.
Maybe Im thinking the whole OOP too difficult..
And by the way this forum is great. Hopefully people will just understand my problems. Heh. I was a long time procedural style programmer and now in 3 months I have dived into OOP and MVC and PHP frameworks and I just get more excited day by day when I explore this stuff!
That depends on whether your Models represent instances or are just ORM objects.
If a Model represents an instance, then each record (row) in the database would become a new Model object. "All records" would simply be represented by an array of these objects. Ruby on Rails for example does it this way.
If your Model is rather an ORM object, it just represents the database as such and allows you to retrieve records from the database through it. The results may be in some container object or just a normal array. CakePHP for instance uses this method.
Is it the both: It can retrieve one
row from the table or all the rows.
You can use a model to interact with the database, there by you can do anything you like, for example getting one or more records, inserting records, updating, etc.
The way to go I would suggest you is to create a model for each of the distinct pages of your site that might interact with the database. You might want to create different functions inside a single model for a single page based on the page's requirements to interact with the database.
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.