I'm creating a movies website, IMDB.com like.. I'm really new to PHP and programming at all but I have some books and StackOverflow of course :)
I have already done lot of the work, but now I have more than 600 lines of code (PHO only) per page and more than 20 database tables only for storing and geting the movie data (many-to-many relationships)
Most of the code are MySQLi queries (prepared statements) to insert/get data and loops. Nothing fancy, just basic PHP/MySQL.
I have some questions:
It is recommended to use MySQLi prepared statements for every SQL query or is better just to use old MySQL for internal PHP/database queries and leave prepared statements for user input only?
To get all the movie data and show it I need to get the data from more than 16 different tables. I use one MySQL query per table (somethimes more) and lots of loops. This is the correct way a website need to work?? I mean.. this is normal???
How can I simplify the code to simplify the reading? Can I separete all those queries to external files?? Can I create functions to handle each table query??
Hope you can give me a hand and maybe you have some more suggestions for correctly building such a website.
Thanks!!
As mentioned in the anwsers above I would also point you to using a framework that impliments the MVC design pattern. Along with that most of the frameworks have an ORM built in but if they do not you can look at Symphony or EZPDO is another good ORM to tie into your Model in (M)VC.
CodeIgniter is a very fast and light weight MVC framework that would allow you to bootstrap pretty quickly but you may also want to look into ZF (ZendFramework). ZF has a great framework feature set and is pretty flexible overall.
Beyond that be sure to seperate your reads and your writes in either or Model or your calls to the ORM of choice. This will allow you to slave data to multiple MySQL Boxes for bigger performance but allows you to use one database engine to start out.
Add in the ability to use Memcached so that you can cache your data/objects vs hitting the database.
When using cache put some thought into how you would expire cache for a database update. In other words if your selecting data from a database to display in a view and that data is has not changed you should not need to hit the database every time but rather pull it from memory. Once the data actually does change you'd want to invalidate that cache so it's not stale and then re-cache the new data.
memcached: http://www.danga.com/memcached/'
-facebook also has a version
CodeIgniter - http://codeigniter.com/
EZPDO - http://www.ezpdo.net/blog/?p=2
ZendFramework -http://framework.zend.com/
Consider looking at or using a web framework for your website.
symfony
CakePHP
CodeIgniter
Are some of the more mainstream ones. Learn from them if anything.
Prepared statements are just fine for your own internal queries to. You'll have a strutured approach for all queries.
Well it depends on what you're showing. But I would say that you normally could use joins to get the data you need from more tables. You'll have a lot less quering to get the correct data, and it sounds like all your data is connected somehow to the one movie you're showing.
As Peter D comments, I would recommend using a web framework to learn how to seperate out the database handling from the view. Are you using an object oriented approach now? Look at the MVC pattern that some of these frameworks implement, that'll get you going.
Like Peter D mention before add this one to the list of framework to use. Zend Framework http://framework.zend.com
Open source and free.
It is recommended to use MySQLi ...
Definitely MySQLi, but it's a big question by itself, if you start coding you'll need to grasp the basic of T-SQL to understand the difference.
To get all the movie data ...
It depends on alot of things. Size of database. Wanted results i.e. the information that need to be displayed, response time of the queries vs displaying in user view. Do you know about JOIN, UNION?
How can I simplify the code to ...
Yes to all theses questions. www.w3schools.com/php/ if it can be of any help and learn the MVC pattern. Useful to alot of programming language these days. Maybe a framework would help you here
To this questions:
"To get all the movie data and show it
I need to get the data from more than
16 different tables. I use one MySQL
query per table (somethimes more) and
lots of loops. This is the correct way
a website need to work?? I mean.. this
is normal???"
No. If I understand you correctly, you should be using some type of JOIN depending on the data you're retrieving from the database. Getting results for huge amounts of data, and then picking out only the pieces you want in PHP is much slower than letting the database do the work of sorting/retrieving only the records/info you want to show.
I highly recommend a somewhat dated but very easy to grasp book that covers PHP and MySQL/Databases in general: http://www.dmcinsights.com/phpmysql2/ - It covers a lot of "in practice" techniques along with the code, so it'd be great to learn from.
There is a apparently a third edition with updated info, but I have not looked at it.
Related
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 am working on a web application which involves create list of Restaurants in various lists like "Joe's must visit places". Now for each Restaurant and list, I have display on website which calculates
Calculating popularity of a Restaurant
Popularity of a list
Number of lists a Restaurant is present in
Currently I am using MySQL statements in PHP for this but planning to switch to MySQL VIEWS and do a simple select statement in PHP...
my question is,
What is Advantage/Disadvantage of using VIEWS over writing sql queries in PHP?
Using views adds a level of abstraction : you may later change the structure of your tables, and you will not have to change the code that displays the information about the lists, because you will still be querying the view (the view definition may change, though).
The main difference is that views are updated after each insertion, such that the data is "ready" whenever you query the view, whereas using your custom query will have MySQL compute everything each time (there is some caching, of course).
The bottom line is that if your lists are updated less frenquently than they are viewed, you will see some gains in performance in using views.
My complete answer would depend upon several things (from your application's perspective):
do you plan to allow users to create and share such lists?
can users create lists of any kind, or just by plugging values into existing query templates?
Assuming you have a couple of pre-defined lists to display:
Use of views offers a couple of advantages:
your code will be cleaner
the query to generate the views will not have to be parsed each time by mysql.
I'm not sure about this: I don't think mysql caches views as Tomasz suggests - I don't think views contain "already preparted data".
One disadvantage is that the logic involved in creating the list goes into the database instead of living in your PHP code - something I'm very averse to. In my world databases are for data, and code is for logic.
Cheers
The original question was about pros and cons, but not seeing much about disadvantages in the answers so far.
Isn't one disadvantage of views that they can give you the false comfort of running a simple query?
For instance, SELECT username FROM myview WHERE id='1'
That looks simple, but what if "myview" is a really complex SELECT... Perhaps even built on other views? You end up having a simple-looking query that, in the background, takes a whole lot more work than if you had written your query from the ground up.
I've been experimenting with views, and despite the benefits, have not yet been fully sold.
I'd be interested in hearing what others perceive about the disadvantages of Views, rather than just the party line about why views are so great. Might still make the switch, but would like to understand more about performance.
If that tables you are trying to make view from are not subject to a frequent change, definitely you gain performance, as you are only doing simple select from already prepared data. But be aware of the fact, that view is not something that is made "once and forever" - every change of a content of one of the tables will make database engine do "view refreshing", so another query (query you are making view from) must be called to taki into account changes that were made. To sum up:
Infrequent changes? Performance. Frequent / constant changes (community adding, commenting, rating your restaurants) - better go with SQL queries.
Disadvantages:
In my opinion databases are used for data layer and it is not that proper to put business code inside them. It both reduces maintainability and it contradicts clean separation of layers. The same applies to including business code and calculations in java scripts of web pages. For java script it is even more serious since it creates security threats. Source control for the code inside database is also another issue.
Now that code is inside database, the security and access complications (to views and stored procedures) is also added.
Migrating an application from one database engine to another will be much more difficult (since in addition to simple queries the stored procedures/views etc. are possibly different too). If the database is only about data then an abstraction layer could allow changing the database engine (at least on at some extent).
Advantages:
Slight performance gains (since data is not coming out of the database for processing, it is processed right inside the database).
Code will seem cleaner (since the dirtiness is hidden inside the database views, stored procedures etc.).
I am fond of dbstructure definition of msaccess which lets defining at once and creating the data entry forms, datatables and reports at once easily.
I have been searching for some framework which would generate the data entry forms, data tables and reports easily. I guess the only thing I need to define is complete datatable structure.
Is there any like that or better one than that?
EDIT:
well i am afraid that PHP frameworks have been limited to programmers only. I would like to extend it with some automated functions like autoform in msaccess which would generate data entry form, auto report for data listing. So that my development time would be again some less. I found doctrine nearly matching my specification but not sure as i haven't fully explored doctrine
Cake offers both "hard" (bake) and "soft" scaffolding, which should be very close to what you want. It's still only meant as a quick proof-of-concept tool and to get you up and running faster so you can concentrate on programming the business logic. It's not meant as a hands-off solution nor to be used in production.
What you seem to be looking for is a database frontend like phpMyAdmin or SQL Buddy, not a PHP framework.
Symfony provides an admin generator that builds all the forms on the fly and it will also update itself when you change your db schema. It is based on doctrine which you say you looked at so that would make things a bit easier for you.
I'm currently mucking about with CakePHP, deciding if I'll use it in an upcoming web application.
The problem is, I've got several tables which at some point share relevant data with each other. If I were to write all the code myself I would use an SQL query using rather a lot of different joins and subqueries. But from what I understand CakePHP only supports joins between two tables.
So for example, I have Users, Profile, Rank, Rating tables and I want to get the profile, rank and ratings of one particular user. CakePHP will do the trick by using multiple, separate SELECT statements. But this would be possible using one query with multiple joins. Performance is expected to be quite important, so not being too wasteful with SQL queries is a major perquisite.
I've found two hacks (one behaviour and one using bindModel) and a similar StackOverflow thread.
I'm undecided whether to use the behaviour or the bindModel hack. Could anybody shed any light as to what is the best approach - viz. what integrates best in the overall CakePHP structure (are features like pagination still available)? Or is there another approach which is ultimately better. The SO thread mentions a method using containables.
Hope I'm not wrong in opening a separate question for this, but the older thread lists some solutions, but the answer isn't that clear to me for the aforementioned reasons.
The easiest way to do this is to not bother with reducint the sql queries and to implement some form of caching.
The next solution - skipping over the Containable behavior since it doesn't work to reduce your queries is to do some ad-hoc joins in the find calls directly. Pushing these into the model so that you can call them from a central place is recommended. The good article on this technique is on the bakery here: http://bakery.cakephp.org/articles/view/quick-tip-doing-ad-hoc-joins-in-model-find
The best solution I have found to date is Rafael Bandeira's Linkable behavior : http://blog.rafaelbandeira3.com/2008/11/16/linkable-behavior-taking-it-easy-in-your-db/ which allows you to use a custom key in the options array that defines the fields and relationships to join on in a clear fashion and uses the technique described in 1 to use joins instead of sequential queries.
Good luck with your project.
The link to this bakery article in the other StackOverflow article you mentioned, is probably the better method for doing ad-hoc joins (without bindModel or a custom behavior). You can already specify joins inline (including extra tidbits such as the type of join) in the options for any find() method calls, but those can be greatly simplified by creating a new find "type" that requires less writing in the find() options. That's what the article discusses.
I also used to use raw SQL for some queries, but found that it can lead to unforseen incompatibilities with databases that are supported by CakePHP. However, this may not be much of an issue if you are not writing a web application to be used by the masses.
I have had similar problems and because performance was a huge factor I decided to simply use raw SQL rather than try and fiddle with solutions purely to maintain "cake-ness". Plus sometimes it's just nice to know where the bottleneck is (even though a debug mode of 2 does help somewhat). Migrating the db won't ever be an issue.
I decided to go for performance over the convenience of auto-pagination, sorting etc. Really you can code these yourself - you did so in the past I'm sure.
The bindModel solution however does interest me. This is what I would go for next time I come across this problem.
I am wondering what the best way is using php to obtain a list of all the rows in the database, and when clicking on a row show the information in more detail, such as a related image etc.
Should I use frames to do this? Are there good examples of this somewhere?
Edit:
I need much simpler instructions, as I am not a programmer and am just starting out. Can any links or examples be recommended?
Contrary to other's recommendations, I would not recommend a framework or abstraction level. It will insulate you from understanding how php works and requires that you learn php and the framework structure/process at the same time. An abstraction layer is good practice in a commercial environment, but from the vibe of your question, you don't anticipate moving servers or migrating your db.
I recommend working procedurally (not object-oriented) with the php and mysql until you understand what is going on and how the language works.
To respond to your actual question:
You need to connect to the database: mysql_connect()
You need to select the database you want to work with: mysql_select_db()
You need to define the query: msyql_query()
You need to use a while loop to get the data:
$query=mysql_query("select * from table_name");
while($row=mysql_fetch_assoc($query)){
extract($row);
echo $name of field 1.": ".$name of field 2;
}
To make each row of output a link to more info rewrite the echo statement like this:
echo "<a href=\"http://addresstomoreinfo.php?image_id=".$image_id.\">".$name
of field 1.": ".$name of field 2."</a>";
The "name of field" variables represent the column names of your db table and I have made up the layout of the field name, colon, and second field name. How the info is displayed is up to you.
The question mark prepends the name of a variable that is defined in the addresstomoreinfo.php page that will be identified by $var=$_GET['image_id'];
Other php, html, css elements are involved in the big picture of accomplishing this. A good source for begining information is http://www.w3schools.com/ I also live and die by the php manual linked to above
I use tables and JavaScript to do this.
Data in a SQL database is, by nature, tabular. So I just select the data and create a table. Then, to drill down (when I need do), I provide a JavaScript "more" functionality and use CSS to hide/display the additional data.
You could begin with the PHP manual. It's rather well organised now. But now that my sarcastic bit's out of the way...
One of the best ways to work with your database (at the moment, your choice is MySQL, but this could change) is to abstract your code from direct interaction with it.
A tool such as ADODB is well worth getting to know and makes the task of "obtain a list of all the rows in the database" rather trivial.
The main advantage of this is that it insulates you somewhat from having to rewrite lots of code if you find you need to migrate your application to a server with a different database running on it.
Better still (imho) would be to look at a framework such as Zend's (well, they do MAKE php afterall) with it's DB abstraction called Zend_Db. This might be overkill for you right now as it appears, from looking at your other questions, that you're quite new to PHP/MySQL development.
Also good: Smarty (for abstracting your presentation from your logic)
I tend to use two separate pages. One to list, which links to the one that shows the detailed record. The one that lists passes an ID parameter on the link (ie. show.php?id=145), as for the show.php page will get that parameter from $_GET['id'].
This is the simplest approach to your problem.
If you're not a programmer, but want to use php to show what's inside your mysql tables, perhaps phpMyAdmin is what you're looking for?
If you're building a simple database-driven application, and you're just starting to learn PHP, the approach I'd recommend is to use a framework that generates these for you. Take a look at QCodo (http://www.qcodo.com), and in particular, this tutorial video: http://www.qcodo.com/view.php/demo_1_live
I think you don't really know what you're asking for! :-)
With a suitable framework, database and object abstraction layers, this is trivial (I've done it several times). But they are not trivial to write from scratch and not helpful for learning PHP from the basics. Unless you've done this in other languages.
OTOH, doing it all directly is still a good exercise (as #kevtrout has described), as long as you're willing to re-engineer the code repeatedly (even if you never really do) to develop suitable abstraction. IMO, there is far too much PHP kicking around that has long outgrown such a simple structure.