I have a design discussion with a collegue.
We are implementing a PHP MySQL database application. In the first instance we have written the Insert Get Update Delete, SelectAll and Search functions for a particular table, writting the table and fieldnames in the code, with several php files, one for the object class, one to draw the HTML table for that table, one for editing a row of that table, one containing the above functions, etc.
The disagreement comes as I have now written generic functions that read/write from the database and draw the HTML taking the table name as a parameter, letting these functions discovers the fieldnames from the database or class. So now that code can be used for any table, with any fields without having to manually go in change each function that needs alteration. I understand there will be cases where more table specific functionality is needed, and this I think that should be done as requirements arise, integrating common parts where possible.
My collegue on the other hand is adamant we should keep a set of files separate for each table, i.e. around 5 php files for each table. The read/write functions written differently in each case, with the need for any changes required for all tables to be affecting 5 x number of tables amount of times.
I can certainly say there will be more than main 15 tables in the database that will at least need basic funcionality.
What approach do you think is most appropriate?
One of the important principles in programming is DRY : Don't Repeat Yourself. So, everything common to several usecases should be written once, in a single location.
Now, I've never had to develop an application where each database table had the same, generic, crud pages. If it were the case, it wouldn't be a functional application, but a database management application. Are you sure you aren't redeveloping phpMyAdmin?
If you need the same code to handle several base operations on several tables, I would say you shouldn't write that code more than once : no need to repeat yourself :
it would take more time writing the application
it would take more time (and possible cause more bugs) when maintaining it
A possible solution could be to put as much common code as possible into a single class, common to many tables ; and, then, have a specific class for each table, that would extend that common class.
This way :
The common code would be written only once
Each table could have its specific code
The common code could be overridden for a specific table, if necessary.
About that, see the Object Inheritance section of the manual.
About that common class idea, you could even go farther, and write pretty much no code at all, if your CRUD is generic enough : there are ORM frameworks that might do that for you.
For instance, you might want to take a look at Doctrine.
We're on the first stages of development, and we don't have the complete functional specifications for the web application we're developing. Yes, we know, but it's not our fault.
So, we're building some parts keeping them pretty simple and straight-forward so we can build on top of that when we have more details on what to build.
We have a section for clients, for ads, for users, ... and I wanted to keep things separate because we don't know what's coming in the future. Yes, at the moment we have only a few fields and some basic listings and editing pages, but all that will grow.
It's not that I don't want to implement some generic code that we can reuse. It's that we don't know yet what will be the limitations in the near future, and I don't want to write generic code that we'll have to parametrize intensely.
For example, Alex built a generic Update method to which you pass an object and it will create an UPDATE SQL statement and execute it. OK, that's cool, but that doesn't work for the Users section of the web app because we store the password encoded. First, it won't encode the password. Second, if you edit a user and don't enter anything on the password and password-confirmation fields, the old password will remain. So, we have a problem with the generic Update method, and as I see it there are two possible solutions:
a) Parametrize the Update method so if it is modifying a user, keep the password if the password on the object is blank. And encode the password, of course.
b) Override the Update method for the child class.
Alex's implementation didn't use inheritance and he used the generic methods in a static class he'd call this way DataAccess::Update($object);. The method takes the table name from the class name as he modified the database to make them match (I prefer "Clients" for the table and "Client" for the class). So, option b is not possible with Alex's implementation.
The way I was trying to build it was keeping separate Update methods for each table. Yes, I was repeating myself but, as I said before, we don't have a full specification, so we don't know how it's going to grow. We have an idea, but we don't have the exact details.
So, the point here is that I don't want to write generic code until we have a much more detailed specification so we can evaluate what can and what cannot be shared between the parts.
Not all sections of the web app work the same and, as JB Nizet said: "If it were the case, it wouldn't be a functional application, but a database management application."
And I can tell you for sure this is not a database management application, even though Alex would say "we're just building a database app." Well, maybe, but a database application is not only showing/modifying the tables. And now, views won't solve all problems.
Again, as JB Nizet said: "If it were the case, it wouldn't be a functional application, but a database management application."
And now I'm repeating myself again, but this time there's no reason for that.
Thanks for your time.
Related
I asked myself what would be the best way to create a history table for a website, I'm only aware of two choices:
Use triggers
Add an extra insert statement to the code when an insert/update/delete statement related to it is used
They said that triggers would be a better way since the load would be on the database and not in the program. But since my website has multiple admins, I would also need to track who modified the content, which I think would only be possible by creating a modified_by column in the history table and manually insert values to it by inserting the session user to that column using the second option together with the time_modified, modified_from, modified_tovalues.
I need to find out if would this be an acceptable reason to use the second option? Are there any more options? Will the second option create any problems in the future?
There is a Rails gem https://github.com/airblade/paper_trail that implements your mentioned functionality comprehensively. I would assume it is doing it purely at the application code level and not the database(triggers) level. This could further indicate that option 2 is better. My thoughts are:
If you use triggers, you will have a serious performance trade off as your site traffic grows and CRUD operations go up. A lot of triggers will go off then.
Implementing some part of the business logic at the database level might be tempting but I would like to keep it all in one place that is in my application code.
You will have some serious thinking to do if you wish to keep your application database agnostic. You will need to re-implement the triggers if you use a different database server.
History keeping increases table size and might become a bottleneck for database performance. You have the option of keeping history for a limited time interval and then archive it to keep the database table nice and clean. Also, you can have a separate database server responsible for history related tables only. These things will be complex to do with triggers.
I can suggest solution # 2. Because i like when all business logic contained in one place (in PHP backend). This code will be more supportable and reusable. And you can save only changed fields into some JSON format. So it keep your HDD place and will work fast. I think triggers is very bad stuff, because you don't know what happens in next time in DB (you must always remember all your triggers):) So i don't use it.
Only one problem you will have - a lot of records in history table. So, i recommend remove records oldest that 3 month
I'd go with option 2. If you are comfortable with ORMs, I'd recommend using one here: a good deal of the history collection code is already written and tested for you.
For example, if you were to use Propel, it comes with a versionable behaviour, which manages a separate versions table, and version numbers per row. (Aside: I believe version 2 hasn't been released as stable yet, though it is linked from the project home page. I use version 1.7, which is still excellent. Both versions have this feature as far as I know).
Doctrine has a similar feature, Versionable, though it looks like that is deprecated in favour of EntityAudit.
I have developed a Web Interface for managing our devices (Dedicated Servers/Switches/etc) at work, however with my basic PHP knowledge, I ignored OOP completely. In the current state it just queries the MYSQL Database and populates the tables. Functions are all stored in a Functions.php file and called as needed.
As the project is functional and used now, I would like to rewrite this to be more efficient as it will be used among our other brands. I am having trouble applying the concept of classes to this project though (I use them all the time in C#/C++).
The way I see it, each Device be it a server, switch, etc. could be a part of a Device class that keeps properties like Datacenter, Name, etc. and methods such as Update, Delete, etc. I suppose I could additionally have a base Device class, then subsequent classes such as Server/Switch/etc. which inherit from that.
My question then is how is this more efficient? Each time the page loads I am still going to have to generate each instance of Device and then populate it from the Database, why I don't really see how this is better than the current implementation.
Thanks for any insight!
Using OOP is mostly unrelated to performance or efficiency. However, it allows you to organize your code in a modular fashion, and encourage code reuse.
A better webpage to explain can be found here.
I recently started working with Yii PHP MVC Framework. I'm looking for advice on how should I continue working with the database through the framework: should I use framework's base class CActiveRecord which deals with the DB, or should I go with the classic SQL query functions (in my case mssql)?
Obviously or not, for me it seems easier to deal with the DB through classic SQL queries, but, at some point, I imagine there has to be an advantage in using framework's way.
Some SQL queries will get pretty complex pretty often. I just can't comprehend how the framework could help me and not make things more complicated than they actually are.
Very General rule from my experience with Yii and massive databases:
Use Yii Active Record when:
You want to retrieve and post single to a few rows in the database (e.g. user changing his/her settings, updating users balance, adding a vote, getting a count of users online, getting the number of posts under a topic, checking if a model exists)
You want to rapidly design a hierarchical model structure between your tables, (e.g. $user->info->email,$user->settings->currency) allowing you to quickly adjust displayed currency/settings per use.
Stay away from Yii Active Record when:
You want to update several 100 records at a time. (too much overhead for the model)
Yii::app()->db->command()
allows you to avoid the heavy objects and retrieves data in simple arrays.
You want to do advanced joins and queries that involve multiple tables.
Any batch job!! (e.g. checking a payments table to see which customers are overdue on their payments, updating database values etc.)
I love Yii Active Record, but I interchange between the Active Record Model and plain SQL (using Yii::app()->db) based on the requirement in the application.
At the end I have the option whether I want to update a single users currency
$user->info->currency = 'USD';
$user->info->save();
or if I want to update all users currencies:
Yii::app()->db->command('UPDATE ..... SET Currency="USD" where ...');
In any language when dealing with the database a framework can help you by providing an abstraction over the database.
Here is a scenario I know I found myself in many times during my earlier development days:
I have an application that needs a database.
I write a ton of code.
I put the SQL statements in the code along with everything else.
The database changes somehow.
I'm stuck with having to go back and make 100 changes to all my SQL statements.
It's very frustrating.
Another scenario I found:
I write a ton of code against a database.
Bugs come in. Lots of bugs. I can't figure them all out.
I'm asked to write tests for my code.
This is impossible because all my code relies on a direct implementation of the database. How do you test SQL statements when they're with the actual code?
So my advice is to use the framework because it can provide an abstraction over the database. This gives you two really big advantages:
You can potentially swap out the database later and your code stays the same! If you're using interfaces/some framework, then most likely you're dealing with objects and not SQL statements directly. A given implementation might know how to write to MySQL or SQL Server, but in general your code just says "Write this object", "Read that list."
You can test your code! A good framework that deals with data will let you mock the database so you can test it easily.
Try to avoid writing SQL statements directly in the application. It'll save you pain later.
I'm unfamiliar with the database system bundled with Yii, but would advise you to use it a little bit to start with. My experience is with Propel, a popular PHP ORM. In general, ORM systems have a class per table (Propel has three per table).
Now, there'll probably be a syntax to do lookups and joins etc, but the first thing to do is to work out how to use raw SQL in your queries (for any of the CRUD operations). Put methods to do these queries in your model classes, so at least you will be benefitting from centralisation of code.
Once you've got that working, you can migrate to the recommended approach at a later time, without getting overwhelmed with the amount of material you have to learn in one go. Learning Yii (especially how to share code amongst controllers, and to write maintainable view templates) takes a while, so it may be sensible not to over-complicate it with many other things as well.
Why to use Yii:
Just imagine that you have many modules and for each module you have to write a pagination code; writing in old fashion style, will need a lot of time;
Why not use Yii ClistView widget? Oh, and this widget comes with a bonus: the data provider and the auto checking for the existance of the article that is about to be printed;
When using Yii CListView with results from ... Sphinx search engine, the widget will check if the article do really exists, because the result may not be correct
How long will it take for you to write a detection code for non existing registration?
And when you have different types of projects will you addapt the methods?
NO! Yii does this for you.
How long would it take for you to write the code in crud style ? create, read, update, delete ?
Are you going to adapt the old code from another project ?
Yii has a miracle module, called Gii, that generates models, modules, forms, controllers, the crud ... and many more
at first it might seem hard, but when you get experienced, it's easy
I would suggest you should use CActiveRecord.It will give many advantages -
You can use many widgets within yii directly as mentioned above.(For paginations,grids etc)
The queries which are generated by the Yii ORM are highly optimized.
You dont need to put the results extracted from SQLs in your VO objects.
If the tables for some reason modified(addition/deletion of column,changing data type), you just need to regenerate the models using the tool provided by yii.Just make sure you try to avoid doing any code changes in the models generated by yii, that will save your merging efforts.
If you plan to change the DB from MYSQL to other vendor in futur, it would be just config change for you.
Also you and your team would save your precious development time.
I'm developing PHP web applications for quite long but now learning OOP approach. To learn and practice, I'm developing a simple web app of "Multiple Choice Questions". When a registered user logs in, he is presented with a list of Quizzes. He selects one and gets questions with multiple answers with any one of them correct.
My questions are:
What are the rules to identify Classes? I think "Quiz", "Questions"
and "Answers" can be declared classes. Am I right?
What'll be association types among these classes (or the ones which
you'll suggest). What are the rules to identify association?
How to separate or present System Classes (e.g. database, validation
classes) and Business Domain Classes?
I'll be grateful if answers could be provided in the context of Quiz system as I have read a lot about "Animal-Dog" Class examples... Thanks in advance for your support.
One particular flavour of OOP you'll find helpful is the Model View Controller paradigm.
Classes in PHP are typically representations of 'objects', or things that ideally fulfil a certain task. A collection of them may work together to provide a more comprehensive functionality, while being of little use in isolation.
In MVC, these classes are generally split into (in simplified terms):
Models: classes that help you work with your database. You'll have one model for each table, and each model will provide you the ability to save and retrieve data, as well as manipulate it before and after the fact. In your case, a Question will be a model, and it might contain the question itself, and an answer.
Views: these aren't classes, but your raw HTML templates that have data from your models injected via a controller. In your case, one view may be a question view. Another may represent the index page. Yet another may present the results of the questionnaire.
Controllers: classes that act as a middle man between your view and your model. They'll fetch data from the relevant models and pass it to the view. In your case, this may be a Quiz controller. It'll fetch the requested question from the database and provide it to the view, and when the answer is submitted, the controller will pass it to the model to see if it's correct, and act accordingly.
Behind this MCV resides a framework (pre-made, or one you rolled yourself) that provides a number of libraries and abstraction layers to help you focus on your application logic. So there'll be database abstractions like ActiveRecord, there'll be wrappers for commonly used procedural functions, presented in an OOP context, there'll be templating systems to help pass data to your view and format it, and so on.
If you want to head in this direction, consider using an existing framework like CakePHP orCodeIgniter to give you a headstart. They'll familiarise you with OOP (to some extent) and how using classes can be beneficial for larger projects.
Well, as I see it, OOP tries to make things more simple, more understanable and more readable for us, programmers.
There arent rules to identify classes. Every programmer can implement different classes to a similar project. When I decide which classes to implement, I will be asking myself questions
like:
What functions do I need to implement ?
Do I have functions that provide support for a similar element in my project ?
Here is an example from my current project: I'm making an analytic system that present graphs for users. I've made 2 classes, one is called analytic and the second is called analyticQueries. The first one is responsible for all of the analytics database updating, and the second is responsible for taking data from the database and prepare it for the graphical engine.
Why didn't I make a single database class ? well, I thought It would be too heavy, and as I see it, there are 2 subjects that need to be seperated to better understand the program's way of work: one is writing the database and second is reading from it.
Another way of thinking of classes (And also a good way of planning your database) is asking these questions:
Who is using the project ?
What are the action of those who are using it ?
Who is using who ? (It can help you for making associations. In my project, both of the analytic classes are connecting to the database. I could make a third DBConnection class and include it in both of the classes, but I thought that it will not be that big and it is not something that is enough central in the project that needs its own class).
In your website, the users are people who log in, so you'll sure need a user table in your database. You will sure need a questions table and maybe answers table.
You can decide you want classes based on your database, for instance userManager can be a class with function responsible on all of the users actions (Login, update details, etc...) and have a questionManager that will handle questions presenting and validating answers.
OOP principles were difficult for me to grasp because for some reason I could never apply them to web development. As I developed more and more projects I started understanding how some parts of my code could use certain design patterns to make them easier to read, reuse, and maintain so I started to use it more and more.
The one thing I still can't quite comprehend is why I should abstract my data layer. Basically if I need to print a list of items stored in my DB to the browser I do something along the lines of:
$sql = 'SELECT * FROM table WHERE type = "type1"';'
$result = mysql_query($sql);
while($row = mysql_fetch_assoc($result))
{
echo '<li>'.$row['name'].'</li>';
}
I'm reading all these How-Tos or articles preaching about the greatness of PDO but I don't understand why. I don't seem to be saving any LoCs and I don't see how it would be more reusable because all the functions that I call above just seem to be encapsulated in a class but do the exact same thing. The only advantage I'm seeing to PDO are prepared statements.
I'm not saying data abstraction is a bad thing, I'm asking these questions because I'm trying to design my current classes correctly and they need to connect to a DB so I figured I'd do this the right way. Maybe I'm just reading bad articles on the subject :)
I would really appreciate any advice, links, or concrete real-life examples on the subject!
Think of a abstracting the data layer as a way to save time in the future.
Using your example. Let's say you changed the names of the tables. You would have to go to each file where you have a SQL using that table and edit it. In the best case, it was a matter of search and replace of N files. You could have saved a lot of time and minimized the error if you only had to edit one file, the file that had all your sql methods.
The same applies to column names.
And this is only considering the case where you rename stuff. It is also quite possible to change database systems completely. Your SQL might not be compatible between Sqlite and MySQL, for example. You would have to go and edit, once again, a lot of files.
Abstraction allows you to decouple one part from the other. In this case, you can make changes to the database part without affecting the view part.
For very small projects this might be more trouble than it is worth. And even then, you should still do it, at least to get used to it.
I'm NOT a php person but this is a more general question so here goes.
You're probably building something small, sometimes though even something small/medium should have an abstracted data layer so it can grow better.
The point is to cope with CHANGE
Think about this, you have a small social networking website. Think about the data you'll store, profile details, pictures, friends, messages. For each of these you'll have pages like pictures.php?&uid=xxx.
You'll then have a little piece of SQL slapped in there with the mysql code. Now think of how easy/difficult it would be to change this? You would change 5-10 pages? When you'll do this, you'll probably get it wrong a few times before you test it thoroughly.
Now, think of Facebook. Think of the amount of pages there will be, do you think it'll be easier to change a line of SQL in each page!?
When you abstract the data access correctly:
Its in one place, its easier to change.
Therefore its easier to test.
Its easier to replace. (Think about what you'd have to do if you had to switch to another Database)
Hope this Helps
One of the other advantage of abstracting the data layer is to be less dependent on the underlying database.
With your method, the day you want to use something else than mysql or your column naming change or the php API concerning mysql change, you will have to rewrite a lot of code.
If all the database access part was neatly abstracted, the needed changes will be minimal and restricted to a few files instead of the whole project.
It is also a lot easier to reuse code concerning sql injection or others utility function if the code is centralized in one place.
Finally, it's easier to do unit testing if everything goes trough some classes than on every pages from your project.
For example, in a recent project of mine (sorry, no code sharing is possible), mysql related functions are only called in one class. Everything from query generation to object instantiation is done here. So it's very for me to change to another database or reuse this class somewhere else.
In my opinion, the data access is one of the most important aspects to separate / abstract out from the rest of your code.
Separating out various 'layers' has several advantages.
1) It neatly organises your code base. If you have to make a change, you'll know immediately where the change needs to be made and where to find the code. This might not be so much of a big deal if you're working on a project on your own but with a larger team the benefits can quickly become obvious. This point is actually pretty trivial but I added it anyway. The real reason is number 2..
2) You should try to separate things that might need to change independently of each other. In your specific example, it is conceivable that you would want to change the DB / data access logic without impacting the user interface. Or, you might want to change the user interface without impacting on the data access. Im sure you can see how this is made impossible if the code is mixed in with each other.
When your data access layer, has a tightly defined interface, you can change its inner workings however you want, and as long as it still adheres to the interface you can be pretty certain it wont have broken anything further up. Obviously this would still need verifying with testing.
3) Reuse. Writing data access code can get pretty repetitive. It's even more repetitive when you have to rewrite the data access code for each page you write. Whenever you notice something repetitive in code, alarm bells should be ringing. Repetitiveness, is prone to errors and causes a maintenance problem.
I'm sure you see the same queries popping up in various different pages? This can be resolved by putting those queries lower down in your data layer. Doing so helps to ease maintenance; whenever a table or column name changes, you only need to correct the one place in your data layer that references it instead of trawling through your entire user interface and potentially missing something.
4) Testing. If you want to use automated tool to carry out unit testing you will need everything nicely separated. How will you test your code to select all Customer records when this code is scattered all throughout your interface? It is much easier when you have a specific SelectAllCustomers function on a data access object. You can test this once here and be sure that it will work for every page that uses it.
There are more reasons that I'll let other people add. The main thing to take away is that separating out layers allows one layer to change without letting the change ripple through to other layers. As the database and user interface are areas of an application / website that change the most frequently it is a very good idea to keep them separate and nicely isolated from everything else and each other.
In my point of view to print just a list of items in a database table, your snippet is the more appropriate: fast, simple and clear.
I think a bit more abstraction could be helpful in other cases to avoid code repetitions with all the related advantages.
Consider a simple CMS with authors, articles, tags and a cross reference table for articles and tags.
In your homepage your simple query will become a more complex one. You will join articles and users, then you will fetch related tag for each article joining the tags table with the cross reference one and filtering by article_id.
You will repeat this query with some small changes in the author profile and in the tag search results.
Using a abstraction tool like this, you can define your relations once and use a more concise syntax like:
// Home page
$articles = $db->getTable('Article')->join('Author a')
->addSelect('a.name AS author_name');
$first_article_tags = $articles[0]->getRelated('Tag');
// Author profile
$articles = $db->getTable('Article')->join('Author a')
->addSelect('a.name AS author_name')->where('a.id = ?', $_GET['id']);
// Tag search results
$articles = $db->getTable('Article')->join('Author a')
->addSelect('a.name AS author_name')
->join('Tag')->where('Tag.slug = ?', $_GET['slug']);
You can reduce the remaining code repetition encapsulating it in Models and refactoring the code above:
// Home page
$articles = Author::getArticles();
$first_article_tags = $articles[0]->getRelated('Tag');
// Author profile
$articles = Author::getArticles()->where('a.id = ?', $_GET['id']);
// Tag search results
$articles = Author::getArticles()
->join('Tag')->where('Tag.slug = ?', $_GET['slug']);
There are other good reasons to abstract more or less, with its pros and cons. But in my opinion for a big part the web projects the main is this one :P