Jump to content
Larry Ullman's Book Forums

Working Through What Is An Array And What Isn'T


Recommended Posts

I've read through the book, and now I'm working through it bit by bit; I am so hung up on this one subject that I need to ask for some clarification.

 

In script 2.7 I'm working through arrays, and how to indicate strings, etc. On p. 64 the box on the right says that multi-dimensional arrays can also come from an html form- and since this is what I want to figure out how to create, I thought I would try to write the correct syntax for this to understand it thoroughly.

 

Here's the code- a simple form that has check boxes and then sub check boxes; I realize this might be a bit more complex than the example but it indicates best what I want to try to work through.

 

<?php
$letts = array(
$_POST['letters'],
);

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
foreach($letts as $title => $list) {
echo "<h3>$title</h2><ul>\n";
foreach($title as $k => $v) {
echo "<li>$k - $v</li>\n";
}
}
echo '</ul>';
}
?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
body, ul, li { list-style-type: none; }
</style>
</head>

<body> 
<form action="page1.php" method="post">
<fieldset>
<legend>My Form</legend>
<fieldset>
<legend>Letters and Numbers: 1</legend>
<ul>
<li>
<input type="checkbox" name="letters[]" value="Alpha" /> Alpha
    <ul>
           <li><input type="checkbox" name="numbers[]" value="One" /> One</li>
           <li><input type="checkbox" name="numbers[]" value="Two" /> Two</li>
           <li><input type="checkbox" name="numbers[]" value="Three" /> Three</li>
           <li><input type="checkbox" name="numbers[]" value="Four" /> Four</li>
       </ul>
  </li>
</fieldset>
<fieldset>
<legend> Two:</legend>
<ul>
<li>
    <input type="checkbox" name="letters[]" value="Beta" /> Beta
<ul>
           <li><input type="checkbox" name="numbers[]" value="One" /> One</li>
           <li><input type="checkbox" name="numbers[]"  value="Two" /> Two</li>
           <li><input type="checkbox" name="numbers[]"  value="Three" /> Three</li>
           <li><input type="checkbox" name="numbers[]"  value="Four" /> Four</li>
</ul>
</li>
</ul>
</fieldset>
<fieldset>
<legend> Teh Three:</legend>
<ul>
        <li><input type="checkbox" name="letters[]" value="Charlie" /> Charlie
<ul>
                <li><input type="checkbox" name="numbers[]" value="One" /> One</li>
<li><input type="checkbox" name="numbers[]"  value="Two" /> Two</li>
<li><input type="checkbox" name="numbers[]"  value="Three" /> Three</li>
<li><input type="checkbox" name="numbers[]"  value="Four" /> Four</li>
</ul>
           </li>
</ul>
</fieldset>
<fieldset>
<legend> Four!</legend>
<ul>
        <li><input type="checkbox" name="letters[]"  value="Delta" /> Delta
<ul>
<li><input type="checkbox" name="numbers[]" value="One" /> One</li>
<li><input type="checkbox" name="numbers[]"  value="Two" /> Two</li>
<li><input type="checkbox" name="numbers[]"  value="Three" /> Three</li>
<li><input type="checkbox" name="numbers[]"  value="Four" /> Four</li>
</ul>
           </li>
</ul>
</fieldset>
<br />
<input type="submit" value="submit" name="Submit!!" />
</fieldset>

</form>
</body>
</html>

 

 

I should say, this is the latest version; previous versions (I've tried a lot of different things but realize that I'm just altering things without understanding what is really going wrong) have returned different errors such as illegal string offset. This one returns the warning that you gave a tip for on page 61- invalid argument foreach. So I'm trying to use a foreach loop on a variable that is not an array- but I suppose I don't understand why it is not an array- is it because the letters[] and numbers[] are not given a relation? should they all have the same name?

 

I thought it was because in some instances I checked only one option- so I tried going through each list and checking multiple in each one. Then I realized that this wouldn't work anyway, because I don't want to create any sort of form where multiple check box values are required instead of optional.

 

If you had any insight on this I would be grateful. Thanks!

Link to comment
Share on other sites

<?php
$letts = array(
$_POST['letters'],
);

 

Okay, you've got to start by getting rid of the use of array() there. $_POST['letters'] will automatically be an array. Wrapping it in array() when assigning to $letts just confuses things.

 

Next, your nested foreach loops probably aren't doing what you want them to. Start by just dumping out the value of $_POST['letters'] to see what data you're actually working with:

print_r($_POST['letters']);

 

As you'll see, the keys for the array (which you assign to $title in your foreach loop) is not an array.

 

Also keep in mind that you're creating two multidimensional arrays in your code: $_POST['letters'] and $_POST['numbers']. There is no relationship between them. How you define a relationship between them depends upon what you're trying to accomplish here (which isn't clear). It'd probably help if your example was either more practical or was explained in English so that I could get a sense of what you're trying to do.

 

Finally, notice that because of where you're using your PHP tags, the output will be written before the HTML head and body.

Link to comment
Share on other sites

Thank you for the quick response.

 

I would like to create the following:

 

1. The user can indicate none/some/all choices in a list (letters)- this is a list of all different items.

2. However, in each sub-list (which the checkboxes are set to states, and only show up if an initial indication is made), the list is the same repeating set of options, with multiple allowed.

 

It could be described as thus:

Field:

-Plumbing

-Construction

-Electric

-Water

 

What do you do within that field?

-Management

-Support (IT, Admin, etc)

-Laborer

-Engineering

 

 

For every item in list A, there will be the same set of sub items (List b ).

 

Then the results are some combination of the two, but able to be searched for separately.

 

(Edit to add):

Can one concatenate values? Or is that more difficult than it needs to be?

Link to comment
Share on other sites

I see. I would be inclined, then, to only create checkboxes for the subitems, but name them a common name to the parent items. For example, a[], b[], c[]. That way, you'd know what subitems were selected in which parent items.

 

You can concatenate values, although I don't know if that helps here.

Link to comment
Share on other sites

I ended up getting it to work- but I think what I seem to be fundamentally confused on is what an array is, and what a multidimensional array is vs a multivariable array. I will have to read up on this more, but I think for now I will continue to work through the book and take notes on what I understand or don't- past experience has shown that these things tend to become more clear as the knowledge base expands.

 

Thank you for the help!

Link to comment
Share on other sites

Not sure if this helps, but by default, all arrays have an index that starts at 0 and increments by 1 for each element in the array.

If you don't want to use that default structure though, you can create an associative array (which I think you're referring to as a multivariable array) in which the index is made up of strings instead of the usual 0, 1, 2, 3, etc.

Both standard arrays and associative (string-indexed) arrays are one dimensional by default.

 

A multidimensional array is an array of two or more dimensions, which can have regular numbered indexes, associative indexes or any combination thereof.

 

The following is an example of a standard array:

 

$arr1 = array('apple', 'banana', 'orange');

 

The index value of 'apple' is 0, 'banana' is 1 and 'orange' is 2.

 

A similar associative array could be created as follows:

 

$arr2 = array('fruit1' => 'apple', 'fruit2' => 'banana', 'fruit3' => 'orange');

 

In this case, if we write $arr2[0], we'll get an index error because there is no such index value. Instead, we need to write things like $arr2['fruit1'], etc.

 

Lastly, let's create a multidimensional array in which the indexes are all default, auto-incrementing numbered indexes:

 

$arr3 = array(array('apple', 'banana', 'orange'), array('strawberry', 'raspberry', 'blueberry'), array('star fruit', 'ugli fruit', 'plantain'));

 

All the various strings in the above array can be referenced as follows:

 

$arr3[0][0]: 'apple'
$arr3[0][1]: 'banana'
$arr3[0][2]: 'orange'

$arr3[1][0]: 'strawberry'
$arr3[1][1]: 'raspberry'
$arr3[1][2]: 'blueberry'

$arr3[2][0]: 'star fruit'
$arr3[2][1]: 'ugli fruit'
$arr3[2][2]: 'plantain'

 

I apologize if my examples are overly simplistic, but I couldn't think of a better way to explain things.

Does that clear up your confusion?

Link to comment
Share on other sites

Well...I think I have had a sort of lightbulb moment as far as articulating specifically what I want to know within the context of what I am trying to do.

 

In building any company/organization profile, I have the main profile, and that is an array (I believe!) of data: company ID, name, type, etc- one of which is an item (and this is getting into database design so I will keep that brief to try to stay on topic) that could be called "what they do".

 

- Within "what they do", there are two items: the field in which they work, and the services they provide within that field. So what_they_do = array (field_of_work, services_provided). (multi-variable?)

 

- Within each field_of_work however, they could have multiple fields/areas- Does this make field_of_work multidimensional?

 

If I do in fact then have a multi-variable array in which there are multi-dimensional arrays, how can I standardize that?

 

This is what I am working to understand and bring to reality.

 

Numerically referenced items is actually preferable to me, I think it makes things a lot simpler. However- I seem to be struggling with the difference between numerically indexed (as in, I say array = (apple, orange, banana) and the index values are 0, 1, 2 vs. having my database table arranged in such a way that the table ID column ends up being the content of the array.

 

Maybe this is where I am struggling more? Because I understand the definitions of the term array, multivariable array and multidimensional array, but then I seem to be lost in translating those terms when it comes to pulling information from my database to use in a dynamic context. I seem to be able to do it just fine when there is only ONE piece of data (or type of data) I need, but once the layers get complex I get tangled.

 

For example:

 

I have a company table, but then I have a "field of work" table and a "services provided" table in which each have three columns: ID, name, and description. Then I set up a joint table in which each company can be listed by ID (from the company table) along with field ID and services ID.

 

I did consider (and even tried) putting the two tables together into one table (field, services): but every possible combination made it really a huge table and that didn't seem like good design either- although perhaps that is the way it should be done and I just don't know enough to know that (hence me working through this book in the first place). Coming from a background of designing the actual layouts, when I write CSS code my goal is to give it the most flexibility with the fewest lines of code to achieve my desired results- and it seemed logical to me that the php/mysql side of things would be the same way, but perhaps it isn't, and maybe that is another source of confusion for me.

Link to comment
Share on other sites

The best way to grasp arrays, particularly multidimensional and associative arrays is to start coding with them. I find associative arrays are very useful when programming with a database. e.g. I select a record from a d/b table which has fields firstname, middlename, surname, address1, address2, city, county, and postcode and put them into an array called $row. I can access each field by calling $row['firstname'], $row['middlename'] etc. if I am working with lots of rows - I can use a loop and I know what each field is referring to. If it was an indexed array, I would have to remember that $row[0]=firstname, $row[1]=middlename etc.

 

You may want to get comfortable working with arrays (indexed and associative) first before moving onto multidimensional ones. Try some of the 'Pursue' questions at the end of the chapters for examples to test your understanding.

 

If your arrays are going to end up in a database you want to keep them as simple as possible. To optimise performance, each table should hold data specific to one entity. For your example you will want a company table - to hold data about a specific company e.g. name, address etc. Then you will want tables for services and fields of work. You may find that some of your tables have only 2 or 3 columns, that is fine. You will use foreign keys to relate the tables to each other where required, for example your company table will have an index to services and to fields of work. You may find it useful to read the chapter on database design.

 

With programming in general, you may end up including a lot of different files which initially seems counter productive but actually is not e.g. if you are continually using functions defined in those files, holding them in separate files and including the file once is a good way to streamline your code.

 

btw - I'm not sure what you mean by a multivariable array. One array can hold different data types - strings, numbers, and arrays (that would be a multidimensional array).

  • Upvote 1
Link to comment
Share on other sites

Ok as suggested, I did some testing.

 

In my database handler file I have the database connection function, as well as these three functions, since I wanted to test this out:

getAllRows : supposed to return an array of rows

getAllData: supposed to return an array of columns

getOneRow: supposed to return an assoc array of values

 

 

The code:

<?php
include_once('databasehandlerfile.php');
$conn = new DatabaseConn();
$result = $conn->getAllRows('SELECT * from field');
var_dump($result);
?>

 

 

Test 1 getAllRows

array(18) {

[0]=>

array(2) {

[0]=>

string(8) "field_id"

[1]=>

string(10) "field_name"

}

*results truncated for demonstrative purposes*

 

 

Test 2 (getAllData), returned this:

array(2) {

["field_id"]=>

array(17) {

[0]=>

string(1) "1"

*results truncated for demonstrative purposes*

}

["field_name"]=>

array(17) {

*results truncated for demonstrative purposes*

 

Test 3 (getOneRow), returned this:

array(2) {

["field_id"]=>

string(1) "1"

["field_name"]=>

string(11) "Engineering"

}

 

They seem to have done what I wanted them to do, however I am still working to display the exact result I want so I can understand how to get what I need in a dynamic context.

What I mean is that I can get results one column at a time and display them as (for example) select options. What I can't figure out is how to make rows from one column in one table sub options for each one of another table's rows from one column.

 

 

 

Thanks for the advice everyone, it's been helpful.

Link to comment
Share on other sites

What I mean is that I can get results one column at a time and display them as (for example) select options.

see this post

how to make rows from one column in one table sub options for each one of another table's rows from one column.
If you've set up the tables with indices to the other tables you can then use a join in your mysql query. But I wonder if you are trying to run before you can walk ( which I too often do!). If you read through each chapter in order and try out the examples you'll find alot of your questions answered.
  • Upvote 1
Link to comment
Share on other sites

see this post

If you've set up the tables with indices to the other tables you can then use a join in your mysql query. But I wonder if you are trying to run before you can walk ( which I too often do!). If you read through each chapter in order and try out the examples you'll find alot of your questions answered.

 

My initial response is- yes you're right! I struggle with the fact that I seem to be able to create websites that seem complex, and while I can grasp a lot of the concepts I've come across in the book so far, nesting multidimensional arrays eludes me and it is a little irritating.

 

The second part of your comment has made me think- I wonder if an idea that I previously had (but tossed) was the correct one- (sticking with the examples I've been using for continuity) the same two tables, but in the services table, a column that has a field_of_work_id column. It would make the table have more rows, since each service value would be directly linked to a field_of_work value, but this could be what I've been trying to figure out. Maybe to make them related, they have to actually be related, instead of being two separate tables with nothing to link them but the form feedback into the joint table.

 

^_^

Link to comment
Share on other sites

Good DB design would suggest that you go with your original idea, which is to create a table of company data, another table for the fields and then a third intermediary table to handle the mixing and mashing of the two.

Essentially, you have a many-to-many relation between the company data and the fields, so you need to pull that data out into a third table with foreign key constraints.

 

It does honestly make the SQL queries a bit more taxing, but only slightly, and it's the right way to do things. The benefit of doing things like that (aside from good (i.e., non-redundant) DB design) is that you won't have to worry about multidimensional arrays either, as each row of results will simply be a one-dimensional associative array of data.

 

Sorry if this post is a bit abstract, but I urge you to make separate tables for the fields and services and company data, and then make intermediary tables to handle the many-to-many relations between those three tables.

 

If you need specifics on how to do all that, please let us know. We'd be more than happy to help by providing code.

Thanks.

  • Upvote 1
Link to comment
Share on other sites

HarleySan- yes, I did just that. ^_^ I worked through all the normalization steps in the book and saw that the design I had was correct.

 

I'm happy to say tonight that I managed to dynamically return the results I was wanting! It's one long list BUT it's there! I found the key while reading chapter 9- ironically enough Larry had a tip on page 284 that had my name all over it. I realized after staring at the code sample in the book that I was trying to array my results when my function had already done that!

 

I didn't use the function as a function- instead I just pulled out the code from the function and put it right into my php code. tiny bit of tweaking but it worked!

I feel like I could fly right now - even though I know that there is more work ahead (next stage will be to get it to appear more manage-ably on the page and to have the code written more elegantly)

 

<?php
include_once('xxxhandlerxxx.php');
$conn = new DatabaseConn();
$query = "SELECT fsid, fname, sname FROM fieldserv ORDER BY fsid";
$result = mysql_query($query);

if($result){
echo '<table border="1" align="center" cellspacing="3" cellpadding="3" width="100">
<tr><th colspan="3"><h3>Fields and Services</h3></th></tr>
<tr>
<td></td>
<td align="left"><b>Fields of Work</b></td>
<td align="left"><b>Services Provided</b></td></tr>';

$numfields = mysql_num_fields($result);
$data = array();
$flist = array();
for($i=0;$i<$numfields;$i++)$flist[] = mysql_field_name($result,$i);
$data[0] = $flist;
while($row = mysql_fetch_assoc($result)){
$data[] = $row;
echo '<tr>
<td align="center"><input type="checkbox" value="'. $row['fsid'] .'" /></td>
<td align="left">' . $row['fname'] . '</td>
<td align="left">' . $row['sname'] . '</td>
</tr>
';
}

echo '</table>';
}
?>

 

I know there's still a long way to go(nesting!!) - but I cannot begin to describe the sense of relief I felt when the results posted to the screen. TY all for the help and advice!! (and Larry for the great book!)

  • Upvote 2
Link to comment
Share on other sites

 Share

×
×
  • Create New...