I'm self-taught programmer/web-guy. And I am completely new to MYSQL. This is not a question asking how-to because I can make it do what I want. Rather I am asking for advice/critiques on how to do it better with regards to the DB design and queries I used.
A little background about me
I am not a professional programmer. Programming has always been more of a hobby interest for me. My job is designing custom jewelry using a CAD program and then have my models milled out via a CNC made especially for carving jewelry models out of wax (and a few days ago we got a 3D printer that prints in wax suitable for jewelry casting...yay!).
Why I'm doing this mysql/php project
For about a year, I've used a physical bulletin board by my workstation to track my 20 to 30 some odd design projects I always seem to have in queue. I have been wanting to make a website whereby I could enter some details about the job ticket and track it that way. This has various benefits, not the least of which is getting rid of the physical board which I always seem to be knocking the tickets off of. But mainly, the boss can view ticket statuses from anywhere in the world. A few months ago I finally got it roughed-in and it is even usable now, but I wanted to add a few more things to the project (namely, notes and special instructions).
So, I've got a main table that's approximately like...
ticket_id | lname | fname | job_desc | state_id |
----------|-------|-------|----------|-----------|
1 | Smith | Bob | dia ring | 1 |
----------|-------|-------|----------|-----------|
2 | Parker| Gil | pendant | 3 |
----------|-------|-------|----------|-----------|
There's other columns in the tickets table, but gives the general idea. The state_id refers to another table of states (statuses), which looks like so...
state_id | state_desc |
---------|----------------|
1 | Not Started |
---------|----------------|
2 | Being Designed |
---------|----------------|
3 | Rendered |
There's more states a ticket can have, but that gives the idea. The state ids end up being column heads which I use on the physical bulletin board.
I would like to have special instructions and notes for each ticket. This was something that has been awkward, though not impossible, on the physical board. It will be much nicer on the website version.
My first thought was to add another column to the tickets table like so....
ticket_id | lname | fname | job_desc | state_id | sp_instr | notes |
----------|-------|-------|----------|----------|----------|-------|
1 | Smith | Bob | dia ring | 1 | | |
----------|-------|-------|----------|----------|----------|-------|
For each ticket, there will be multiple instructions/notes and I want them to end up as unordered lists in the web page. So I would have to do something like...
Finger Size: 6.5|||Use three largest diamonds only|||Use customer's gold
And then explode on the "|||" (or some other arbitrary character combination) to get the array to make the list from. Simple enough. It was my first direction. Not too bad for the instructions. Never gonna have more than 5 or 6 short sentences. But the notes (which could double as an activity log, too) could be more complex and numerous.
So then I considered making a separate table like so...
ticket_id | instr |
----------|----------------------------------|
12 | Finger Size: 6.5 |
----------|----------------------------------|
12 | Use three largest diamonds only |
----------|----------------------------------|
12 | Use customer's gold |
----------|----------------------------------|
18 | Put bird on pendant somehow |
----------|----------------------------------|
18 | Use cust's white gold in pendant |
----------|----------------------------------|
Below is the meat of the php code that uses the database (connection info is not shown and table names have been changed)....
$db = new mysqli("{connection info}");
// put column heads in an array
$result = $db->query("SELECT * FROM states_table");
$col_heads = array();
while($row = $result->fetch_assoc()){
$col_heads[] = $row;
}
// put ticket info in an array
$result = $db->query("SELECT * FROM main_table ORDER BY due_date");
$tickets = array();
while($row = $result->fetch_assoc()){
$tickets[]=$row;
}
// do a bunch of stuff here to make HTML for the columns & tickets
// collect special instructions
$result = $db->query("SELECT main_table.ticket_id, instructions.instr FROM main_table LEFT JOIN instructions ON main_table.ticket_id = instructions.ticket_id");
while($row = $result->fetch_object()) {
var_dump($row);
}
But it's that last query that is giving me a headache. For tickets that have no special instructions, I get...
object(stdClass)#4 (2) {
["ticket_id"]=>
string(1) "6"
["instr"]=>
NULL
}
But when they do, I get a separate object for each record in the special instructions table like this...
object(stdClass)#2 (2) {
["ticket_id"]=>
string(2) "39"
["instr"]=>
string(22) "Use dias marked in red"
}
object(stdClass)#4 (2) {
["ticket_id"]=>
string(2) "39"
["instr"]=>
string(32) "Cust likes side shank of RG ring"
}
object(stdClass)#2 (2) {
["ticket_id"]=>
string(2) "39"
["instr"]=>
string(73) "Cust likes top of WG ring as well as the top of the ring from our website"
}
I am definitely able to (and did) go through that mess with a while loop and collect the instructions for a single ticket id, pack them into an array and associate them with the id so I have key=>value pairs like so...
ticket_id => array of instructions
So I can strong-arm my way through it, but I feel like I am overlooking some power in the MYSQL query statements somehow. Are my database tables and queries laughable? Have I overlooked something common/useful/powerful? Or is that just how linking a single record from one table to another table with multiple records is?
Sorry for the rambling post.