I have a normalized database, with foreign keys/primary keys giving one to many databases.
I plan to access this database with PHP for the basic frontend/backend display. Now, my question comes from these two exampled queries:
CREATE VIEW `view` AS
SELECT
functiondetails.Detail,
functionnames.ID,
functionnames.FunctionName,
functionnames.Catogory
FROM functiondetails
INNER JOIN functionnames ON functiondetails.AsscID = functionnames.ID
or
SELECT
functiondetails.Detail,
functionnames.ID,
functionnames.FunctionName,
functionnames.Catogory
FROM functiondetails
INNER JOIN functionnames ON functiondetails.AsscID = functionnames.ID
There is no error within the query as i've ran both without fail, but my overall question is this:
if I plan to constantly reference alot of information from my database. Wouldn't it be easier to create a view, which will then update all the time with the newly added information, or would it be in better practice to have the second query on my actual php.. Example:
$Query = $MySQli->prepare("
SELECT
functiondetails.Detail,
functionnames.ID,
functionnames.FunctionName,
functionnames.Catogory
FROM functiondetails
INNER JOIN functionnames ON functiondetails.AsscID = functionnames.ID
")
$Query->execute();
$Results = $Query->fetch_results();
$Array = $Results->fetch_array(MYSQLI_ASSOC);
Or to select from my view?
$Query = $MySQLi->prepare("SELECT * FROM `view`");
$Query->execute();
$Results = $Query->fetch_results();
$Array = $Results->fetch_array(MYSQLI_ASSOC);
So which one would be a better method to use for querying my database?
Views are an abstraction layer and the usual reason for creating an abstraction layer is to give you a tool to make your life easier.
Some of the big advantages to using views include:
Security
You can control who has access to view without granting them access to the underlying tables.
Clarification
Often times, column headers aren't as descriptive as they can be. Views allow you to add clarity to the data being returned.
Performance
Performance wise, views do not negatively hurt you. You will not, however, see a performance gain by using views either as MySQL does not support materialized views.
Ease in Coding
Views can be used to reuse complex queries with less room for user error.
Ease of Management
It makes your life easier whenever your table schema changes.
For example, say you have a table that contains homes you have for sale, homes_for_sale, but later on you decide you want that table to handle all homes you've ever had for sale/have for sale currently, all_homes. Obviously, the schema of the new table would be much different than the first.
If you have a ton of queries pulling from homes_for_sale, now you have to go through all your code and update all the queries. This opens you up to user error and a management nightmare.
The better way to address the change is replace the table with a view of the same name. The view would return the exact same schema as the original table, even though the actual schema has changed. Then you can go through your code at your own pace, if needed at all, and update your query calls.
You may be assuming that MySQL stores the results of a view somewhere, and updates that result as data in the underlying tables change. MySQL does not do this. Querying a view is exactly like running the query.
But it can even be worse performance than running the bare SQL query, because MySQL may accumulate the results of the base query in a temporary table, so that you can use further SQL clauses in your query against the view. I say "may" because it varies by view algorithm.
See http://dev.mysql.com/doc/refman/5.6/en/view-algorithms.html for a description of how MySQL uses either the "merge" algorithm or the "temptable" algorithm for executing a view.
If you want materialized views, there's a tool called FlexViews that maintains materialized views:
Flexviews is a materialized views implementation for MySQL. It includes a simple API that is used to create materialized views and to refresh them. The advantage of using Flexviews is that the materialized views are incrementally refreshed, that is, the views are updated efficiently by using special logs which record the changes to database tables. Flexviews includes tools which create and maintain these logs. The views created by Flexviews include support for JOINs and for all major aggregation functions.
Creating View is preferable if you are:
Sure about the required columns
Want to reuse your view somewhere else as well
You like coding in abstract way. (Hiding technical details)
Need fast access by creating index on it.
Specific access to few user (point took from comments)
A view is simply a stored text query. You can apply WHERE and ORDER against it, the execution plan will be calculated with those clauses taken into consideration. I think it would be useful if you want to keep your code "clean".
What you need to keep in mind is that it is a little harder to modify the view, so if you are not quite sure about the columns, or it will change latter, stick to a query.
About performance is THE SAME!
Best regards!
Performance wise they should be the same, but the view is better for a few practical reasons.
I prefer views because it encourages better reuse and refactoring of the complex queries by altering them in one place instead of having to copy-paste a newer version everywhere if use the query in multiple places.
Also running an update query against a view can look a lot cleaner and simpler, but be aware that you sometimes can't update multiple columns in a view that belong to different underlying tables. So if you have to update 2 different columns, you'll have to run two different update queries.
Using a view also makes sense because you offload complex database logic to the database where it belongs instead of building it into your application code.
On the downside of using a view, that can take you a little bit longer to setup if you don't have your database management tool at the ready. Also, if you have a lot of views, you'll probably have to come up with some way to organize and document them all. This gets more complex if views start building off of other views. So you'll have to plan ahead and maintain dependencies.
Related
I cant seem to find an acceptable answer to this.
There are two big things I keep seeing:
1) Don't execute queries in the controller. That is the responsibility of business or data.
2) Only select the columns that you need in a query.
My problem is that these two things kind of butt heads since what is displayed in the UI is really what determines what columns need to be queried. This in turn leads to the obvious solution of running the query in the controller, which you aren't supposed to do. Any documentation I have found googling, etc. seems to conveniently ignore this topic and pretend it isn't an issue.
Doing it in the business layer
Now if I take it the other way and query everything in the business layer then I implicitly am making all data access closely reflect the ui layer. This is more a problem with naming of query functions and classes than anything I think.
Take for example an application that has several views for displaying different info about a customer. The natural thing to do would be to name these data transfer classes the same as the view that needs them. But, the business or service layer has no knowledge of the ui layer and therefore any one of these data transfer classes could really be reused for ANY view without breaking any architecture rules. So then, what do I name all of these variations of, say "Customer", where one selects first name and last name, another might select last name and email, or first name and city, and so on. You can only name so many classes "CustomerSummary".
Entity Framework and IQueryable is great. But, what about everything else?
I understand that in entity framework I can have a data layer pass back an IQuerable whose execution is deferred and then just tell that IQueryable what fields I want. That is great. It seems to solve the problem. For .NET. The problem is, I also do PHP development. And pretty much all of the ORMs for php are designed in a way that totally defeat the purpose of using an ORM at all. And even those dont have the same ability as EF / IQueryable. So I am back to the same problem without a solution again in PHP.
Wrapping it up
So, my overall question is how do I get only the fields I need without totally stomping on all the rules of an ntier architecture? And without creating a data layer that inevitably has to be designed to reflect the layout of the UI layer?
And pretty much all of the ORMs for php are designed in a way that totally defeat the purpose of using an ORM at all.
The Doctrine PHP ORM offers lazy loading down to the property / field level. You can have everything done through proxies that will only query the database as needed. In my experience letting the ORM load the whole object once is preferable 90%+ of the time. Otherwise if you're not careful you will end up with multiple queries to the database for the same records. The extra DB chatter isn't worthwhile unless your data model is messy and your rows are very long.
Keep in mind a good ORM will also offer a built-in caching layer. Populating a whole object once and caching it is easier and more extensible then having your code keep track of which fields you need to query in various places.
So my answer is don't go nuts trying to only query the fields you need when using an ORM. If you are writing your queries by hand just in the places you need them, then only query the fields you need. But since you are talking good architectural patterns I assume you're not doing this.
Of course there are exceptions, like querying large data sets for reporting or migrations. These will require unique optimizations.
Questions
1) Don't execute queries in the controller. That is the responsibility of business or data.
How you design your application is up to you. That being said, it's always best to consider best patterns and practices. The way I design my controllers is that I pass in the data layer(IRepository) through constructor and inject that at run time.
public MyController(IRepository repo)
To query my code I simply call
repository.Where(x=> x.Prop == "whatever")
Using IQueryable creates the leaky abstraction problem. Although, it may not be a big deal but you have to be careful and mindful of how you are using your objects especially if they contain relational data. Once you query your data layer you would construct your view model in your controller action with the appropriate data required for your view.
public ActionResult MyAction(){
var data = _repository.Single(x => x.Id == 1);
var vm = new MyActionViewModel {
Name = data.Name,
Age = data.Age
};
return View();
}
If I had any queries that where complex I would create a business layer to include that logic. This would include enforcing business rules etc. In my business layer I would pass in the repository and use that.
2) Only select the columns that you need in a query.
With ORMs you usually pass back the whole object. After that you can construct your view model to include only the data you need.
My suggestion to your php problem is maybe to set up a web api for your data. It would return json data that you can then parse in whatever language you need.
Hope this helps.
The way I do it is as follows:
Have a domain object (entity, business object .. things with the same name) for Entities\Customer, that has all fields and associated logic for all of the data, that a complete instance would have. But for persistence create two separate data mappers:
Mappers\Customer for handling all of the data
Mappers\CustomerSummary for only important parts
If you only need to get customers name and phone number, you use the "summary mapper", but, when you need to examine user's profile, you have the "all data mapper". And the same separation can be really useful, when updating data too. Especially, if your "full customer" get populated from multiple tables.
// code from a method of some service layer class
$customer = new \Model\Entities\Customer;
$customer->setId($someID);
$mapper = new \Model\Mappers\CustomerSummary($this->db);
if ($needEverything) {
$mapper = new \Model\Mappers\Customer($this->db);
}
$mapper->fetch($customer);
As for, what goes where, you probably might want to read this old post.
I'm using codeigniter for one of my projects, and right now what I have is a table with PROJECT information, and I'm displaying all the PROJECTS in a specific view.
Now, I also want that same view to display other related information about the projects such as the number of views as well as the associated tags. But this would require multiple JOINS in the model(which would require me to alter the existing query...) but it would keep the view from having to call the model directly.
Would I get better performance if I simply break up the queries, and have 2 separate queries related to the other information in the VIEW? I find this to be more clear, but I wonder if it's slower since I'm calling the model for EACH project in a loop.
Why dont you just code both - and test using CI Profilier?
Then you will be 100% sure. Furthermore - if the results are "close" you can just go with the option that suits your programming logic better.
p.s. you could also loop the multiple calls to the model into an array (like $projects) in the controller, and pass that variable to the view, so in either scenario the "view" is NEVER calling the "MODEL" directly.
I'm working with the TinyMVC framework, and it allows one to "build MySQL queries programmatically, much like active record." The example is embedded here (relevant TinyMVC documentation):
class Members_Model extends TinyMVC_Model
{
function get_members()
{
$this->db->select('foo,bar,baz'); // set selected columns
$this->db->from('mytable'); // set from what table(s)
$this->db->where('foo','test'); // where foo='test'
$this->db->orwhere('foo=? and bar=?',array('test','test2')) // where foo='test' and bar='test2'
$this->db->join('jointable','mytable','jointable.foo=mytable.foo'); // join tables on (optional) condition
$this->db->in('mycolumn',$elements,$islist,$prefix) // IN clause: column, elements (comma-separated or array), $list=boolean is list or array, $prefix: AND|OR
$this->db->orderby('ordercolumn'); // order by column(s)
$this->db->groupby('groupbycolumn'); // group by column(s)
$this->db->limit($limit,$offset); // query limit, optional offset
$this->db->query();
while($row = $this->db->next()) {
$rows[] = $row;
}
return $rows;
}
}
How is this different or better than the writing the SQL query outright:
SELECT foo, bar, baz
FROM mytable
WHERE...
The benefit is that you can have interdependent functions in your controller that can build on your query without having to worry about the order of your SQL. You can have conditional logic to use certain active record manipulations on one query and then simply run it when it's fully populated.
CodeIgniter's active record implementation is extremely useful. I imagine TinyMVC's is very similar.
The codeigniter website gives the following reason
Beyond simplicity, a major benefit to using the Active Record features is that it allows you to create database independent applications, since the query syntax is generated by each database adapter. It also allows for safer queries, since the values are escaped automatically by the system.
it is an opinion (my)...
you can play with part of the query qithout handling long string.
for example:
if(){
$this->db->where($a,$b);
$this->db->where($c,$d);
$this->db->where($e,$f);
}else{
$this->db->where($g,$h);
$this->db->where($i,$j);
$this->db->where($k,$l);
}
writing the above statement in one string is not very nice coding and hard for maintenance.
And in addition to that, you can than generate cross database queries (helps for migration and in shelf products).
that is only one good reason...
It is not really different, it's more to make it easier for you, the programmer. Because if you write the query yourself, you have to worry about security yourself (mysql injection for example) using their model, they do that for you. You only need to put your variables in and done.
It is way easier to be consistent in your code. And easy to always escape strings etc when doing inserts/updates. Security is important.
<troll>
Because some people are allergic to SQL and want to shoehorn objects into relational operations.
Security ? Use prepared statements. Portability ? Have a list of queries per DBM.
And if you have to dynamically generate a query, you may have to rethink how you separate your database layer from your application layer.
</troll>
The advantage of those ways of doing database queries is all this code can be generated quickly using some framework. Which enables you to prototype applications very fast which you'll need often.
And you don't have to learn vendor specific SQL when going from one DBM to another (google "Oracle Limit" to see an example of what I mean).
I am working on an architecture redesign at my work and we've basically settled on a loosely-basic MVC custom solution. The intentions are to have the standard CRUD operations plus additional list operations defined in each of the models in our system.
Unfortunately about 30% of the code in our system uses complex joins and otherwise advanced querying that doesn't fit this model. Which is to say it could fit the model, but the list function would be huge and certainly error prone which is something we are trying to solve with the rewrite.
Given that, where would you place complex and very specific queries in such a system? We've been toying with a few options.
Add multiple versions of list/get in addition to the basic ones
Add in custom models for these queries that reside as siblings to the model directory
Don't use models in this situation and add the work directly in the action
We have outsourced help as well so we are attempting to keep it as simple as we can in terms of implementation and maintainability. ORM solutions or other heavyweights are out of the question.
Where would you want to see such things placed as a developer?
I apparently lack the privileges necessary to comment, so I'm posting this as answer...
Could you provide an example or two of the kinds of queries you have that don't fit into a model? Generally speaking: a good ORM will get you a long way, but some queries really are just too hairy to map easily, and if your team already has strong SQL skills the ORM can also seem like it's getting in the way.
First , all you're queries should stay in you're model .
Second , most of mvc frameworks provide more than just simple crud for you're database operations like a query functionality that where you can pass the query string , in this case you can build you're queryes manualy or with a query builder like for example Zend_Db_Table_Select and that handles multiple joins prety well . Or again if we look some place else than Zend let's say Codeigniter , it still provides a query builder for the model where you can add you're joins or build any other kind of complex queries .
That being sayd , it looks like you're base model class ( the one you extend each of you're models ) needs a query builder functionality , then you should be all good as you would be able to build any query you like inside any model you like .
I have similar issues in am MVC framework I've been building from scratch.
I don't particularly like the overhead of SELECT * on complex queries so I didn't build any of that functionality in whatsoever.
It's slower to code, but I code every query by hand in the relevant class (my model calls a Class 99% of the time).
For really complex queries shared amongst various routines, I have functions that return the generic joins and then concat the additional parameters for that particular query.
Example provided as requested:
private function returnFindClientRequests(){
$query = "SELECT
SR.sign_project_name, SR.module_signregister_id_pk
,SRI.module_signregister_sign_id_pk,SRI.sign_location_address
,SRR.status, SRR.module_signregister_item_client_request_id_pk, SRR.client_comment, SRR.requested_by_user, SRR.date_created
,SRR.admin_comment, SRR.date_actioned
,CL.client_name, CL.module_client_id_pk
FROM
`module_signregister` SR, `module_signregister_item` SRI, `module_signregister_item_client_request` SRR, `module_client` CL
WHERE
SR.module_signregister_id_pk = SRR.module_signregister_id_pk
AND SRR.module_signregister_sign_id_pk = SRI.module_signregister_sign_id_pk
AND SRR.requested_by_group = CL.module_client_id_pk
AND " . Database::groupQuery('CL');
return $query;
}
This query is shared amongst some other functions but also uses a call to Database::groupQuery() that us used to return session specific variables to many of the queries.
Models are workers - if you have 100 reports you're potentially going to need 100 models. Joins have nothing to do with MVC - how your data is addressed is another pattern altogether. If you're not using ORM and you're not using active records then all that's left is sending the SQL straight to the server via a model. Probably via a dedicated database class but the model will handle the query and its results.
I've been reading several articles on MVC and had a few questions I was hoping someone could possibly assist me in answering.
Firstly if MODEL is a representation of the data and a means in which to manipulate that data, then a Data Access Object (DAO) with a certain level of abstraction using a common interface should be sufficient for most task should it not?
To further elaborate on this point, say most of my development is done with MySQL as the underlying storage mechanism for my data, if I avoided vendor specific functions -- (i.e. UNIX_TIMESTAMP) -- in the construction of my SQL statements and used a abstract DB object that has a common interface moving between MySQL and maybe PostgreSQL, or MySQL and SQLite should be a simple process.
Here's what I'm getting at some task, are handled by a single CONTROLLER -- (i.e. UserRegistration) and rather that creating a MODEL for that task, I can get an instance of the db object -- (i.e. DB::getInstance()) -- then make the necessary db calls to INSERT a new user. Why with such a simple task would I create a new MODEL?
In some of the examples I've seen a MODEL is created, and within that MODEL there's a SELECT statement that fetches x number of orders from the order table and returns an array. Why do this, if in your CONTROLLER your creating another loop to iterate over that array and assign it to the VIEW; ex. 1?
ex. 1: foreach ($list as $order) { $this->view->set('order', $order); }
I guess one could modify the return so something like this is possibly; ex. 2.
ex. 2: while ($order = $this->model->getOrders(10)) { $this->view->set('order', $order); }
I guess my argument is that why create a model when you can simply make the necessary db calls from within your CONTROLLER, assuming your using a DB object with common interface to access your data, as I suspect most of websites are using. Yes I don't expect this is practical for all task, but again when most of what's being done is simple enough to not necessarily warrant a separate MODEL.
As it stands right now a user makes a request 'www.mysite.com/Controller/action/args1/args2', the front controller (I call it router) passes off to Controller (class) and within that controller a certain action (method) is called and from there the appropriate VIEW is created and then output.
So I guess you're wondering whether the added complexity of a model layer -on top- of a Database Access Object is the way you want to go. In my experience, simplicity trumps any other concern, so I would suggest that if you see a clear situation where it's simpler to completely go without a Model and have the data access occur in the equivalent of a controller, then you should go with that.
However, there are still other potential benefits to having an MVC separation:
No SQL at all in the controller: Maybe you decide to gather your data from a source other than a database (an array in the session? A mock object for testing? a file? just something else), or your database schema changes and you have to look for all the places that your code has to change, you could look through just the models.
Seperation of skillsets: Maybe someone on your team is great at complex SQL queries, but not great at dealing with the php side. Then the more separated the code is, the more people can play to their strengths (even more so when it comes to the html/css/javascript side of things).
Conceptual object that represents a block of data: As Steven said, there's a difference in the benefits you get from being database agnostic (so you can switch between mysql and postgresql if need be) and being schema agnostic (so you have an object full of data that fits together well, even if it came from different relational tables). When you have a model that represents a good block of data, you should be able to reuse that model in more than one place (e.g. a person model could be used in logins and when displaying a personnel list).
I certainly think that the ideals of separation of the tasks of MVC are very useful. But over time I've come to think that alternate styles, like keeping that MVC-like separation with a functional programming style, may be easier to deal with in php than a full blown OOP MVC system.
I found this great article that addressed most of my questions. In case anyone else had similar questions or is interested in reading this article. You can find it here http://blog.astrumfutura.com/archives/373-The-M-in-MVC-Why-Models-are-Misunderstood-and-Unappreciated.html.
The idea behind MVC is to have a clean separation between your logic. So your view is just your output, and your controller is a way of interacting with your models and using your models to get the necessary data to give to the necessary views. But all the work of actually getting data will go on your model.
If you think of your User model as an actual person and not a piece of data. If you want to know that persons name is it easier to call up a central office on the phone (the database) and request the name or to just ask the person, "what is your name?" That's one of the ideas behind the model. In a most simplistic way you can view your models as real living things and the methods you attach to them allow your controllers to ask those living things a series of questions (IE - can you view this page? are you logged in? what type of image are you? are you published? when were you last modified?). Your controller should be dumb and your model should be smart.
The other idea is to keep your SQL work in one central location, in this case your models. So that you don't have errant SQL floating around your controllers and (worst case scenario) your views.