I am currently working on a personal project. The entire site is dynamic so I am requesting all sorts of information from the database on all pages. I noticed that I was duplicating specific code to display the data to the pages. A few examples would be applying htmlspecialchars to the data or iterating through to set image paths, etc.
What i am wondering is if this is a bad decision to make so I can course correct early on. Most internet resources have said that the controller manipulates while the model fetches, updates, inserts, etc. into db. BUT it just makes sense at least for me anyway to manipulate the output data via model since all pages will use it in the same way.
No. A model merely represents data, whether that came from a database, an XML file, a web service/API, or even just an array.
If you find yourself doing the same thing over, then it’s time to re-factor and DRY your code out. For things like sanitising data, you would normally have a presenter that takes your model, and returns it data sanitised however you wish. That way the model has its single responsibility (represent data), and your present had a single responsibility of transforming data.
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.
By business model, or business objects, I mean plain old objects like a "User" with all their properties name, adress, ...; in addition to all the user properties let's say each user would have an "AppointmentBook" object, each book has a set of "TimeSlot" objects, etc.
The business model has objects with references between them, at least that's how I code a business model in Java.
Here comes the question:
To intialize my business objects, in Java, I would
fetch all of the data from DB only once during application
initialization,
map data from my DB to my business objects
store in memory (maps) and they would be shared across all the requests.
PHP's Share-Nothing-Architecture is confusing me for proper OO programming:
If I use the same logic, I would have to fetch all the objects from DB, for every request (I know I could still cache, but you don't cache all of your DB, it's not a question about caching but rather about the way of programming in PHP and its architecture).
So let's say that for one HTTP request, I just need the User properties and I don't need to access his appointment book. It would be a pitty to fetch all the data from the DB for all the objects the User makes reference to, as I just need his properties. This means that I will initialize PHP objects from my model with a lot of NULL values (NULL because of the objects contained in User that I won't load) which can later on lead to errors.
I was wondering how professional PHP developers usually use their business objects?
(I'm coming from Java)
UPDATE: It was kind of stupid to say that I would load the whole database into memory during application init in Java. What I rather meant is that, if I need to fetch a specific user, I could just load all of its data and that would be accessible through all the requests.
In PHP you do not keep all the data of your domain business model in the memory. Instead you only request from DB ( though cache, if needed ), the data you want.
Model layer in php should be built from multiple domain object and data mappers ( i assume, that part is not so different from Java ). If you need User details, then you fetch only that information from database/cache. You most likely will have a separate mapper just for dealing with user(s).
You display the information about that user, and forget about the query. Next request (when and if it comes) will require different information. Maybe you will want ContactList for that User ... then you really do not need user itself, only his user_id. Again, you let you mapper to fetch data into the domain object responsible for handling contact list, and if contact list contains User instances, then just create them, but leave in "unfetched" state (object knows only own user_id). Fetch them only if you really need to, and only the parts which you will use ins that "view".
P.S. you might have notices, I told that model later should be segmented, but quite often php developers just create single class of each DB table (which implements ActiveRecord) and call it "model". This is a result caused by Ruby on Rails influence on php framework developers, which, IMHO, is one of the worst things that has happened to PHP in past 5 years.
Your Java example implies your storing your entire databases content in memory. If your doing that, what's the point of the database? Why not just create all those object and memdump them for persistence.
If I use the same logic, I would have to fetch all the objects from DB, for every request
That's simply madness, you don't need to fetch anything, you create new instances when you need them and destroy them when you no longer need them.
So let's say that for one HTTP request, I just need the User properties and I don't need to access his appointment book.
That's easy, redesign your user. Your user needs it's properties and a property called appointmentBook which is simply an array of appointment book ids.
If you actually need those appointments you can fetch them from the database later.
This means that I will initialize PHP objects from my model with a lot of NULL values (NULL because of the objects contained in User that I won't load) which can later on lead to errors.
Not really, if this is the case your User object is too big. Make it smaller, you should load the entire user. Except of course the user has to be small enough for you to sensible load it.
If you don't want that then you can always create a UserProperties class and let every User have one. When you load the User you load the properties, but you also have an option to create the properties seperately.
Even in Java you would not load all data from the database into memory. You can however - as you write - often load more compared to short Transaction Scripts you normally have in PHP.
You models should be "clever" then to only load the data from the persistence storage that is needed to perform the requested action. This requires the object to be "clever" enough to lazy-load data probably.
This can be achieved with a Domain Model that knows enough about itself and a Data Mapper that knows enough about the storage for example.
There are other patterns as well which might suit your needs depending on the type of application, however a Domain Model together with Data Mapper is quite flexible.
An exemplary data mapper in the PHP world is Doctrine.
I have a enterprise webapp that is extremely ajax heavy, all data goes though some sort of ajax, so is saving, updating deleting etc. Modeled after the MVC paradigm
The site is mostly compromised of three parts
Interface page
An interface page only contains the interface and all the js that goes with it, no data processing of any kind. All data is requested after the interface has loaded. All data is transmitted and received in a common interchange format.(More below)
eg. edit_inventory.php or list_inventory.php
Backend Page
A backend page that processes data when commands are received kinda like APIs that you see on other webapps, it basically have a giant switch statement of all the commands it accepts.
eg. ajax_inventory.php
Classes Page
A page with a single class that handles a single object, eg item, invoice, account etc.
They currently handle only database connections, getting data and saving data. It is also responsible for error checking and taking care of foreign key links/cascade data.
Copying from a typical CMS, a set of classes, interface and backends are called components.
root
>comp
>inventory
>class_inventory.php
>ajax_inventory.php
>edit_inventory.php
>list_inventory.php
>ajax_inventorymerge.php
>edit_inventorymerge.php
>account
After a while, I noticed this method or idea have generated a lot of files, current at 400+ files just for interfaces and backends. The 400+ pages are quite unique in their own respects, most are complex CRUD interfaces for billing, inventory, reporting, misc data.
The questions, I am looking for answers that are commonly used.
Is this a good pattern, can it be
improved?
Should objects and classes such as "Product" responsible for formatting the data into the common interchange format as mentioned earlier?
Should objects allow unfiltered access to their data or only filtered access? Unfiltered access also meant that there must be lots of filtering to be done at the backend level. Filtering is mostly getting rid of unwanted data(waste of bandwidth) or metadata. However, sometimes it might be data that the user should not see(Permission related). Filtering is mostly done on the key-values pair(form_data)
Since there are multiple data forms outputted by an object from html(form_html), messages(msg), key-value pair(form_data) etc. How would one best request the data in one whole, rather than $a->getData(), $a->getMsg, $a->getStuff?
Another interchange format? or just use the common interchange format as mentioned earlier?
Common Interchange format(in json)
{"msg":"Sucess",
"form_data":{
"id":100,
"product_code":"BLA",
"size":"3"
},
"form_html":{
"list":"<\/li><\/ul>"
},
"script":"alert('Some stuff');"
}
So I am a little confused on the object oriented part of PHP. Right away I will apologize for the fact I know very little about PHP and databases.
My question is when you are making, say, a database to hold users in it, why would you want to make a class/object for that user when you can just pull info from the database?
Also, if you were to make a object/class where is the data for the objects stored? For example, if I have a class with a username and email, and I make that object, were does it get stored?
Thanks for taking your time to help a learning noob!
My question is when your making per
say a database to hold users in it,
why would you want to make a
class/object for that user when you
can just pull info from the database.
You make objects to abstract away specific functionality. What happens if you move to, say, Microsoft SQL Server (hypothetically speaking)? Rather than update your entire site, you just edit the implementation of the object.
Also if you were to make a
object/class where is the data for the
objects stored? Like a class with a
username and email, and I make that
object, were does it get stored.
The same place as any other variable.
There are a LOT of reasons why you want to use some abstraction on top of just raw database access in any reasonably large software system. If you're looking at an Object Oriented approach you should consider that one of the core ideas of the Object Oriented paradigm is that an object encapsulates both data and logic that acts on that data.
Let's take a concrete example. Say that a part of your application (the UI) needs to display user information, including a nicely formatted user name. In an OO world you could have a User object which would store a local copy of the data in the database, and expose methods like getFormattedName(), or something similar. Now the rest of your application can use that code without needing to know about the database, or even how the name is formatted. On the other hand if you were just pulling data directly from the database then the UI part of the application (which doesn't really care about databases) still has to know itself how to get information about the user from the database, and how to format the users name nicely.
To put it simply, there are logic not captured in a database table but related to the entry. The database only stores the raw data. How the data is used and how it interacts with the rest of your application should be captured in your object methods.
You're missing a fundamental of object-oriented design. Ignoring inheritence entirely, Objects combine information/data and functions/procedures/operations into a single unit called an object. This object performs operations (methods/behaviors/functions/procedures) and has attributes. A database will not have the entire set of operational/procedural information. By design, a database will only contain data, and know nothing of how the data can be used or what the data does.
Databases store data in a tabular fashion which is designed to be speedy. Objects are so much more flexible; they can be trees, they can be lists, they can be widgets, or anything else out of a million things. They can represent presentation, data, or structure. And sometimes they are even faster (when it's easier to calculate a value on the fly rather than retrieve it from a database). Databases are very powerful and important but are only appropriate for a small subset of the tasks that a web application performs. The rest are made easier by objects.
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.