I was wondering what would be the best practices and the best way to achieve consistency while accessing your database data :
Current structure goes as follow
Data Access --> Business Logic --> Controller --> View
My data access layer is composed of a Zend_Db_Table, Zend_Db_TableRowset and a Zend_Db_TableRow for each table.
My business logic is stored in the model named based on a the table
Example of problematic query :
I want to get a specific user based on his username. To do so I have a user table and a role table (role.id is referred as role_id in the user table).
I don't want to have to use the findDependentRowset that will run additionnal queries for each row that get returned. (will get problematic in data grid that display the data as many rows can be returned).
The choices I have (getName() is used in this example to simplify, but it can be any processing) :
Make a custom join on the role table in the user table which will return an index array composed of associative array. In that case I can't call my getName() function defined in my Model_DbTable_User to build the name (first name + middle + last name). Even if I "cast" my array to a Zend_Db_Table_Rowset (or my custom table_rowset) I can't access my custom class method since I get a generic Zend_Db_Table_Row object.
Make a custom join but build the name using CONCAT() in my query at runtime, I still get an array but the name is build so I don't need the getName() method. But if I have specific logic to apply i'm stuck.
Make a view joining user and role tables in my database and create a new set of Zend_DbTable, Zend_DbTableRowset and Zend_DbTableRow. This way I can have specific logic in my database stack.
An ORM (propel or doctrine (1 or 2)), I have no experience with these, I might need more informations to make the right choice.
My alternate goal is to be sure I get consistency in my data structures
ie:
array all the way :
array(
array(row1),
array(row2)
);
object all the way
$row = $rowset->current();
$row->field;
Creating a view should be done regardless because it complements the other ideas more than it competes with them. The view will:
Abstract the database to something that you can more easily work with.
Be faster because there's no parsing.
Be accessible outside of your application.
Once you've created the views, you can choose a strategy that best solves the problem. If you're creating a form that represents a single entity, then an ORM is probably a good fit. But if you're displaying large lists of data or generating reports that contain many entities then using a declarative language like SQL is probably easier and would perform better.
Related
I'm doing a web app here using Laravel + AngularJS and I have a question.Do I need a model for each table that I have in my database? There are 87 tables in my database and I need to query all of them according to with the input that the User wants.
I just want to make sure with all tables must have a model file or if just one is enough.
There are 2 ways by which you can access your DB tables:
Eloquent ORM (dependent on Models)
DB Facade Query Builder(independent on Models)
Former, is more clean and best approach to perform DB query and related task, whereas latter is not clean, and it is going to be difficult for you to manage large application, as you told there are 80+ tables in your application.
Also, if you're using Eloquent way, then it's also a better to have a base model, which will have common code which you can inherit in child models. Like if you want to store "user id" who did some DB changes, then in the boot function, you can write Auth::id() and assign that value to changed_by field on your table.
In DB Facade way, you've to hard code table name every time you're performing DB operation, and which leads to inconsistency when you found that you've to change the name of the table, it's a rare scenario still it'll be difficult to manage if in a file there are multiple tables DB operation going on. There are options like, creating a global table name variable which can be accessed to perform DB operation.
Conclusion:
Yes, creating 80+ model for implementing Eloquent way is painful, but for a short term, as the application grows it will be easy for you to manage, it will be good for other developer if they start working on it, as it will give a overview of DB and it will improves code readability.
It depends on how you'd like to handle queries.
If you'd like to use Eloquent ORM, you need model classes to handle objects and relationships. That is a model for a table, except intermediate relationship tables, which may be accessed through pivot attribute.
Raw SQL queries are also supported. You don't really need model classes for them, as each result within the result array will be a PHP StdClass object. You need to write raw SQL though.
See Laravel documentation.
I have a conceptual question, what is the best way to gather information from various models and treat them in different ways in order to return an array with the requested data, without using a "god" method?
I'll summarize the example I'm trying:
View "Payroll" is characterized by a html table that shows information of an employee, for example: base salary, every discount of the month (from the Payments table) as well as commissions from another table, so in Controller I just do $this->set($employee_info, $this->Employee->getInfo());
This method is responsible for gathering information from models that are not even related to him in some way (e.g.: Configuration Model) and at the end it returns the array required, the question is: what the best way to separate these responsibilities?
This method is responsible for gathering information from models that
are not even related to him in some way
You won't get around to call several models in this case in what you call a "god" method. The only way to get around that is to associate the data.
I would create three methods, one that fetches the data from all models, one that creates the data structure you want from that data and one that calls the two others and returns the data. I don't see a better way to separate that without having the data associated.
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.
Let's say I have three tables: users, books, and users_books.
In one of my views, I want to display a list of all the books the current user has access to. A user has access to a book if a row matching a user and a book exists in users_books.
There are (at least) two ways I can accomplish this:
In my fetchAll() method in the books model, execute a join of some sort on the users_books table.
In an Acl plugin, first create a resource out of every book. Then, create a role out of every user. Next, allow or deny users access to each resource based on the users_books table. Finally, in the fetchAll() method of the books model, call isAllowed() on each book we find, using the current user as the role.
I see the last option as the best, because then I could use the Acl in other places in my application. That would remove the need to perform duplicate access checks.
What would you suggest?
I'd push it all down into the database:
Doing it in the database through JOINs will be a lot faster than filtering things in your PHP.
Doing it in the database will let you paginate things properly without having to jump through hoops like fetching more data than you need (and then fetching even more if you end up throwing too much out).
I can think of two broad strategies you could employ for managing the ACLs.
You could set up explicit ACLs in the database with a single table sort of like this:
id: The id of the thing (book, picture, ...) in question.
id_type: The type or table that id comes from.
user: The user that can look at the thing.
The (id, id_type) pair give you a pseudo-FK that you can use for sanity checking your database and the id_type can be used to select a class to provide the necessary glue to interact the the type-specific parts of the ACLs and add SQL snippets to queries to properly join the ACL table.
Alternatively, you could use a naming convention to attach an ACL sidecar table to each table than needs an ACL. For table t, you could have a table t_acl with columns like:
id: The id of the thing in t (with a real foreign key for integrity).
user: The user the can look at the thing.
Then, you could have a single ACL class that could adjust your SQL given the base table name.
The main advantage of the first approach is that you have a single ACL store for everything so it is easy to answer questions like "what can user X look at?". The main advantage of the second approach is that you can have real referential integrity and less code (through naming conventions) for gluing it all together.
Hopefully the above will help your thinking.
I would separate out your database access code from your models by creating a finder method in a repository class with an add method like getBooksByUser(User $user) to return a collection of book objects.
Not entirely sure you need ACLs from what you describe. I maybe wrong.
So I'm working on a framework-esque system with one of my co-workers. Our current challenge is how to best implement statuses. Oftentimes, a status will carry with it unique data (a color for a table row, or text to be displayed to a user. etc). Currently, we have a statuses table which contains all this data. Contained in that table is a column: "css_class", which, whenever a record has that status, the specified CSS class is attached to the element (in this case a tr). Also, in order to assign another record a specific status, a foreign key is specified in that database table (in this case, a user has a specific status. So in the users table, there is a statuses_id foreign key). This implementation works alright, but there are a few problems. First, what if I need to perform a specific action in PHP if a record is in a specific status? The way we do it now is something like this:
if($user->status==0)
{
//execute some code
}
This really doesn't work well if statuses can change. Change one status, and the associated code either breaks or behaves differently than intended.
The other issue, and the main reason for posting a question is that the table contains the column "css_class". This is very versatile and allows us change the style of a specific status very quickly. But we really dislike the idea of putting code inside a database. Perhaps having CSS classes in a database isn't necessarily a bad thing, but I really don't know what the common practice is. Any ideas?
EDIT:
What I've gathered from the first few answers is that I should keep all my view stuff out of my model stuff in order to maintain an MVC framework. My argument is that if I keep the css_class name out of the database, then I'm checking the status id in the view in order to decide which class to assign it. So if I put the class in the database, I'm putting View information in the Model. If I don't put CSS classes in the database then I'm putting Model information in the View (checking which ID it belongs to). So by not muddying up the Model, I muddy up the view instead.......
The most elegant way I've seen this solved so far (and I've worked with a few MVC implementations now) is to store only the relevant data in the database. E.g. you'd store status="red" in the database, and leave it up to the view to know what to do with a red status, in terms of CSS. The problem is then solved by designing a sufficiently advanced View layer that creates reusable structures -- that way you don't need to always be updating things on a page-by-page basis when the css changes.
Passing this information up to the Model somewhat defeats the point of the content/presentation separation, because now your code needs to know to pull presentation information off the database and forward it along to the View level or, shudder, you'll be pulling that stuff from the database right in your View layer code, which makes maintenance a nightmare, as you've now lost control over the information flow.
If you want to continue your paradigm of storing this in the DB, you could make another table that maps VARCHAR names of the statuses to their corresponding INTEGER IDs.
However, if this was my framework. I would not be storing view information like this in the database. This would be handled by the V of my MVC setup.
From a data modelling point of view:
Have a different table for each "kind" of status; keep user statuses separate from page statuses (for example) - group the like entities together.
Don't put the CSS classes into the database, but use some form of status indicator - this could be an ENUM column, if you know the set of possible statuses up front. Transform this into the appropriate CSS class in the view layer. You don't want to end up in a situation where your CSS can't be changed because some data in the database prevents it.