TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
IRC Channel
IRC Speech Bubble Join the friendly bunch on IRC...
(#TalkPHP on Freenode)

...Also available via a web interface.

See this thread for information on the TalkPHP Free Hugs Initiative™. Subject to availability.
Associates
Associates
CSS Tutorials
Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old 12-03-2007, 01:10 PM   #1 (permalink)
The Contributor
Upcoming Programmer 
 
Gurnk's Avatar
 
Join Date: Oct 2007
Location: US
Posts: 66
Thanks: 19
Gurnk is on a distinguished road
Book Category System Tutorial

When I first started using PHP, and really still today, I used it for Content Management Systems. I got them to be pretty advanced, except there was one thing that always got me. Whenever I did categories, I was limited to however many fields I had in the "articles" table. I'm sure you PHP gurus already know how I'm going to solve this problem, so this article is mostly for some new comers.

The basic idea of this setup is selecting the categories from one table and list them. Then you insert each check box (category) into one field, separated with a comma. Then you explode the categories when you want to display it.

You need to first setup your tables. Make one table called Categories, with 2 fields. Primary ID, and Name. (You can do a 3rd - description, if you want). Then if you already have a posts table for your CMS, just make a new field called "cats" or "categories". On your page where you add a new post, add the following code.

PHP Code:
<?php
    $select 
= @mysql_query("SELECT title FROM `cats` ORDER by title DESC");
          while(
$row mysql_fetch_array($select)) { 
               
extract($row);        
               echo
'<input type="checkbox" name="cat[]" value="'.$title.'" />'.$title.' <br />'
           }
?>
This code will get all the rows from the "cats" table, and list them next to a check box. The name of the check box is an array, so you can have multiple checks.
(Note: This needs to be inside the form you use to post your articles).

Now before you insert this data into the database, we need to link all the check boxes together. Heres how we can do it.

PHP Code:
// Make an array out of our name="cat[]" value on the checkbox.
$cats array_map("mysql_real_escape_string",$cat);
// Implode (Opposite of explode) them together with a comma.
$imp implode(",",$cats); 
Now just insert the "$imp" variable into the database field that you made (probably cat) like normal. So if you checked "Site Updates" and "Random Info", it would insert "Site Updates, Random Info" into the single field.

Now its time to actually call the categories. Here is how we can do that:

PHP Code:
$cats explode(","$cats);
$totalcats count($cats);
$i 0;
while(
$i $totalcats) { 
     echo
'<a href="browse.php?view='.$cats[''.$i.''].'" >'.$cats[''.$i.''].'</a>';
     if(
$i == $totalcats 1)
           echo 
"";
      else 
           echo 
", ";
     
$i $i 1;

All of that above code should be inside your loop that is getting your posts.

First we define the variable $cats as an explosion of the field "cats". Remember when we imploded it before we put it into the database, now we are doing the opposite. We are finding the "," between each one, and splitting it up into an array. Then we count it with $totalCats, so we know how many pieces it was exploded into. The $i variable is just set to 0, for counting purposes.

The next piece of code is called a while loop. It means this.

PHP Code:
while(something is true) {
     do 
this

So, while $i (0) is less than $totalCats, continue. The first echo in our loop echos out a link and the name of the category. $cats[''.$i.''] is getting whatever value is represented in our array by cat[0]. In arrays, the counting starts as 0 So that means it is echoing our first piece of exploded field. The next part:

PHP Code:
if($i == $totalcats 1)
    echo 
"";
else 
   echo 
", "
This is a little cosmetics thing. Its saying that if $i (our number) is 1 less than the total number of exploded pieces, echo nothing. If it is not, echo a ", ". It needs to be one less, since arrays start counting at 0. This means if you have 3 categories, "Cat1", "Cat2", and "Cat3", it will be "Cat1, Cat2, Cat3" It didn't add that last comma, since it realized Cat3 was the last one.

The very last $i = $i + 1; is to increment our $i variable, so the while loop will move onto the next exploded piece.

That about does it. :) I know the tutorial may be sort of hard to follow, since I assumed you had a few things setup already, but I didn't have time to write out a whole CMS tutorial, since I am at school. But if you have any questions on how to get it working, I'll be glad to answer them as best I can.

Good luck!
Send a message via MSN to Gurnk
Gurnk is offline  
Reply With Quote
The Following 3 Users Say Thank You to Gurnk For This Useful Post:
codefreek (12-29-2007), Haris (12-03-2007), Wildhoney (12-03-2007)
Old 12-03-2007, 03:44 PM   #2 (permalink)
The Frequenter
Prolific Welcomer Upcoming Programmer 
 
Join Date: Sep 2007
Posts: 360
Thanks: 24
Haris is on a distinguished road
Default

Good job on the tutorial.

Thanks.
Haris is offline  
Reply With Quote
Old 12-03-2007, 04:01 PM   #3 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,280
Thanks: 90
Wildhoney is on a distinguished road
Default

Thanks for the tutorial! There is another way to get around this problem, and that is by normalising your database. That is, having a lookup table to store all the items. You list all your categories in one table (categories) and then you list all your items that require categories in another table (pictures), you then have a table in between those 2 called something like (pictures_categories) - your lookup table.

Allow me to demonstrate.

Code:
Table: categories

+-----+-------------+
| id  | name        |
+-----+-------------+
| 11  | psychology  |
| 12  | philosophy  |
| 13  | sociology   |
+-----+-------------+
Code:
Table: pictures

+-----+-------------+
| id  | name        |
+-----+-------------+
| 1   | image1      |
| 2   | image2      |
| 3   | image3      |
+-----+-------------+
Code:
Table: pictures_categories

+-------------+--------------+
| picture_id  | category_id  |
+-------------+--------------+
| 1           | 11           |
| 1           | 12           |
| 2           | 13           |
+-------------+--------------+
As you can see in our pictures_categories table, our image1 has 2 categories, and our image3 has 1 category, whereas our 3rd image has no categories. You would then perform a MySQL JOIN to get the categories that the images are associated with. Something like so:

Note: Not tested this query, but I'm 95% sure it'll be fine!

sql Code:
SELECT
    categories.name
FROM
    pictures
LEFT JOIN
    pictures_categories
ON
    pictures_categories.picture_id = pictures.id
LEFT JOIN
    categories
ON
    categories.id = pictures_categories.category_id
WHERE
    pictures.name = 'image1'

This would then return the names of all the categories that image1 has associated with it. It's a tough one to describe, but I hope you can at least extract some useful points! Also for any one interested, maybe Wikipedia'll provide more in-depth information.

But basically, our pictures_categories table contains 2 columns of IDs which reference each of the other 2 tables. You just match up the IDs and use the lookup table to store multiple categories.
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.

Last edited by Wildhoney : 12-07-2007 at 04:28 AM.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
The Following 5 Users Say Thank You to Wildhoney For This Useful Post:
codefreek (12-29-2007), Gurnk (12-04-2007), Haris (12-04-2007), Orc (12-07-2007), ReSpawN (12-11-2007)
Old 12-03-2007, 07:44 PM   #4 (permalink)
The Contributor
Upcoming Programmer 
 
Gurnk's Avatar
 
Join Date: Oct 2007
Location: US
Posts: 66
Thanks: 19
Gurnk is on a distinguished road
Default

Ah good idea Wildhoney. :) I guess in a way that would be a little more organized then the method I mentioned.

@ Haris - No problem!
Send a message via MSN to Gurnk
Gurnk is offline  
Reply With Quote
Old 12-03-2007, 08:23 PM   #5 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,280
Thanks: 90
Wildhoney is on a distinguished road
Default

All part of the learning process, squire! If you'd not have written the article you wouldn't have found the other way of going about it. Not today anyway. The good thing about my way is it's really fast to find the categories and even search within the categories.

Article much appreciated!
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
Old 12-04-2007, 05:41 AM   #6 (permalink)
The Frequenter
Prolific Welcomer Upcoming Programmer 
 
Join Date: Sep 2007
Posts: 360
Thanks: 24
Haris is on a distinguished road
Default

Quote:
Originally Posted by Wildhoney View Post
Thanks for the tutorial! There is another way to get around this problem, and that is by normalising your database. That is, having a lookup table to store all the items. You list all your categories in one table (categories) and then you all your items that require categories in another table (pictures), you the have a table in between those 2 called something like (pictures_categories).

Allow me to demonstrate.

Code:
Table: categories

+-----+-------------+
| id  | name        |
+-----+-------------+
| 11  | psychology  |
| 12  | philosophy  |
| 13  | sociology   |
+-----+-------------+
Code:
Table: pictures

+-----+-------------+
| id  | name        |
+-----+-------------+
| 1   | image1      |
| 2   | image2      |
| 3   | image3      |
+-----+-------------+
Code:
Table: pictures_categories

+-----------+--------------+
| image_id  | category_id  |
+-----------+--------------+
| 1         | 11           |
| 1         | 12           |
| 2         | 13           |
+-----------+--------------+
As you can see in our pictures_categories table, our image1 has 2 categories, and our image3 has 1 category, whereas our 3rd image has no categories. You would then perform a MySQL JOIN to get the categories that the images are associated with. Something like so:

Note: Not tested this query, but I'm 95% sure it'll be fine!

sql Code:
SELECT
    categories.name
FROM
    pictures
LEFT JOIN
    pictures_categories
ON
    pictures_categories.picture_id = pictures.id
LEFT JOIN
    categories
ON
    categories.id = pictures_categories.category_id
WHERE
    pictures.name = 'image1'

This would then return the names of all the categories that image1 has associated with it. It's a tough one to describe, but I hope you can at least extract some useful points! Also for any one interested, maybe Wikipedia'll provide more in-depth information.

But basically, our pictures_categories table contains 2 columns of IDs which reference each of the other 2 tables. You just match up the IDs and use the lookup table to store multiple categories.
Lol, it was that easy.

In my last script, I had like 3 queries to do simple tasks like these.
Haris is offline  
Reply With Quote
Old 12-04-2007, 11:55 AM   #7 (permalink)
The Contributor
Upcoming Programmer 
 
Gurnk's Avatar
 
Join Date: Oct 2007
Location: US
Posts: 66
Thanks: 19
Gurnk is on a distinguished road
Default

So Wildhoney, on yours, each time you add something to the pictures database, you get just the id, and then put the id in the pictures_category table, with the id of category? Then when you want to query them.. How exactly are you matching them? Maybe I need to read up on table joining. :)

EDIT: Ahh yes.. I've just read a few short articles. Join and Left Join looks pretty interesting, I may have to start putting it to use. :)

Last edited by Gurnk : 12-04-2007 at 01:18 PM.
Send a message via MSN to Gurnk
Gurnk is offline  
Reply With Quote
Old 12-07-2007, 04:34 AM   #8 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,280
Thanks: 90
Wildhoney is on a distinguished road
Default

Sorry, completely missed your last question, Gurnk! Basically it's all down to the JOINs:
  1. Join picture.id to picture_categories.id based on WHERE clause (one to many);
  2. Join picture_categories.category_id to categories.id (many to many);

Key:
Blue = Table
Green = Column

So for every ID that matches to the picture's image in our lookup table, get all the IDs that match up to a categories in the categories table.
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
The Following User Says Thank You to Wildhoney For This Useful Post:
codefreek (12-29-2007)
Old 12-07-2007, 08:54 AM   #9 (permalink)
Jay
The Contributor
Good Samaritan 
 
Join Date: Dec 2007
Posts: 60
Thanks: 5
Jay is on a distinguished road
Default

Hum, sorry to be a burden.. but you should probably test queries before you suspect that they work, it could save time in the future

[/TIP]

Otherwise, great article for the beginners!
Jay is offline  
Reply With Quote
The Following User Says Thank You to Jay For This Useful Post:
Haris (12-07-2007)
Old 12-07-2007, 01:36 PM   #10 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,280
Thanks: 90
Wildhoney is on a distinguished road
Default

Quote:
Originally Posted by Jay View Post
Hum, sorry to be a burden.. but you should probably test queries before you suspect that they work, it could save time in the future

[/TIP]

Otherwise, great article for the beginners!
Was that aimed at me? Either way, yes I should. I was fairly confident though that it would work, but even still, you have a fair point!
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
Old 12-07-2007, 08:07 PM   #11 (permalink)
The Contributor
Upcoming Programmer 
 
Gurnk's Avatar
 
Join Date: Oct 2007
Location: US
Posts: 66
Thanks: 19
Gurnk is on a distinguished road
Default

Quote:
Originally Posted by Wildhoney View Post
Sorry, completely missed your last question, Gurnk! Basically it's all down to the JOINs:
  1. Join picture.id to picture_categories.id based on WHERE clause (one to many);
  2. Join picture_categories.category_id to categories.id (many to many);
Key:
Blue = Table
Green = Column

So for every ID that matches to the picture's image in our lookup table, get all the IDs that match up to a categories in the categories table.
Ah nice one! I didn't know you could do stuff like table.column. Thanks for the tips.
Send a message via MSN to Gurnk
Gurnk is offline  
Reply With Quote
Old 12-09-2007, 07:07 PM   #12 (permalink)
The Frequenter
Prolific Welcomer Upcoming Programmer 
 
Join Date: Sep 2007
Posts: 360
Thanks: 24
Haris is on a distinguished road
Default

Quote:
Originally Posted by Wildhoney View Post
Thanks for the tutorial! There is another way to get around this problem, and that is by normalising your database. That is, having a lookup table to store all the items. You list all your categories in one table (categories) and then you list all your items that require categories in another table (pictures), you then have a table in between those 2 called something like (pictures_categories) - your lookup table.

Allow me to demonstrate.

Code:
Table: categories

+-----+-------------+
| id  | name        |
+-----+-------------+
| 11  | psychology  |
| 12  | philosophy  |
| 13  | sociology   |
+-----+-------------+
Code:
Table: pictures

+-----+-------------+
| id  | name        |
+-----+-------------+
| 1   | image1      |
| 2   | image2      |
| 3   | image3      |
+-----+-------------+
Code:
Table: pictures_categories

+-------------+--------------+
| picture_id  | category_id  |
+-------------+--------------+
| 1           | 11           |
| 1           | 12           |
| 2           | 13           |
+-------------+--------------+
As you can see in our pictures_categories table, our image1 has 2 categories, and our image3 has 1 category, whereas our 3rd image has no categories. You would then perform a MySQL JOIN to get the categories that the images are associated with. Something like so:

Note: Not tested this query, but I'm 95% sure it'll be fine!

sql Code:
SELECT
    categories.name
FROM
    pictures
LEFT JOIN
    pictures_categories
ON
    pictures_categories.picture_id = pictures.id
LEFT JOIN
    categories
ON
    categories.id = pictures_categories.category_id
WHERE
    pictures.name = 'image1'

This would then return the names of all the categories that image1 has associated with it. It's a tough one to describe, but I hope you can at least extract some useful points! Also for any one interested, maybe Wikipedia'll provide more in-depth information.

But basically, our pictures_categories table contains 2 columns of IDs which reference each of the other 2 tables. You just match up the IDs and use the lookup table to store multiple categories.
Can you use the same structure for categories and sub-categories? I am confused. :(
Haris is offline  
Reply With Quote
Old 12-09-2007, 08:10 PM   #13 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,280
Thanks: 90
Wildhoney is on a distinguished road
Default

How do you mean, Haris? That structure can be used for anything although usually it's where you have a one-to-many relationship, you introduce the lookup table to normalise the database to allow for two one-to-one many relationships across 3 tables.
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
The Following User Says Thank You to Wildhoney For This Useful Post:
Haris (12-10-2007)
Old 12-10-2007, 04:47 AM   #14 (permalink)
The Wanderer
 
Rizza's Avatar
 
Join Date: Dec 2007
Location: Orlando, FL
Posts: 23
Thanks: 0
Rizza is on a distinguished road
Default

Code:
category
  id
  parent_id
  name
Is a pretty easy way to get category/sub-categories. Just use parent_id default of 0 for root-level categories. You can recurse through it as well if subcategories have their own children, etc as well.
Rizza is offline  
Reply With Quote
The Following User Says Thank You to Rizza For This Useful Post:
Haris (12-10-2007)
Old 12-10-2007, 05:24 AM   #15 (permalink)
The Frequenter
Prolific Welcomer Upcoming Programmer 
 
Join Date: Sep 2007
Posts: 360
Thanks: 24
Haris is on a distinguished road
Default

I've got it now.
Haris is offline  
Reply With Quote
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT. The time now is 07:50 AM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0
Inactive Reminders By Icora Web Design