Free Republic
Browse · Search
Bloggers & Personal
Topics · Post Article

Skip to comments.

Xampp: Programming for the masses, C, MySQL & HTML together!
self | 2012/02/14 | Mycroft Homes

Posted on 02/14/2012 12:38:26 PM PST by Mycroft Holmes

Or, learn to code the next Facebook™ in your spare time.

Really for true about the Facebook™ part. It was initially written using this technology so that should give you some idea what is possible if you master this idiom. Admittedly, it doesn't scale to 800 million users, but it is pretty serviceable for most people and it's free.

Learning to program earns you power. Steadily all of the machines around us are morphing into computers surrounded by hardware that mediates the processor's interaction with the physical world. To change the behavior of any given machine all you need to do is change the software driving it. A remarkable number of machines are being built these days that explicitly include a function allowing a knowledgeable user to reprogram the device in total. Most of the routers for sale on the market today include this capability. See www.dd-wrt.com for complete details.

But you don't need to master the intricacies of hardware to write the next Facebook™. After all, you are just shuffling bits around on existing hardware that you need to know really nothing about other than it can store and manipulate data in predictable ways. Pretty cool.

What follows is a tutorial on Xampp, a package that installs everything you need to build complex database driven websites. It is targeted at a person competent in this forum. By competent I mean able to use fonts, images and hot links. People who are not able to do those things may learn them by mashing either my username or here for a tutorial on just those very things.

The first line of links at the top of the page is the FreeRepublic tutorial. The second line of links takes you to the Xampp tutorial, the one we will be doing here. The first one will be the installation of Xampp on your machine and serving up the world's simplest web page to your browser by a server on your machine. The tutorial is being copied to my FreeRepublic home page as it is being developed so if you want to read ahead it is available but it is a work in progress. The program that the tutorial will generate a skeleton of is complete and working very nicely, thank you. My task is leading you though the maze that is how one designs and implements such a thing to begin with.

What you make is up to you. Creation, especially under the current regime, is a revolutionary act. So get those Dewskies in the fridge and the coffee on the burner and let's code!

Xampp installation tutorial follows:


TOPICS: Computers/Internet; Education; Weird Stuff
KEYWORDS: apache; html; php; programming; xampp
Navigation: use the links below to view more comments.
first 1-5051-56 next last

Xampp:

This is the beginning of a tutorial describing how to install software that will run a web server and a database on your personal machine. This will enable you to write and read web pages locally, without having to upload them to a server and these web pages will be able to read and write data to the database. You will also be able to program in C in a fairly convenient fashion, just by including it in the source.php file of the web page. The combination of persistent storage, programming in C and HTML & JavaScript as the user interface provides a convenient and free development platform for solving a rather wide range of problems.

The tutorial will proceed in a step by step fashion, using all of the elements described above. All of the actual code will be provided and each new piece will be explained along the way. It isn't my intent to provide and exhaustive reference to C, HTML, JavaScript or MySQL. Instead you will be pointed to those references when appropriate. I will try to explain each new thing as it occurs but if I miss one, feel free to rattle my cage.

Xampp is an acronym for X-platform, Apache, MySQL, PHP Preprocessor. You Windows people, don't run off; his works for you too. Xampp runs on Windows, Mac OS X, Linux and Solaris, sort of your full service package. It's a collection of programs that let you set up a database and a web server on your computer that lets you do interesting and useful things with data driven webpages for free! Additionally, setting up an Apache server on your personal machine allows you to sharpen your HTML skills without a whole lot of unnecessary uploading to a server flap-doodle.

Why do this? Well, you can leverage your knowledge of HTML to configure a user interface which talks to a database which stores arbitrary information. Using PHP (which is a C preprocessor) you can do programming sorts of things inside webpages. For everyday manipulation and storage of data this works wonderfully. If it is your intention to do heavy math, say ray-tracing for optical design, well, there are probably better choices for programming that application. But for most purposes this technique is quite sufficient. If you are collecting a bunch of data and then pawing through it in a variety of ways and want to be able to do this from a variety of platforms in geographically disparate locations, well this is for you.

One of the beauty parts of programming this way is that the results are platform independent. You write the program once and it works anywhere that a web browser runs with any web browser. Given HTML 5 and Flash it is easy to incorporate video into your program as well, though for the life of me I haven't actually needed to do video yet. It's also a pretty neat way to learn C and Javascript which I will get into later.

The database we are using is MySQL. This is accessed by a preprocessor to the C programming language called PHP. PHP lets us embed C programs into web pages that run on the server side (which the user never sees) as opposed to scripts (like JavaScript) which runs on the user side and can be freely examined by the user. This is used to write web pages which are served up by a program called Apache2 which is a wildly popular web server. This collection of stuff is called Xampp. To get all of this juicy goodness go here:

http://www.apachefriends.org/en/xampp.html and select the correct installation for your operating system and follow the easy directions. If you are doing a windows installation select the installer option as opposed to the 7zip or winzip options. This allows you to do an uninstall. Accept the defaults and do not add MySQL and Apache as Services. This means that they will not start without you telling them to. This is something you might want to do later but for now let's start and stop these programs explicitly.

Under Windows, Xampp installs in its own directory at the root, c:\xampp. If you change this during the install to say, the more normal c:\Program Files\ things will work with XP but will break under Vista. I haven't checked with Windows 7. Don't do this, accept the defaults. You do need to determine and remember the document root directory for your installation. This is where you need to put the .html and .php files for the web server to find them. For all flavors of windows look for c:\xampp\htdocs, Linux users will find the document root at /var/www, Mac OS X and Solaris users should probably also find the root at /var/www but I don't know for sure.

Important Security Considerations:
Don't turn on your Apache server unless you are behind a hardware firewall. You should already be behind a hardware firewall. If you have a router between your computer and your ISP you probably already have a hardware firewall. Check, be sure. If you don't, Walmart had a sale last week on Cisco M-10 routers for $25 and you need one right now. I'm serious about this. If you turn on an unprotected server outside a firewall it will be infested by the Chinese within 24 hours. Most likely it will be infested in 2 hours but if I claimed that you probably wouldn't take me seriously; but there are people with Asian IP addresses trolling all the time. You need to block port 80 incoming, most routers do this by default. Port 80 is what your Apache server listens to on your installation. You don't want people outside your local net getting to your server, honest. These are shark infested waters, mate'e...better gear up.

After successfully installing Xampp you will be asked if you want to start the Xampp control panel. Answer yes and start the Apache and MySQL services on the control panel. This will take a few seconds to start. Then open Chrome or some other web browser and in the address bar type localhost and hit 'Enter' to navigate to the Xampp splash page. Select your language and you should see a page congratulating you on a successful install. In the navigation bar on the left towards the bottom you will see under Tools and selection for 'phpMyAdmin'. Remember that if Apache and PHP are not running none of the following works.

At this point you should have successfully installed a web server and a database on your local machine. This is kind of neat but you need some content, some web pages to look at for this to be interesting. This next bit describes the creation of a program that keeps a list of purchased items in a database and can more or less organize food and other consumables for a household. All of the elements described at the beginning of this section will be exercised and a vaguely useful program will emerge.

Now start phpMyAdmin to add a new user to the MySQL database access list. The User-Name needs to be 'admin' and the Password needs to be 'password'. These are both obvious values that really should be something else for security reasons. It is up to you to make that so if you desire. The only other place those values appear is in the 'include/connect.php' file and they may be freely edited to something more security conscious, but don't do that now. They need to be simple right now for the tutorial to work. Look along the top of the page for the tab 'Privileges' and select it. Then select 'Add New User' and a create a user 'admin' with a password 'password'. Both are all lower case and it does matter. The host setting is 'local' and check all of the global privileges and leave the resource allocations alone and 'Create User'.

<html>
  <head>
    <title>
	Minimal
    </title>
  </head>
  <body>
	Hello World...
  </body>
</html>
Locate your document root and copy the above code into a file there called "index.html" Under Linux the document root is /var/www and under Windows it's c:\xampp\htdocs. For historic and server population reasons we will refer to that directory in general, no matter what its actual name, as ~www. The ~ part indicates whatever path you have to take to get to your document root, the www is the actual directory name if your are using a sensible OS, otherwise substitute htdocs. It's a choice.

Type "localhost" (← exactly that, not your machine's name, no quotes) into the address bar of your browser and hit CR. You should now be looking at "Hello World..." Feel free to edit the <body> part to your heart's content. It's a way to prove to yourself that you actually are in control. Have fun.

Editing .html and .php files in Windows is best done with Programmer's Notepad. The reason is that PN knows about the syntax of .php (and many other languages) and will clue you up with colors when you have made errors in the placement of that single quote in a sea of text. For this sort of thing it's the bee's knees and you can find it at: Programmer's Notepad. Under Linux I am using Geany which offers a similar feature set to PN.

When you configured the MySQL db you created a user 'admin' with a password 'password' to allow the program to access the database. These names and passwords are rather obvious and will be easily guessed by any bored teenager. You can change this username and password by editing the file /include/connect.php and the appropriate user in phpMyAdmin to the values you desire. Don't do this now, they need to be exactly the current values for the tutorial to work. You will understand more concerning this later but you really need to remember about the bored teenager part, oh, and the Chinese.

1 posted on 02/14/2012 12:38:32 PM PST by Mycroft Holmes
[ Post Reply | Private Reply | View Replies]

To: Mycroft Holmes

I’m intrigued. Bookmark for later reading.


2 posted on 02/14/2012 12:55:41 PM PST by RobertClark ("Governments are instituted among Men, deriving their just powers from the consent of the governed")
[ Post Reply | Private Reply | To 1 | View Replies]

To: RobertClark

likewise.


3 posted on 02/14/2012 1:01:54 PM PST by cuban leaf (Were doomed! Details at eleven.)
[ Post Reply | Private Reply | To 2 | View Replies]

To: Mycroft Holmes

Interesting post. Xampp is the standard way Drupal programmers set up an offline development environment. Done it myself . Highly recommended.


4 posted on 02/14/2012 1:12:40 PM PST by InterceptPoint (TIN)
[ Post Reply | Private Reply | To 1 | View Replies]

To: Mycroft Holmes

Interesting post. Xampp is the standard way Drupal programmers set up an offline development environment. Done it myself . Highly recommended.


5 posted on 02/14/2012 1:12:46 PM PST by InterceptPoint (TIN)
[ Post Reply | Private Reply | To 1 | View Replies]

To: Mycroft Holmes

I use Mamp for my osx’s php/mysql development.


6 posted on 02/14/2012 1:26:57 PM PST by smith288 (Peace at all costs gives you tyranny free of charge)
[ Post Reply | Private Reply | To 1 | View Replies]

To: 21stCenturion

...


7 posted on 02/14/2012 1:59:44 PM PST by 21stCenturion ("It's the Judges, Stupid !")
[ Post Reply | Private Reply | To 1 | View Replies]

To: InterceptPoint
Xampp makes things very easy. I have two Linux servers already setup at home. When I moved to do my development work from my home office I installed MySQL, OpenSSL,PHP and phpMyAdmin on one of the systems.

For those who don't have Webmin on their Linux servers, I suggest adding it. It is a wonderful tool.

webmin site

8 posted on 02/14/2012 4:43:46 PM PST by sand88 (Nothing on this Earth would get me to vote for Mitt.)
[ Post Reply | Private Reply | To 5 | View Replies]

To: Mycroft Holmes
HTML Heavy:

This is a more rigorous HTML section describing what you need to know to do stand alone web pages outside the Free Republic environment, perhaps on a server on your own machine using Xampp. HTML is an extension of XML (eXtensible Markup Language) which has been extended (hey!) to be especially useful in describing the appearance of pages. XML is designed to be both human and machine readable. All of the characters in an XML file are either markup or content. Markup begins and ends with angle brackets <markup>. Everything else is content. Some characters are special and sometimes need to be represented in a form that XML won't recognize (like <). There is a way to create these characters by representing them with with a code that begins with an ampersand and ends with a semicolon &char_desc;. The char_desc part is either numeric or a short alphabetic descriptor, like &amp; for & or &lt; and &gt; for < and >. Mash here for a more complete treatment.

A tag is markup which begins with < and ends with >. There must be no space between the < and the text which defines the type of tag, if there is XML treats the whole mess as text. Most tags are part of tag pairs which are individually referred to as start tags <tag> and end tags </tag>. There are also empty element tags like break <br /> which is its own start and end tag. Note that the forward slash / appears as the first character of the text part of the end tag and also as the last character of the empty element tag.

An element begins with a start tag and ends with an end tag. There may be content or other elements between the start and end tags. An element may also be an empty element tag, (honestly, I don't make this stuff up). Elements provide programs with well defined chunks of data that describe what they are about. As a bonus it is all human readable.

Web pages always begin and end with an <html> tag. Let's cut straight to the chase and show all the normal elements of an HTML page.

<html>
  <head>
    <title>
	Page title goes here...
    </title>
    <style>
	CSS Style, if you've got it...
    </style>
    <script>
	JavaScript here...
    </script>
  </head>
  <body>
	Hello New World...
  </body>
</html>

Make a subdirectory under your document root called "tutorial". If you cut and paste the code above into a file called "~www/tutorial/index.php" in the root directory of the Apache server created in the xampp section and point your browser at "http://localhost/tutorial/index.php" you should see "Hello New World..."

The exact location of root directory of the Apache server depends on the operating system that Xampp is installed on. We are using a subdirectory "tutorial" to keep all the files in one obvious place. The file name "index" is special to HTML. If we pointed our browser to "http://localhost/tutorial/" the server would look for the file "index.html" or "index.php" in the directory "~www/tutorial" if we didn't explicitly specify a file. We are using "index.php" which tells the server that the file should be run through the PHP preprocessor before being served up to the browser.

The only required bits are the opening and closing html tags <html></html> That is what makes an HTML page, a bit boring though. There are two main subdivisions of the page, the <head></head> and the <body></body>.

The <head> contains three elements, <title> <style> and <script>. None of the elements of the <head> appear on the web page proper, but you can see them by doing View Source with your browser. The Title is what appears in the tab at the top of the browser. The Style element contains CSS (Cascading Style Sheets) descriptions of the styles of various parts of the document. It is strongly recommended to learn and use CSS instead of the deprecated <font>. More about this later. The third section contains the Scripts. These are little bits of program that travel with the web page and do computation and interaction with the user in his browser. Scripts are powerful and interesting.

The <body> contains the web page content. This content can be as simple as text and images or it can be dynamically created by driving it with a database and a bit of clever programming.

Forms:

You can't use forms on the forum for obvious reasons.

Most useful web pages collect data from the user and transform it in some interesting way. Forms are the method used to collect data from the user. Like everything else, a form is an element that looks like <form action="mumble.html" method="post"> some stuff in the middle </form>. That's all there is to it, just kidding. You can read more about forms here.

The action="mumble.html" part specifies what page will be presented back to the user when the data is entered and the Submit button is pressed. The data is entered into named Inputs on the current page and is shuttled back to the server for use in creating the action="mumble.html" page.

The method="post" bit describes how the information is passed back to the server when the submit button is pressed. If the method is "get" the information appears appended to the URL and is visible to the user. The preferred method is "post" because more information can be passed and it doesn't appear appended to the URL.

Because we are using PHP to construct our web pages, we can use a much more elegant construct for our forms that looks exactly like this:
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>"> This is much the same as the form above, except for the action part. This bit is a PHP script which runs on the server and very slickly sorts out all of the Inputs from the previous page. This allows you to write an interactive web page that looks like many pages but is really all the same page being called with different inputs. All of the following presumes this style of programming.

Replace the body part of "index.php" with the following:

  <body>
	<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
	Hello World...
	<form>
  </body>
Now refresh the page and you should see no change, but you have added a form.

Inputs:

You can't use inputs on the forum for obvious reasons.

Inputs look like <input type="text" name="favorite_flavor" /> This is a type "text" which has a default size of 20 characters. Available types are text, button, checkbox, file, hidden, image, password, radio, reset and submit. The name="favorite_flavor" provides a "handle" or name for that particular input. Copy the text below and use it to replace the body of "index.php".

  <body>
	<form method="post" action="/tutorial/index.php">
	Hello World...<br />
	Fave Flav:<input type="text" name="favorite_flavor" /> 
	<select onchange='updateMenu();' name='command'>
		<option value='Global Commands'>Global Commands</option>
		<option value='Add To List'>Add To List</option>
		<option value='Delete From List'>Delete From List</option>
	</select>
	<br />
	<input type="submit" name="submit" /> 
	<form>
  </body>

Save the file and mash reload on your browser and you should see:

If you see anything like the above you have a working form. There will be slight differences in size and fonts depending on what the defaults of your particular browser are, but it should look pretty much the same. Now, we are going to do a bit of debugging. What follows is probably my favorite PHP fragment.

<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}
?>
This is an embedded PHP Script. The first line is the opening token of the script, this alerts the PHP preprocessor that what follows until the closing bit (last line) is a PHP Script that should be processed. What it does is picks apart and prints out the names of all of the inputs passed back to the server along with their values. How it does this in detail is contained in the PHP Section but just accept it as a little bit of magic for the moment. Copy the above fragment and insert it in the file "index.php" immediately after the opening <form> tag.

Once you have done that you can mash the submit button on the page and whatever values you have in the inputs will be listed in text with the names of the inputs themselves. This saves a whole lot of heartache debugging web pages. You should see roughly the following above the select and text entry areas:

favorite_flavor=chocolate
command=Add To List
submit=Submit
Hello World...

You did type "chocolate" didn't you? To get to the interesting stuff we are going to have to understand more about PHP.

9 posted on 02/14/2012 5:36:21 PM PST by Mycroft Holmes (Mash name for HTML primer)
[ Post Reply | Private Reply | To 1 | View Replies]

To: Mycroft Holmes

PHP:

Functions Variables Strings Concatenation If

You can't use PHP on the forum for obvious reasons.

PHP is a Scripting Language like JavaScript. Unlike JavaScript, which runs in the user's browser to mediate user interactions, PHP runs on the server in a fashion which is invisible to the user. It the user invokes View Source he won't see any of the PHP on the page. PHP is used to run C programs as part of the HTML pages on the server before the raw HTML is generated and presented to the user.

All scripts in HTML begin with <? Have script stuff here, and end with ?>. The default script type is JavaScript. To get the PHP interpreter you need to start the script with <?php You can find the PHP manual here. What you will find if you poke the link is a pretty good manual describing how the PHP preprocessor works and quite a bit of material about the language C. You need to know this, leave this tab open if you are not fluent in C.

C is fundamental. You can not go wrong learning C, it's everywhere you want to be. C in PHP is a little different than standard C, it is not really typed. This means that variables, which all start with $, can have any sort of value stuffed into them. If you try to multiply a character by an array this implementation will let you and not warn you. It's part of its charm. Let's talk about that magical little PHP fragment we are using for debugging:

<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}
?>
If your eyes glaze over as you read this next passage just skip it. I promised to do this bit earlier and understanding exactly how this works is not at all necessary to continue but it is a nice spot to stop and talk about the syntax of C as practiced by PHP.

The first line opens the PHP script. The second line assigns the value of "true" to the variable $debug. The assignment operator is an equals sign = . Note that the line, and what we call the expression ends with the semicolon → ; ←. Expressions are bits of C that have meaning and are almost always terminated with a semicolon. Expressions may continue across lines that don't end with a semicolon.

The third line is an if statement, if $debug is true (and it is, we set it the line before) then we do all of the stuff inside the first pair of curly braces {...do all this stuff...}. This is the entire rest of the line as the curly braces nest so you do the stuff out to the matching brace at the end of the line. The curly braces serve to group the entire rest of the line as the required "do if true" part of the if statement. There is an optional "else, do if false" part but that isn't present here. A parenthetical note here, if you are using Programmer's Notepad you'll see that PN will show you the matching brace to one you select. This is really sweet and you need this, get it now.

The first expression in the "do if true" part is $ta = array_keys($_POST); $ta is a variable we pulled out of thin air. I call it 'ta' as a really short form of TemporaryArray. I don't call it TemporaryArray because I want the entire expression to fit on one line. array_keys($_POST); is what we are assigning to $ta. array_keys is a built in PHP function that returns an array of keys from the key=>value pairs which comprise an array.

Arrays are a bit different in PHP; the index of the array is not constrained to be numeric, it can also be a string. This is very different from C and has profound and useful implications. $_POST is an array constructed from the HTML post data where the keys (indexes of the array) are the names of the inputs in the form being submitted and the values of the array are the values of those inputs. And yes, you can have arrays of arrays. PHP is nothing if not flexible.

So after the first expression is evaluated we have an array of keys in $ta. The second expression:
for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}
is a for loop. This is a loop that iterates through a sequence of instructions a number of times and then quits. The basic logic goes: 1. set x to some number; 2. if x < some other number don't quit ; 3. do some thing; 4. increment x; 5. Go to 2 until quit. The actual formal expression is a bit more compact.

for($ti=0;$ti<count($ta);$ti++) is the control structure for the loop. The first expression inside the parenthesis assigns $ti (temporary index) the value 0. The second expression checks to see if $ti is less than count($ta). count is another built in PHP function that returns the number of keys in an array. If $ti is less than count($ta) then the statement(s) in the curly braces { } right after the closing parenthesis of the control structure are executed:
{echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}
echo emits a string as raw HTML to the page. What we are echoing is the concatenation of four strings. The concatenation operator is the period (.), really. The first string $ta[$ti] is fetched from the array of keys we put in $ta. The keys for the array $ta itself are numeric, as this is the default for the function array_keys. Other options are possible, we'll see those later. As the loop increments the string in $ta[$ti] will be the name of each input in the previous form's post and that will be printed to the screen. The next string to be printed is an equals sign "=". Next is the string in the array $_POST[$ta[$ti]]. $_POST contains the key=>value pairs that are the previous form's inputs, $ta[$ti] contains the string that is the key for $_POST so that whole bit resolves to the value in $_POST pointed to by a particular named input. This cycles through all of the variables passed in the post. Hope that made sense.

The previous web page rewritten in PHP idiom looks like:

  <body>
	<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}

	echo "Hello World...<br />";
	echo "Fave Flav:<input type='text' name='favorite_flavor' /> ";
	echo "<select onchange='updateMenu();' name='command'>";
		echo "<option value='Global Commands'>Global Commands</option>";
		echo "<option value='Add To List'>Add To List</option>";
		echo "<option value='Delete From List'>Delete From List</option>";
	echo "</select>";
	echo "<br />";
	echo "<input type='submit' name='submit' /> ";
?>
	<form>
  </body>
This is pretty boring, all we have done is put the PHP command echo in front of each line of HTML, quoted the HTML using double quotes, and replaced the double quotes " in the HTML with single quotes '. The last bit is important, HTML doesn't care about the difference between double and single quotes, PHP does. If you write all your HTML using single quotes you may then grab it right up and echo it without editing. Also, we added a semicolon ; to the end of each line of PHP, that's what indicates the end of the line.

One of the many things that PHP lets us do is sort of hide, or cram down information. The select in the previous example takes a lot of lines to make but is conceptually simple. Using PHP we can make the creation of that select appear as a single line by putting most of the work in another file. Copy the following text into a subdirectory you name "include", name the file "tutorial_functions.php".

<?php
/*		file: include/tutorial_functions.php
*		2012/029/13 - working initial cut
*		
*		Functions for tutorial
*/
function select_command($_POST, $base_name) {
	echo "<select onchange='updateMenu();' name='".$base_name."'>";	
	if ($base_name == 'command') {
		echo "<option value='Global Commands'>Global Commands</option>";
		echo "<option value='Add To List'>Add To List</option>";
		echo "<option value='Delete From List'>Delete From List</option>";
	} else {
		echo "<option value='Local Commands'>Local Commands</option>";
		echo "<option value='Chocolate'>Chocolate</option>";
		echo "<option value='Vanilla'>Vanilla</option>";
	}
	echo "</select><br />";
}
?>
to PHP
This is a function that makes a Select Object. A function is not an in-line replacement, rather it is a template for an instance of, in this case, a select object. The function's name is select_command. Information is passed into the function by the variables inside the parenthesis after the function name. All variables in PHP begin with $, that's how you know they are variables. Variables that are used by PHP and the System begin with $_, don't begin your variable names with underscore. In this case, we are passing in all of the inputs from the previous page in $_POST and a name for the particular select we are making when we call this function in $base_name.

The second line of the function begins with echo to emit raw HTML to make the select. The onchange='updateMenu();' bit is a directive to the select to call the script updateMenu(); when the value of the select changes. There is no script available to run, yet, so this is ignored. We'll be using this later. To understand the next new bit .$base_name. we'll need to talk a bit about strings.

Strings in PHP are collections of characters surrounded by double quotes. They can also be variables which have been assigned the value of strings, like $base_name in the example above. The PHP command echo expects one string as its argument. In the above example there are three distinct strings, two delimited by double quotes and the string contained in the value of $base_name. How we make these three strings one is by Concatenation of the strings using the . operator. Yes, the operator (symbol) for concatenation (mushing the strings together) is a period. Learn more about strings here.

So what we are doing with the second line is an echo of three strings mushed into one by the two periods surrounding .$base_name. followed by a ; (semicolon) to terminate the line.

The next line is an If Statement. The if statement is one method of directing program flow, or deciding things depending on how you think of this stuff. It has the form if(some_expression){do_if_true;}else{do_if_false;} The some_expression part has to evaluate to true or false. This is called a Boolean type. The semicolons after the do_if_true/false parts are required, the else do_if_false part is not required. The parentheses are used to group statements together and are optional if there is only one statement in each group.

The boolean expression in the example if($base_name == 'command') gets evaluated. If $base_name is equal to the string literal 'command' the expression evaluates to TRUE and the next statement is executed. The double equals == is the comparison operator for equals. A single equals = is an assignment operator which would assign the string 'command' to the variable $base_name, not what we want.

To recap, we have a function which when called creates an instance of a select which is named whatever name we passed in $base_name and depending on the value of that name makes one or the other type of select. After the select is constructed we echo a break to put whatever comes next on a new line.

Now we'll rework index.php, copy the following into the body part of the file.

  <body>
	<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}

	include "include/tutorial_functions.php";  // a collection of functions for various stuff

	echo "Hello World...<br />";
	echo "Fave Flav:<input type='text' name='favorite_flavor' /> ";
	select_command($_POST, $base_name="command"); // pick a command
	select_command($_POST, $base_name="something_else"); // pick another command
	echo "<input type='submit' name='submit' /> ";
?>
	<form>
  </body>
What's changed here is the include directly after the debug line. This sticks the contents of the named file inline in that spot. Since the file is a function it isn't executed (run) until it is called (invoked). We call that function twice with the lines that start select_command. If you save both files and mash Submit you should see something like:

10 posted on 02/14/2012 8:37:28 PM PST by Mycroft Holmes (Mash name for HTML primer)
[ Post Reply | Private Reply | To 9 | View Replies]

To: sand88
For those who don't have Webmin on their Linux servers, I suggest adding it. It is a wonderful tool. webmin site

Nice tool, just works. There is a lot more capability there than I need to manage my little herd but I expect I'll be using it anyway.

I can't believe that I am not getting any more takers on this thread. It seems like most of the people who responded already know what I am trying to impart. Sigh. Well, I have my own reasons for writing...

11 posted on 02/14/2012 9:49:45 PM PST by Mycroft Holmes (Mash name for HTML primer)
[ Post Reply | Private Reply | To 8 | View Replies]

To: Mycroft Holmes

Please keep posting. I find your instructions easy to understand and very informative.
I haven’t played with HTML for 15 years and it just got way ahead of me.

Your last post on HTML got me playing with it again.


12 posted on 02/15/2012 5:02:07 AM PST by Haddit
[ Post Reply | Private Reply | To 11 | View Replies]

To: Mycroft Holmes
The function we have constructed previously is pretty trivial and perhaps not very interesting but it does show how you can use a function as a template to create different instances of similar items.

What follows is a more amusing piece of code that actually does solve something. Specifying a quantity of stuff is a problem that comes up fairly often. Quantities have an amount and a unit, like 3 gallons or 5 feet. As a general rule you want to avoid allowing the user to type anything that will be used as an entry into a database, they will only break your heart (or tables). So selects are preferred to text inputs for pretty much everything. This generates a pair of selects named $prefix.'count' and $prefix.'units' right next to each other.

By this time when you see $ you should think variable. So you know that $prefix means some string that has been assigned to the variable $prefix. You should also think string literal when you see single quotes around some text, like 'count'. So when you see $prefix.'count' you are seeing the contents of the variable $prefix concatenated (.) with the string literal 'count' which results in one string.

Another thing you need to be aware of is that if something isn't a variable and it isn't quoted by either single or double quotes and it isn't an operator (<,>,=,+,-,...) and it looks like some_text($mumble_optional) then it is probably a function. Either one of yours or a PHP built in function. There is a nifty little search feature at the top of the the PHP documentation that defaults to searching the PHP function list. If you see something you don't understand that looks like a function(), go there for enlightenment grasshopper.

If you find yourself doing the same thing more that once you probably want to try to generalize it an make it into a function. Think of functions as tools that you are building. A few tools that do a a lot of things are better than a lot of tools that each do a few things. They are easier to find if they don't proliferate in an uncontrolled fashion.

A word about comments. PHP supports C style comments, which you don't see in the fragment below. I think comments are an unalloyed good, I just couldn't think of any to add to the code here that aren't blindingly obvious. Maybe I have been doing this too long. I do try to give variables and functions names that have readily apparent meaning.

Another thing I find useful is using text for option values in selects. If you don't specify a value an integer is assigned. Later when you evaluate the value you have an integer with no readily apparent meaning. In the past, integers were the preferred way of carrying value because memory was expensive and we tried to cram as much meaning into each bit as possible. Today memory is cheap, programmer's time is expensive. So any little thing we can do to make things blindingly obvious is a good thing.

Note that we are passing $Ingredient_Count and $Units into the function. This is because we can use the select as both a knob (to adjust things) and an indicator (to inform the user). Without special effort a select shows the first option on the list. We are passing the function the values that we want the select to stick at. If we don't provide values it will do the default behavior. In general we want to design objects that are as broadly useful as possible. This is why we didn't stick any labels on the selects in this function; any that we picked now would probably be wrong. We could pass one in, but it's a complication. Simple and general are what we strive for in functions.

function select_quantity($prefix, $Ingredient_Count, $Units)
{			
	echo "<select onchange='updateMenu();' name='".$prefix."count' >";
	for($i=0.5;$i<5;$i=$i+0.5) {
		if($i != $Ingredient_Count) echo "<option value='".$i."'>".$i."</option>";
		else echo "<option selected='selected' value='".$i."'>".$i."</option>";	
	}
	for($i=5;$i<33;$i++) { 
		if($i != $Ingredient_Count) echo "<option value='".$i."'>".$i."</option>";
		else echo "<option selected='selected' value='".$i."'>".$i."</option>";	
	}
	echo "</select>";
	echo "<select onchange='updateMenu();'  value='ea' name='".$prefix."units' >";
	if ('ea' != $Units) {echo "<option value='ea'>ea</option>";}
	else {echo "<option selected='selected' value='ea'>ea</option>";}
	if ('oz' != $Units) {echo "<option value='oz'>oz</option>";}
	else {echo "<option selected='selected' value='oz'>oz</option>";}
	if ('g' != $Units) {echo "<option value='g'>g</option>";}
	else {echo "<option selected='selected' value='g'>g</option>";}
	if ('lb' != $Units) {echo "<option value='lb'>lb</option>";}
	else {echo "<option selected='selected' value='lb'>lb</option>";}
	if ('tsp' != $Units) {echo "<option value='tsp'>tsp</option>";}
	else {echo "<option selected='selected' value='tsp'>tsp</option>";}
	if ('tbsp' != $Units) {echo "<option value='tbsp'>tbsp</option>";}
	else {echo "<option selected='selected' value='tbsp'>tbsp</option>";}
	echo "</select>";
}
The first line echos the opening tag of the select assigning the name of the select to be $prefix."count' so we can identify this particular select. The next line is the beginning of a for loop which spans 4 lines. The control structure for the loop increments the temporary variable $i by 0.5 for each pass of the loop. We are doing this because we want the count part of this control to increment by half on the low end till the value 5 and then increment by 1 to 32 which is done in the second for loop. This gives us a finer control of the value on the low end where it is more important and the ability to choose the appropriate units give the user the ability to input any reasonable values for this application.

Thinking about reasonable values is part of what you want to do when you design a function. This particular application manages a household inventory. Initially I believed that most of what I was buying was groceries and this select design reflects that. The units are all weights and volumes which are useful in the kitchen and not lengths which are useful other places. After using the program for a bit I would add lengths to this control. I just haven't done it yet because I designed a general purpose work-around into the program that makes this flaw not painful enough to immediately address.

I'd also might add more numbers at the top incrementing by 5 from maybe 30 to 100. There is a limit to how many items you can usefully cram into a select though. One of the ways to manage that is to use a two stage select but that has some interesting complications we will get into later.

The third section of the function generates the units selector. In a select an option has two parts, a value and a label that appears to the user on the select itself. Explicitly calling out the value is not required, if it is absent an integer starting at 0 and incrementing for each additional option is provided. I like to use the same text for the value as the user sees; this way when I encounter the value in the program I know what it does, not just that it is '2'.

Now grab that code above and save it in ~www/tutorial/include/tutorial_functions.php just in front of the closing tag for the PHP at the end of the file. We'll be using this bit shortly. Now we want to rework ~www/tutorial/index.php so that the body looks like:

  <body>
	<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}

	include "include/tutorial_functions.php";  // a collection of functions for various stuff

	echo "Hello World...<br />";
	echo "Fave Flav:<input type='text' name='favorite_flavor' /> ";
	select_command($_POST, $base_name="command"); // pick a command
	echo "<br />Food: ";
	select_quantity($prefix='food_'); // pick a quantity of food
	echo "<br />Drink: ";
	select_quantity($prefix='drink_'); // pick a quantity of drink
	echo "<input type='submit' name='submit' /> ";
?>
	<form>
  </body>

So save the files and hit Submit or Reload and pay attention. The first time you hit submit or reload the debug values aren't quite what you expect. Then you hit Submit again and they look OK. This is because the values in the debug area are the values that were on the previous screen. You need to keep that firmly in mind. These things become much more important later. You should now be seeing a screen that looks much like this:

So who ordered that break between Fave Flave: and Food:? Not what I had in mind. Poking about I notice that the select_command() function emits a <br /> at the end which is affecting our placement of related objects. Do not put positioning stuff in functions, it doesn't belong there. So fix select_command() in include/tutorial_functions.php so it doesn't emit that nasty break and save it away so it works properly. Good.

Another thing you might notice is that I entered 'chocolate => really' into the favorite_flavor text field. That => bit looks dangerously like an operator which ought to scare you. Remember, users can enter anything they can type into a text field and they are not usually looking to make life easy for you. They'll type the darnedest things... Don't give them the chance if you don't have to; if you do, pay attention, there are ways to mitigate the problem.

Another thing that is irritating about this program is that the controls and text inputs are not sticky. The data disappears when you Submit it. Usually that is what we want so that is the default behavior, but not always. Sometimes we want the data to stick. I want it to stick so that's what we'll do next.

13 posted on 02/15/2012 11:18:10 AM PST by Mycroft Holmes (Mash name for HTML primer)
[ Post Reply | Private Reply | To 10 | View Replies]

To: Haddit
Please keep posting. I find your instructions easy to understand and very informative. I haven’t played with HTML for 15 years and it just got way ahead of me. Your last post on HTML got me playing with it again.

Thanks, it's nice to know that it touched someone. The whole thing is on my Freep homepage starting with the Xampp link. The stuff on the homepage is a bit better edited as I always find some nit after I pull the trigger on the post. Sigh.

14 posted on 02/15/2012 3:08:43 PM PST by Mycroft Holmes (Mash name for HTML primer)
[ Post Reply | Private Reply | To 12 | View Replies]

To: Mycroft Holmes
So the current goal is to make the data stick from Submit to Submit. Copy the following code into the body of index.php.
  <body>
	<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}

	$FoodCount = $_POST["food_count"];  // Memory, Dr Memory 
	$FoodUnits = $_POST["food_units"];  
	$DrinkCount = $_POST["drink_count"]; 
	$DrinkUnits = $_POST["drink_units"];  
	$FavoriteFlavor = $_POST["favorite_flavor"]; 

	include "include/tutorial_functions.php";  // a collection of functions for various stuff

	echo "Hello World...<br />";
	echo "Fave Flav:<input type='text' value='".$FavoriteFlavor."' name='favorite_flavor' /> ";
	select_command($_POST, $base_name="command"); // pick a command
	echo "<br />Food: ";
	select_quantity($prefix='food_', $FoodCount, $FoodUnits); // pick a quantity of food
	echo "<br />Drink: ";
	select_quantity($prefix='drink_', $DrinkCount, $DrinkUnits); // pick a quantity of drink
	echo "<input type='submit' name='submit' /> ";
?>
	<form>
  </body>

The new parts are the block of assignments directly below our debugging statement and the use of those assigned values to inform the various elements of the form what their values should be. By now you recognize $_POST["food_count"] is an access to the array $_POST using the index "food_count" and assigning the value to $FoodCount.

Following the use of $FoodCount down to the function select_quantity() we see that $FoodCount is being fed to what we labeled $Ingredient_Count in the function. It might be occurring to us now that maybe $Ingredient_Count isn't the best sort of function name, it's too specific. Just $Count might be a more appropriate name, maybe $Amount, mumble.

You might also notice that the names don't match between the function call in index.php and the function template in tutorial_functions.php. This is a very good thing. This lets us change the poor names in our function template to good ones without having to find everywhere they were used and change those too. What does have to match is the order of the variables in function call and the function itself. It is best to put the required variables first in the function and the optional variables last.

But the really clever bits of this have probably passed unnoticed. If you look at the code above it makes sense. Once you understand the general syntax of C and a few operators the biggest help or hindrance to producing readable code is reasonable names. Reasonable descriptive names for variables and functions will make your life a lot easier. If you doubt the wisdom of this take a close look at the debug line again.

I know you have already mashed submit, I hope you saw something like:

But there is still something bothersome about the form. That Submit button looks like a pretty much otherwise useless piece of digital flotsam; let's get rid of it. What we would really like is for the form to be submitted when the command select is changed. This is going to need for us to do a bit of translation in the web browser. A change in the value of command needs to be transmogrified into the push of the vanished Submit button. We can't do this with PHP; it runs on the server, so it's

JavaScript to the rescue!

15 posted on 02/15/2012 5:12:43 PM PST by Mycroft Holmes (Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 13 | View Replies]

To: Mycroft Holmes
JavaScript to the rescue!

JavaScript: top

You can't use JavaScript on the forum for obvious reasons.

JavaScript runs on the client-side as opposed to the server-side where PHP runs. This makes it beautifully complementary to PHP. In another complementary fashion we are going to be editing the head of index.php not the body for this piece. Scripts may appear in-line, but I like to segregate them into their own little ghetto in the head. Replace all of the script element in the head with the following:

    <script type="text/javascript">
		/*	These scripts are available globally to all the included files.  The scripts
		*	are executed by the client machine in response to inputs by the user, typing
		*	input and selecting menus and such.  
		*
		*	Unlike the php source, these scripts are visible to the client when view source
		*	is used. The scrip functions are generally called by form elements when they
		*	are manipulated by the user, and cause things to happen on the client page.
		*
		*	It is very important in general to test all objects for non-null values before
		*	attempting to write to them as writing to a null object will hang the script.
		*	You can tell this is happening when you see that the form doesn't update when
		*	the values of the <selects> are changed.
		*/
		function formSubmit() 
		{	// reload frm1 (everything is frm1) with the current input values
			document.getElementById('frm1').submit();
		}
		function updateMenu() // runs every time any menu <select> is updated
		{	// 			
			formSubmit();
		}
    </script>
Now let's chat. In the opening tag we declare the script type to be text/javascript. We don't have to do this, it's the default. It's nice to make explicit the default though so that everybody is clear on the concept. Inside JavaScript C style comments work. Outside, HTML style comments are necessary. All of the comments are above are true and useful.

Those comments are pretty typical of what I write for comments. I'm lazy, to do this tutorial I swiped all this stuff from a program I already had written and working and deleted the stuff that isn't relevant. I don't like to write about what the code is doing; if I have named things properly I can read that. I comment about why the code is doing what it is doing. That I can't read in the code and I am unlikely to remember from one day to the next.

Our selects pretty much all have onchange='updateMenu();' in the opening tag. The attribute onchange is what we call an event. An event is something that happens to an element like changing value (onchange) or having the mouse move over the element (onmouseover). Events are things which happen to elements; think of them as verbs for elements. Mash here for a more complete treatment of events.

The event onchange causes a call to the function updateMenu() which calls formSubmit() which actually does the heavy lifting. The reason we didn't call formSubmit() directly is that we might want to do other things when a select changes that we don't want to do when some other element wants to submit the form. The actual submitting gets done by the document.getElementById('frm1').submit(); statement. To explain that statement we have to get into something known as the Document Object Model.

I don't want to talk in detail about DOM right now so just take a gander at that little bit of magic that simulates pushing the submit button and then look carefully in the opening tag of the form in the modified body that follows:

  <body>
	<form id="frm1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}

	$FoodCount = $_POST["food_count"];  // Memory, Dr Memory 
	$FoodUnits = $_POST["food_units"];  
	$DrinkCount = $_POST["drink_count"]; 
	$DrinkUnits = $_POST["drink_units"];  
	$FavoriteFlavor = $_POST["favorite_flavor"]; 

	include "include/tutorial_functions.php";  // a collection of functions for various stuff

	echo "Hello World...<br />";
	echo "Fave Flav:<input type='text' value='".$FavoriteFlavor."' name='favorite_flavor' /> ";
	select_command($_POST, $base_name="command"); // pick a command
	echo "<br />Food: ";
	select_quantity($prefix='food_', $FoodCount, $FoodUnits); // pick a quantity of food
	echo "<br />Drink: ";
	select_quantity($prefix='drink_', $DrinkCount, $DrinkUnits); // pick a quantity of drink
	//echo "<input type='submit' name='submit' /> ";
?>
	<form>
  </body>
What's different about the opening tag of the form is id="frm1". You can find all of the standard attributes here, and id is one. The short story is that it is a unique identifier for our form. The entire string document.getElementById('frm1').submit(); is DOMinese for "submit 'frm1' in this document".

One more thing to notice is that the line that echoed out the raw HTML for our former Submit button has been commented out. If you don't do this the button and the DOM fight and things don't work. You want things to work. Don't have two objects try to do the same thing, it's bad and wasteful (also bad).

You'll find that if you copy the script and the body into index.php, save and refresh, that the Submit button disappears and that the form is now submitted every time the value of a select changes. Give it a whirl.

To recap, we learned about events, which are like verbs for elements. We learned that we can use JavaScript to link events to the actions of elements on the browser's page through the Document Object Model. And that the DOM itself is a big black box at the moment. That will change.

MySQL: top

You can't use MySQL on the forum for obvious reasons.


xkcd: exploits of a mom. For more, click pic.

16 posted on 02/15/2012 11:36:36 PM PST by Mycroft Holmes (&larr; Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 15 | View Replies]

To: RobertClark; cuban leaf; InterceptPoint; smith288; 21stCenturion; sand88; Haddit
So it finally occurred to me that I should be pinging a list. You're on it. Let me know if you want different. There is lots of stuff to play with.

I blame poor social skills.

17 posted on 02/15/2012 11:52:38 PM PST by Mycroft Holmes (&larr; Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 2 | View Replies]

To: Mycroft Holmes
I blame poor social skills.

Developer with poor social skills?? No way.

18 posted on 02/16/2012 7:07:46 AM PST by smith288 (Peace at all costs gives you tyranny free of charge)
[ Post Reply | Private Reply | To 17 | View Replies]

To: smith288
I blame poor social skills.

Developer with poor social skills?? No way.

I don't really qualify as a developer. I'm more an EE/science type with a really disturbing set of hobbies.

19 posted on 02/16/2012 2:08:10 PM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 18 | View Replies]

To: Mycroft Holmes

Also of interest are the BitNami stacks

http://bitnami.org/stacks


20 posted on 02/16/2012 2:19:09 PM PST by 2ndamendmentpa
[ Post Reply | Private Reply | To 1 | View Replies]

To: 2ndamendmentpa
Also of interest are the BitNami stacks bitnami.org/stacks

Indeed. Care to relate your experiences with this piece of juicy goodness? Please do...

21 posted on 02/16/2012 3:11:16 PM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 20 | View Replies]

To: Mycroft Holmes; RobertClark; cuban leaf; InterceptPoint; smith288; 21stCenturion; sand88; Haddit

DOM:

Document Object Model: Or how I learned to love OOP...

Object Oriented Programming is the latest fad in code-smithing, all the cool kids have been doing it for 20+ years. The previous model was procedural, you called procedures with a pointer to data and the procedure munged the data and returned a value indicating success or failure or something... Procedures, algorithms, were separate from data and you called one to operate on the other.

The Object Model rolls procedures and data into a single fur-ball called an object. Procedures get renamed methods (I guess so you know it's an object) and the data, which gets renamed properties is inside the object and is usually divided into public and private parts (methods too). The public parts are the bits you can see and use.

Looking at the money bit from the last section document.getElementById('frm1').submit(); In this fragment, document is an object. getElementById('frm1') is a method of the object document which resolves to an object which is an element of type form with the id 'frm1'. This object has a method submit() which involks the Submit Input on the element object. Clear?

DOM can be viewed as an inverted tree with the document at the top. All of the elements of the document (page of HTML) are accessible if you give them a unique id="mumble". getElementById() is the best method of referring to elements in JavaScript. There is a method getElementsByTagName() which gets you a NodeList of all the elements with name="mumble" but it's easier just to use id="mumble" and ensure that id is unique.

You can look at the methods for the element object here. The most useful is setAttribute() which can be used to force inputs to desired values and states. But if you look to the left on the screen you will see a list of HTML DOM Objects. This is where the gold lies if you want to twiddle elements from JavaScript.

The take away here is that those elements on your page that you want to manipulate with JavaScript need to have a unique id="mumble". You may then refer to that element as document.getElementById('mumble').method();. The methods that are available to the object (element) depend on the object. In the tutorial example the object was a form and one of the methods of a form is submit();.

One of the hazards of JavaScript is that it fails silently. This is probably a good idea in a client side scripting language, if a particular thing is unavailable at the moment you don't want error messages spewed all over the user's screen. But it does make it annoying to debug. One of the things that will definitely cause JavaScript to fail is any attempt to write to a NULL object. Any object that doesn't appear on the current page is NULL. This is not as nonsensical as it seems. Your program may have the notion of an object that you just aren't rendering at the moment because the time is not right. If your script tries to write to that object when it has not been instantiated the script stops silently.

DOM is just another way to look at the document. We have been thinking of the document as a collection of HTML that gets spewed by the server to the client for rendering but it really is more complicated than that, and the DOM gives us a way to talk about it.

Editorial Rant: I've heard a lot of whining from old farts about how OOP doesn't make sense, or that it's too hard. Get over it. It turns out to be a fairly useful way of thinking about things and frankly, who cares if the actual bits don't work that way. In the early '90's I wrote a Java application (not script, running on the iron) of >100K lines in less than a year which maintained a schedule in an arbitrary database, built a website to sell time in that schedule, routinely displayed images and video and even answered and took reservations over the phone. It was, of course, wildly networked. We managed to sell about a thousand systems and never had a user report a bug. It is my understanding that most of them are in use to this day. End of rant.

22 posted on 02/16/2012 8:59:14 PM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 16 | View Replies]

To: Mycroft Holmes

I was a COBOL programmer between 1983 and 2002. A friend and coworker moved from COBOL to Powerbuilder and eventually became a teacher for Sybase in the mid-1990’s.

When we had lunch one day a few years later, we talked about our old programming days. As we talked about the changes from the old days he commented that the COBOL programs that I designed were actually object oriented in the way they functioned. Personally, I think that OOP is the only way to fly, and very easy to maintain.


23 posted on 02/17/2012 5:44:21 AM PST by cuban leaf (Were doomed! Details at eleven.)
[ Post Reply | Private Reply | To 22 | View Replies]

To: rdb3; Calvinist_Dark_Lord; Salo; JosephW; Only1choice____Freedom; amigatec; stylin_geek; ...

24 posted on 02/17/2012 5:45:36 AM PST by ShadowAce (Linux -- The Ultimate Windows Service Pack)
[ Post Reply | Private Reply | To 1 | View Replies]

Comment #25 Removed by Moderator

To: Mycroft Holmes

bookmark


26 posted on 02/17/2012 7:35:50 AM PST by rurgan (Make all laws have an expiration date of 3 years. too many laws is the problem)
[ Post Reply | Private Reply | To 1 | View Replies]

To: All

I can’t for the life of me figure out what on this thread would provoke a reply that would draw attention from a moderator. Some people’s children.


27 posted on 02/17/2012 9:09:55 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 26 | View Replies]

To: RobertClark; cuban leaf; InterceptPoint; smith288; 21stCenturion; sand88; Haddit; 2ndamendmentpa; ..

MySQL:

You can't use MySQL on the forum for obvious reasons.


xkcd: exploits of a mom. For more, click pic.

The first step in using a database is to create one. You can't do this from PHP, you have to do this directly using phpMyAdmin. Type localhost/phpmyadmin/ into your browser's address bar and hit CR. Select the Databases tab and type 'tutorial_db' into the textbox under Create New Database. Select 'ascii_bin' under Collate (you are selecting a character set for the db here). Bug (select, hit-it) Create. You should get feedback that "Database tutorial_db has been created" and you should see it appear in your list of databases.

Copy the following code into a file named ~www/tutorial/include/connect.php

<?php
$db = "tutorial_db";
$link = mysql_connect('localhost', 'admin', 'password');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
echo 'Connected successfully<br>';
mysql_select_db($db) or die(mysql_error());
?>
This fragment is not a function but an in-line bit of code that appears wherever we type include 'include/connect.php'; It just drops right in, like text from the gods. What it does is connects us to our database, using the name and password provided earlier, and informs us that we have successfully connected. The "or die" construct is interesting. If we fail to successfully connect the PHP script quits, Dead Right There. There is a very helpful error log though, you should find it soon. Part of the beauty of PHP is that this fragment (with our login name and password) never appears in the raw HTML emitted by the server. We then select, as opposed to connect to our database to proceed further. Copy the following code into the body of ~www/tutorial/index.php to make sure we are all on the same page.
  <body>
	<form id="frm1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}

	$FoodCount = $_POST["food_count"];  // Memory, Dr Memory 
	$FoodUnits = $_POST["food_units"];  
	$DrinkCount = $_POST["drink_count"]; 
	$DrinkUnits = $_POST["drink_units"];  
	$FavoriteFlavor = $_POST["favorite_flavor"]; 

	include "include/tutorial_functions.php";  // a collection of functions for various stuff

	echo "Hello World...<br />";
	echo "Fave Flav:<input type='text' value='".$FavoriteFlavor."' name='favorite_flavor' /> ";
	select_command($_POST, $base_name="command"); // pick a command
	echo "<br />Food: ";
	select_quantity($prefix='food_', $FoodCount, $FoodUnits); // pick a quantity of food
	echo "<br />Drink: ";
	select_quantity($prefix='drink_', $DrinkCount, $DrinkUnits); // pick a quantity of drink

	echo "<br />";
	include 'include/connect.php'; // connects us to tutorial_db
?>
	<form>
  </body>
The new thing here is the include/connect.php at the bottom. If you do the usual save/submit cycle you should see "Connected successfully" from the include file telling you all is good. We will soon eliminate the line generating that happy feedback as it will be in our way, but for now it lets us know everything is working as it should.

Now we need to add a Table. In this case, a table is not furniture but a template for a collection of data. The data we are collecting for this little program is about stuff we buy at the store. The first table we need is one that represents items. I've copied below the existing table I am using.

	 1	name			varchar(64)	latin1_swedish_ci
	 2	upc			bigint(16)		No	None	
	 3	menus			varchar(64)	latin1_swedish_ci
	 4	price			varchar(16)	latin1_swedish_ci
	 5	amount			varchar(32)	latin1_swedish_ci
	 6	calories_unit		varchar(32)	latin1_swedish_ci
	 7	suppliers		varchar(64)	latin1_swedish_ci
	 8	handling		int(11)		No	None
	 9	url			varchar(64)	latin1_swedish_ci
	 10	level			double		No	None
	 11	reorder			float		No	None

Tables are where data is stored in a database. It's convenient to think of tables as rows of individual items and columns of data fields. One of the columns is designated the primary key and the values in that column must be unique, each row's value must be different. Think of the primary key as the one true name of the record or individual entry (row) in the table.

The list above comprise the columns of the table. In general it is better to overdo than to fall short on field sizes. Don't be ridiculous, we don't need 4096K to store a product name, but it is easy to make fields go away or be smaller. Before you have accumulated significant data it is easy to adjust fields in general. Going big and cutting back when you have some experience seems to be a path that has worked for me.

Another database trick you want to be very aware of: If you are storing the same data in two different places you are doing it wrong. Consider the table above, there is a field named 'suppliers' and its a varchar(64). You might naively think we are going to put the supplier's name and address in that field, but that would be wrong. Many (most, really) of the items come from the same supplier. Imagine row after row containing the data 'Wallmart in Milton, FL 32570' over and over again, row after row. Pretty dreary all this duplication of text.

So what we do is create another table called 'suppliers' with a numeric primary key and a bunch of fields that have the supplier name, address, phone, contact, url, last conversation and anything else we can think of because we are only going to store this bit once and use that primary key in the suppliers field of the item table data.

So why is suppliers a text field? Because we may have multiple suppliers for the same item. We can store them by saving their primary keys as Comma Separated Values (CSV) in the suppliers field. There are downsides to this we will discuss later.

The next thing to do is write some code that will check to see if the tables we are interested in are present, and if not, to create them. Being lazy, for this application I just used phpMyAdmin to define the tables, but if you want to deploy an application to some folks and have them collect their own data you might want your program to set up the tables. So, I'll go away now and work that out and be back with some code that creates tables.

I hope some of you are being entertained. I know I am...

28 posted on 02/17/2012 10:44:47 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 22 | View Replies]

To: Mycroft Holmes

Are you talking about the pulled post #25?


29 posted on 02/17/2012 11:18:37 AM PST by ShadowAce (Linux -- The Ultimate Windows Service Pack)
[ Post Reply | Private Reply | To 27 | View Replies]

To: Mycroft Holmes; cuban leaf

Another former COBOL programmer here. I have considered writing a similar tutorial, geared towards folks like me - ‘old ‘mainframers that are now working in another skillset. Today I do java/js/j2ee/weblogic/xml/oracle/hibernate/etc development, and really enjoy it.

I used to look at OOP as magic, then got into it a bit more. Makes sense now, but sometimes I am still annoyed by ‘kids these days’. The whole ‘shopping cart’ model - seems no one knows how to do volume processing anymore. Even though a lot of my work is ‘front-end’, I still prefer the challenge of dealing with large ‘batches’ of work (and still needed where I work). Sad to say they ignore this work in favor of their on-line fetish...

I started my tutorial this weekend using Win 7, but in a Virtual Box running Ubuntu. Somehow lost my ‘vdi’ file or some such, so now I get to start again.


30 posted on 02/17/2012 11:23:32 AM PST by LearnsFromMistakes (Yes, I am happy to see you. But that IS a gun in my pocket.)
[ Post Reply | Private Reply | To 1 | View Replies]

To: ShadowAce
Are you talking about the pulled post #25?

Yes

31 posted on 02/17/2012 11:32:19 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 29 | View Replies]

To: Mycroft Holmes

That was me. I double posted the tech ping so I requested the mod remove the duplicate post.<p
Nothing to be alarmed about.


32 posted on 02/17/2012 11:39:42 AM PST by ShadowAce (Linux -- The Ultimate Windows Service Pack)
[ Post Reply | Private Reply | To 31 | View Replies]

To: LearnsFromMistakes; cuban leaf
Nice. I look forward to seeing your stuff. It's good to see different descriptions of the same difficult material. Lighting it up from multiple directions make perception easier.

I'm writing for a really bright 17 year old. I've got a nephew I hope to interest with this when I'm done.

33 posted on 02/17/2012 11:53:02 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 30 | View Replies]

To: LearnsFromMistakes

I read a book in 1996 that was called, I believe, OOP for managers. It was great. With tons of analogies and pictures it discussed objects, classes, stored procedures and all that stuff.

I haven’t done any programming since I left COBOL. I”m now a PM/BSA. That said, I did rewrite a very poorly written five pages of SQL Server code someone handed me into a structured two pages.

It’s amazing how similar the functionality of computer languages is to figure out even with training, once you’ve learned one of them.


34 posted on 02/17/2012 11:56:49 AM PST by cuban leaf (Were doomed! Details at eleven.)
[ Post Reply | Private Reply | To 30 | View Replies]

To: Mycroft Holmes

I wasn’t going down the ‘lamp’ path for a tutorial, but something more like a ‘standard’ dev environment: linux, java, maven, junits, mysql, junits, etc - keep adding components like version-control, injection control, logging, code analyzers, web servers (which you cover)...you get the idea.

I have a good idea how to get these all going, but I would love to have it all written down and easily repeatable. I have a growing list of components to add...somewhere...


35 posted on 02/17/2012 12:40:08 PM PST by LearnsFromMistakes (Yes, I am happy to see you. But that IS a gun in my pocket.)
[ Post Reply | Private Reply | To 33 | View Replies]

To: LearnsFromMistakes

Sweet. Even better.


36 posted on 02/17/2012 12:44:47 PM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 35 | View Replies]

To: LearnsFromMistakes
junits, mysql, junits,

You listed junits twice?

I like junits...

37 posted on 02/17/2012 12:50:05 PM PST by LearnsFromMistakes (Yes, I am happy to see you. But that IS a gun in my pocket.)
[ Post Reply | Private Reply | To 35 | View Replies]

To: Mycroft Holmes
Bookmarking. Another good method of setting up a server like this for educational purposes is to build a virtual machine, and use it as your sandbox. Normally, such a server can be set up as a local (RFC1918) address, so there is no way the outside world can get to it, yet your local computer can. Also, it would let you test out some interesting things, like running your mysql server on another VM. It's always a bad idea to have your DB running on the same box as your web/app server.

I've had a lot of fun with that kind of thing in the past, and actually set up a 3-tiered architecture in VMs under VMWare to play with different scenarios. Granted, that kind of thing is probably over the average Joe's head, and memory resources (I have 18GB on my workstation, and rarely have memory issues), but for those who want to go further, it can give folks an idea of the complexity of real-world systems.

If I have some time this weekend, I might build a small VM for exactly this purpose. Wonder if I could get it runing under DSL. Hmmmmm...

38 posted on 02/17/2012 8:48:49 PM PST by zeugma (Those of us who work for a living are outnumbered by those who vote for a living.)
[ Post Reply | Private Reply | To 1 | View Replies]

To: zeugma
I had a couple of co-workers at my last gig who were deep into the whole VM deal. The were both consultants from CH2M Hill and the ability to switch environments completely seemed really attractive if you were a consultant working with multiple clients.

But I never got what VM would do for me. I'm a fair power user but I don't need to be switching environments or hiding information from myself or others. What advantages would I get from using a VM, other than increased hassle?

I see people doing it, so there must be something I'm missing. I've already got multiple machines with multiple OSs, why do I need to virtualize any of them?

Hoping for light, not heat. Regards.

39 posted on 02/18/2012 2:52:52 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C primer)
[ Post Reply | Private Reply | To 38 | View Replies]

To: Mycroft Holmes
I see people doing it, so there must be something I'm missing. I've already got multiple machines with multiple OSs, why do I need to virtualize any of them?

Hoping for light, not heat. Regards.

No heat from me about this. ;-)

I see VMs as a tool that can be used in a lot of different ways. Let me set forth a few scenerios, that might shed some light for you.

One last thing. I've really been  suprised that more corporate-type software isn't sold as complete working VMs. Could you imagine what it would mean from a troubleshtooting perspective, if you could tell your customer "take a snapshot and sent it to us." You'd have absolute and complete control over the hardware, software, and many other aspects of the environment. I would think from a supportability standpoint it would be an absolute godsend.  If you set things up properly, such that customer data resided on a separate disk, mounted to the VM at boot time, the customer would be protected against sending you confidential information as well.

I'm sure there are a lot of other use-cases, as varied as you could probably imagine. I can understand someone not really seeing the utility of virtualization. It depends a lot on how you use your computer. There may well not be any benefit fo you. Then again, there might just be a use that you've just not thought of yet.

40 posted on 02/19/2012 11:26:34 AM PST by zeugma (Those of us who work for a living are outnumbered by those who vote for a living.)
[ Post Reply | Private Reply | To 39 | View Replies]

To: zeugma
Nice pitch on the value of virtualization for the average schlub. Thank you for taking the time. You sold me. I'd sort of heard all of that before, but it went in one ear and out the other. I especially liked the notion of "kid-proofing" a machine from malware. If I could get back all the hours...

So I installed VirtualBox from Oracle on my Ubuntu 11.10 box yesterday hoping to install XP to get to the one (count 'em) remaining program that I must use Billware to run.

For some reason I can't get the VM to see the local hard drive while it is attempting to install XP. I've mapped a drive and all and I expect that I'll work it out. Mumble. In the mean time I still have the crappy old laptop running AVR Studio 5 and nothing else. That's plenty safe too. Nobody wants to play with the decrepit old laptop.

I, for one, welcome our new SkyNet Overlords /.

41 posted on 02/20/2012 2:30:02 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C JavaScript primer)
[ Post Reply | Private Reply | To 40 | View Replies]

To: Mycroft Holmes

BFL Thanks!


42 posted on 02/20/2012 7:56:14 AM PST by HeartlandOfAmerica (Geithner: Taxes on 'Small Business' Must Rise So Government Doesn't 'Shrink')
[ Post Reply | Private Reply | To 41 | View Replies]

To: RobertClark; cuban leaf; InterceptPoint; smith288; 21stCenturion; sand88; Haddit; 2ndamendmentpa; ..
When we last left off I had erroneously stated that you can't create a db from PHP. More accurately, I had tried for a little bit and given up and just whacked it off with phpMyAdmin, tables too. So here is the promised code to create a db and tables from PHP. First, to make sure we are all on the same page, here are the three files we will be playing with in their entirety.

~www/tutorial/index.php

<html>
  <head>
    <title>
	Page title goes here...
    </title>
    <style>
	CSS Style, if you've got it...
    </style>
    <script type="text/javascript">
		/*	These scripts are available globally to all the included files.  The scripts
		*	are executed by the client machine in response to inputs by the user, typing
		*	input and selecting menus and such.  
		*
		*	Unlike the php source, these scripts are visible to the client when view source
		*	is used. The scrip functions are generally called by form elements when they
		*	are manipulated by the user, and cause things to happen on the client page.
		*
		*	It is very important in general to test all objects for non-null values before
		*	attempting to write to them as writing to a null object will hang the script.
		*	You can tell this is happening when you see that the form doesn't update when
		*	the values of the <selects> are changed.
		*/
		function formSubmit() 
		{	// reload frm1 (everything is frm1) with the current input values
			document.getElementById('frm1').submit();
		}
		function updateMenu() // runs every time any menu <select> is updated
		{	// 			
			formSubmit();
		}
    </script>
  </head>
  <body>
	<form id="frm1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {echo "In index.php<br />";$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br />";}}

	$FoodCount = $_POST["food_count"];  // Memory, Dr Memory 
	$FoodUnits = $_POST["food_units"];  
	$DrinkCount = $_POST["drink_count"]; 
	$DrinkUnits = $_POST["drink_units"];  
	$FavoriteFlavor = $_POST["favorite_flavor"]; 

	include "include/tutorial_functions.php";  // a collection of functions for tutorial
	include "include/connect.php";  // keys for db login
	include "include/check_tables.php";  // see that db tables are present, create if not

	echo "Hello World...<br />";
	echo "Fave Flav:<input type='text' value='".$FavoriteFlavor."' name='favorite_flavor' /> ";
	select_command($_POST, $base_name="command"); // pick a command
	echo "<br />Food: ";
	select_quantity($prefix='food_', $FoodCount, $FoodUnits); // pick a quantity of food
	echo "<br />Drink: ";
	select_quantity($prefix='drink_', $DrinkCount, $DrinkUnits); // pick a quantity of drink
	echo "<br />";
	echo "Hi there<br />";

	check_tables(); // check to see that tables present
	echo "<br />Hi Again<br />";

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

~www/tutorial/connect.php
<?php
// this is an in-line and the only place where the db username
// and password should appear.
$debug = true;
$db = "tutorial_db";
$link = mysql_connect('localhost', 'admin', 'password');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
if($debug == true) {echo 'Connected to MySQL successfully<br>';}
?>
~www/tutorial/check_tables.php
<?php
/*		file: include/check_tables.php
*		2012/02/17 - working initial cut
*		
*		Check for existance of tables and create any
*		missing ones.
*/
function check_tables() {
// Usage without mysql_list_dbs() deprecated
	$debug = true;
	include 'include/connect.php'; // connects us to db
	if($debug == true) {echo 'Connected SQL link='.$link.'<br />';}
	$res = mysql_query("SHOW DATABASES");
	if($debug == true) {echo "checking database...<br />";}
	while ($row = mysql_fetch_assoc($res)) {
		echo $row['Database'] . "\n";
	}
}
	// Create items table
function create_items_table() {
	include 'include/connect.php'; // connects us to tutorial_db
	echo "Creating Table items.<br />";
	$sql = "CREATE TABLE items
	(
	name varchar(256),
	upc bigint(16) NOT NULL,
	menus varchar(64),
	price varchar(32),
	amount varchar(32),
	calories_unit varchar(32),
	suppliers varchar(32),
	handling int(11),
	url varchar(512),
	level double,
	reorder float,
	CONSTRAINT item_pk	// primary key
		PRIMARY KEY (upc),
	CONSTRAINT item_uq	// unique fields
		UNIQUE (upc)
	)";		
	// Execute query
	mysql_query($sql,$link);
	mysql_close($link);	
}
?>

These have been edited a bit to suit my nefarious purposes so please do cut and paste. The main differences here are that we are making a connection to the db and getting a list of the databases present. We can then check to see if our db is among them. If so, we'll check the tables and if they are not present we will create them. We won't ask permission because without tables the rest of the tutorial is pretty useless, but in a real application it is usually wise to ask before doing anything rash.

After you have saved the files away and diddled one of the selects to get a refresh, you should see something like:

Whoops! See below:

drink_units=oz
Connected to MySQL successfully
Hello World...
Who ordered that? Looks like we have treated an inline, connect.php, like a collection of functions and it hurt us. So remove the include to prevent unnecessary connects. Fix this to be sure you understand.

The other thing that is going on here, the thing that we planned, is that we are connecting to the db successfully with a particular Resource id and we got a list of databases. Ours, "tutorial_db" is among them because we created it earlier using phpMyAdmin. Using that same tool, let's blow it away so we can recreate it auto-magically.

A quick word about debugging here. I use echo extensively for debugging (and the error logs). Sometimes it is temporary, like "Hi there". These statements get blown away forever when they have served their purpose. There are others though, that I think may just get used again, and they get hidden by if($debug==false){spray_information_to_page;} in the normal course of things. As the number of files grow, I like to identify what file or function the debugging information came from so I can turn it off. This is why "In index.php" now appears at the top of the output.

So let's add a little bit to our check_tables() function to create the necessary db and tables.

function check_tables() {
// Usage without mysql_list_dbs() deprecated
	include 'include/connect.php'; // connects us to db
	$debug = true;
	if($debug == true){echo 'Connected SQL link='.$link.'<br />';}
	$res = mysql_query("SHOW DATABASES");
	if($debug == true){echo "checking database...<br />";}
	$present = false;
	while ($row = mysql_fetch_assoc($res)) {
		if($debug == true){echo $row['Database']." ";}
		if($row['Database'] == $db){$present = true;}
	}
	if($debug == true){echo "<br />";}
	if($present == false) { // Create db
		echo "Database ".$db." not present. Creating...<br />";
		$sql = 'CREATE DATABASE '.$db;
		if (mysql_query($sql, $link)) {
			echo "Database ".$db." created successfully<br />";
		} else {
			echo 'Error creating '.$db.': ' . mysql_error() . "<br />";
			die(mysql_error());
		}
	}
	mysql_select_db($db);
	$sql = "SHOW TABLES FROM ".$db;
	$result = mysql_query($sql);
	if (!$result) {
		echo "DB Error, could not list tables\n";
		echo 'MySQL Error: ' . mysql_error();
		exit;
	}
	$items_present = false;
	while ($row = mysql_fetch_row($result)) {
		if($debug == true){echo "Table: {$row[0]} <br />";}
		//echo "Table: ."$row[0]." ";
		if($row[0] == 'items') {$items_present = true;}
	}
	if($items_present == false) { //make items table
		create_items_table();
	}
	mysql_free_result($result);
}

Copy, save, submit and you should see something like:

Which shows a database named 'tutorial_db' and table called 'items' created. Yea! Next we'll talk more about SQL in general.

43 posted on 02/20/2012 12:40:35 PM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C JavaScript primer)
[ Post Reply | Private Reply | To 28 | View Replies]

To: Mycroft Holmes
We are using a version of SQL called MySQL. There are about 5 major flavors of SQL, all pretty much mutually incompatible at the level of fine detail. At the same time, they all work substantially alike. Understanding one version gets you 97% of the way to understanding any other. SQL was developed originally by IBM in the early 1970's and called SEQUEL. It was renamed due to a trademark dispute.

A pretty good tutorial on SQL in general can be found here. SQL is an acronym for Structured Query Language. Some formulations replace Structured with something less complementary. It became an ANSI standard in 1987 (the reason there are only five versions) which has been enhanced by vendors several times since then in the interest of keeping their customers locked to their particular product.

It's a language like any other. There are control structures (CASE statements) and a blizzard of data types, different for each version, of course. The whole business is optimized to work on data structured as tables. Think rows of individual entries with columns of fields of different data types. SQL is used to sort through a collection of such data looking for rows which meet the specification of the moment and returning those rows to the user for further processing.

Most of the actual mechanics of what we will be doing is putting together a string (called a query in SQL-speak) and stuffing it into the function $res = mysql_query($sql); with the results ending up in the array $res. It's the query string itself that does most of the work communicating with the db. The formulation while ($row = mysql_fetch_row($result)) {paw_through_the_rows;} lets you step through the rows of results looking for what you want. Ninety five percent of what we do is simple variations on this theme.

Most of the art of SQL lies in designing the tables. There are definitely right and wrong ways to go about it. You can even make the wrong way work, for a while. I'm not a database guy and I do have a penchant for learning things the hard way. I've been trying to formulate general rules for db design but have only come up with one so far. If you find yourself storing the same information in two different places, you are doing it wrong.

We have already designed one table. We slipped that in with the function create_items_table() in ~www/tutorial/check_tables.php. This is a table of items one might buy at the store. We enumerated the list of fields earlier and that list is present in the function above. One of those fields is called menu and it tells us which menu (a grouping) that item is to be found on. We need to somehow group items so as to keep the selects for the items from becoming unwieldy.

The initial thought was to group like items with like. Drinks with drinks and dairy with dairy and such. This turns out to be not such a bad idea and almost correct. The people doing the actual buying wanted a list organized by where the items physically were in the store. This meant that some items that were say fresh orange juice were not stored with the other drinks but instead are with the dairy items. Some flexibility in the menus is obviously required.

So we need a table for the item menus. Let's call it item_menus. It needs two fields, index0 type int(11) and name type varchar(64). We are using index0 instead of index for a name because the name index is special to SQL, name does not appear to be special. This is the table's primary key and it is also used to order the menu. The name part of the table is the text that actually appears in the menu used to organize the items.

I've reworked this file a bit so stuff this whole mess into ~www/tutorial/check_tables.php

<?php
/*		file: include/check_tables.php
*		2012/02/17 - working initial cut
*		2012/02/20 - added creating db, items
*		2012/02/20 - added creating item_menus
*		
*		Check for existance of tables and create any
*		missing ones.
*/
function check_tables() {
// Usage without mysql_list_dbs() deprecated
	include 'include/connect.php'; // connects us to db
	$debug = true;
	if($debug == true){echo 'In check_tables() Connected SQL link='.$link.'<br />';}
	$res = mysql_query("SHOW DATABASES");
	if($debug == true){echo "checking database...<br />";}
	$present = false;
	while ($row = mysql_fetch_assoc($res)) {
		if($debug == true){echo $row['Database']." ";}
		if($row['Database'] == $db){$present = true;}
	}
	if($debug == true){echo "<br />";}
	if($present == false) { // db not present, creat it.
		echo "Database ".$db." not present. Creating...<br />";
		$sql = 'CREATE DATABASE '.$db;
		if (mysql_query($sql, $link)) {
			echo "Database ".$db." created successfully<br />";
		} else {
			echo 'Error creating '.$db.': ' . mysql_error() . "<br />";
			die(mysql_error()); // die a horrible death, can't go on...
		}
	}
	mysql_select_db($db);
	$sql = "SHOW TABLES FROM ".$db;
	$result = mysql_query($sql);
	if (!$result) {
		echo "DB Error, could not list tables\n";
		echo 'MySQL Error: ' . mysql_error();
		exit; // die a horrible death, can't go on...
	}
	$items_present = false; // flags for table creation
	$item_menus_present = false;
	while ($row = mysql_fetch_row($result)) { // paw through the results
		if($debug == true){echo "Table: {$row[0]} <br />";}
		//echo "Table: ."$row[0]." ";
		if($row[0] == 'items') {$items_present = true;}
		if($row[0] == 'item_menus') {$item_menus_present = true;}
	}
	mysql_free_result($result); //return some memory
	if($items_present == false) { //make items table
		create_items_table();
	}
	if($item_menus_present == false) { //make item_menus table
		create_item_menus_table();
	}
}
	// Create items table
function create_items_table() {
	include 'include/connect.php'; // connects us to tutorial_db
	echo "Creating Table items. <br />";
	// do NOT put any comments in the string below
	$sql = "CREATE TABLE items (
	name varchar(256),
	upc bigint(16) NOT NULL,
	menus varchar(64),
	price varchar(32),
	amount varchar(32),
	calories_unit varchar(32),
	suppliers varchar(32),
	handling int(11),
	url varchar(512),
	level double,
	reorder float,
	CONSTRAINT item_pk	
		PRIMARY KEY (upc),
	CONSTRAINT item_uq	
		UNIQUE (upc)
	)";		
	// Execute query
	$res = mysql_query($sql);
	if($debug == true){echo "Result = ".$res;}
	mysql_close($link);	// we're done, clean up.
}
	// Create item menus table
function create_item_menus_table() {
	include 'include/connect.php'; // connects us to tutorial_db
	echo "Creating Table item_menus. <br />";
	// do NOT put any comments in the string below
	$sql = "CREATE TABLE item_menus (
	index0 int(11) NOT NULL,
	name varchar(64) NOT NULL,
	CONSTRAINT item_menus_pk	
		PRIMARY KEY (index0),
	CONSTRAINT item_menus_uq	
		UNIQUE (name)
	)";		
	// Execute query
	$res = mysql_query($sql);
	if($debug == true){echo "Result = ".$res;}
	mysql_close($link);	// we're done, clean up.
}
?>
The rework is in the table creation logic and in closing the links after individual table creation. This is probably a good idea to let the system reclaim memory in an orderly fashion. The system will also probably reclaim the memory when a new $link is opened, at least it should. Better to be explicit and safe than rely on how things should be and sorry. A few comments have been added for clarity. Hey, I tried.

Another thing to be aware of is that this whole check_tables() business runs every time the page is refreshed. You might not want to do that, it consumes resources (CPU) that you might want for something else, like running the program with > 10K users. It would be wise to only run this function when there are new tables to be made. On the other paw, it isn't very computationally expensive. For the moment we will leave things as they are. We'll be slipping new tables in pretty regularly for a while.

So, to recap; we know how to check to see if a db is present and create it if not. We can check for the presence of individual tables and create them if they are not in the db. In the future, for additional tables I will provide the function for table creation and you will graft it into check_tables() so that it all works. You should be able to do this now. If not, I need to know because I may not be communicating clearly.

44 posted on 02/21/2012 4:51:05 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C JavaScript primer)
[ Post Reply | Private Reply | To 43 | View Replies]

To: RobertClark; cuban leaf; InterceptPoint; smith288; 21stCenturion; sand88; Haddit; 2ndamendmentpa; ..

New installment ping.


45 posted on 02/21/2012 4:53:00 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C JavaScript primer)
[ Post Reply | Private Reply | To 44 | View Replies]

To: Mycroft Holmes

I’m sorry that I can’t really help you with VirtualBox, as it’s something I’ve only played with in a very limited way. Regarding kid-proofing a computer, it can be a major Godsend. I have a friend you actually went so far as to set up an ESX server in his home with virtual desktops installed for his kids. He’s using a thin client that looks more or less like an oversized wall-mounted electrical outlet. You plug in a monitor/keyboard/mouse and connect to the ESX farm for your desktop. He seems to like the setup a lot. When he’s ready to upgrade OSes, he can install an image, clone it a few times, and **poof** new desktops all around the house.


46 posted on 02/21/2012 12:10:15 PM PST by zeugma (Those of us who work for a living are outnumbered by those who vote for a living.)
[ Post Reply | Private Reply | To 41 | View Replies]

To: RobertClark; cuban leaf; InterceptPoint; smith288; 21stCenturion; sand88; Haddit; 2ndamendmentpa; ..

Writing the Program: top

So now we have all of the pieces in place to begin writing our program and our understanding of all of the various bits is sufficient to proceed. There is a new factor I would like to introduce here, the notion of a hidden variable. This is an input in a form that doesn't appear on the rendered page. It's very useful in passing state information from page view to page view; it's really all the same page.

A hidden variable looks like this <input id='edit_menu_exists_id' type='hidden' value='exists' name='edit_menu_exists'> The simple existence of the variable can contain the information or you can attach a value to it. This variable is going to be used to indicate how we are editing items in the database. There are three types of edit we can do, add, edit and delete. We can also note that a page (or display interface) exists. We use simple obvious strings to convey those values to make the program more readable.

In the code below there is a hidden variable in the function edit_menu() that only shows up in $_POST when an instance of function edit_menu() exists. We assign the value of that variable to $EM_exists and it serves as a flag to let us know if we are editing menus or not.

We can light up an instance of edit_menu() by selecting 'Edit Menus' at the bottom of the global command select created by select_command($_POST); We removed the silly switch and base_name business, that was just for the tutorial. If we do select 'Edit Menus' the form is submitted with the value of the input 'command' as 'Edit Menus' which will appear in the array $_POST["command"] and gets stuffed into $Command.

When we come to the if statement $Command == 'Edit Menus' is satisfied and none of the other variables exist so they are not a factor. edit_menu($_POST); gets invoked (called, executed) and an instance of edit_menu() is created with all of its various objects. We'll see those later.

The newly created instance creates it's hidden variable which eventually lands in $EM_exists which lets us "latch" the instance of edit_menu() until the 'Exit Edit Menus' condition in the if statement is satisfied.

Replace the entire body of ~www/tutorial/index.php with the following:

 
  <body>
	<form id="frm1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {echo "In index.php<br />";$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br />";}}

	$Command = $_POST["command"];  // Memory, Dr Memory; global command select value
	$EM_command = $_POST["edit_menu_command"];  // edit_menu command select value
	$EM_exists = $_POST["edit_menu_exists"];  // edit_menu exists
	$New_menu = htmlspecialchars_decode($_POST["new_menu"]);  // used in edit_menus as a source (is a textfield)
	$Current_menu = $_POST["menu_current"];
	//$Feedback = ''; // Global string, produced by everybody, consumed by index.php and printed at the bottom of the page.

	include "include/tutorial_functions.php";  // a collection of functions for tutorial
	include "include/check_tables.php";  // see that db tables are present, create if not
	include "include/edit_menu.php";  // edit the menu catagories.
	include "include/select_generic.php";  // a generic select into the db

	select_command($_POST); // pick a command
	echo "<br />";
	check_tables(); // check to see that tables present
	
	if  (($Command == 'Edit Menus'  || $EM_exists == 'exists') && $EM_command != 'Exit Edit Menus')  {  
		edit_menu($_POST);  
	} 
	echo "<p class='fb'>".$Feedback."</p>"; // output at bottom of page
	echo "<p class='err'>".$Error."</p>"; // using the css defined at the beginning of the page
?>
	<form>
  </body>

We include two new .php files which we'll be using later. When they are missing things should fail silently but an error message is recorded in the error log. You have found the error log, yes?

The first file, edit_menu.php, we discussed above, it lets you create and edit menus (categories) for items you purchase. The second file, select_generic.php is used by edit_menu() and a whole lot more. With select_generic() we can begin to see the possibilities of maybe making all of this not so dreary and confusing. We'll get to that too.

Near the bottom is code that prints the contents of a couple of variables that are used to report errors and feedback. There is a new construct <p class='fb'>".$Feedback."</p>. This is the first sighting of the actual use of CSS. What we have done is assigned this entire paragraph to the class 'fb' (feedback). Later we will color it blue but that's a distraction for now.

Another thing to notice as we move forward is that the pages now start to seem to have two parts. There is a noun part that makes objects that show up on the page and there is a verb part that controls the action. I like to group the action at the end of the file. This seems to make sense, first you make things and then you act on them. When we Submit the page all of the values of the inputs with the names of their instances (most of the objects we are creating) are posted back to the server.

47 posted on 02/22/2012 5:18:15 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C JavaScript primer)
[ Post Reply | Private Reply | To 44 | View Replies]

To: RobertClark; cuban leaf; InterceptPoint; smith288; 21stCenturion; sand88; Haddit; 2ndamendmentpa; ..

Back at the Server:

Whoops! Un-comment $Feedback = ""; in index.php, the example above. Sorry, slip of the mind. That statement zeros out that variable before it gets processed by the grammar of the includes. That is where it sees most of its use.

Back at the server, the very first thing we do in the form (modulo debug) is unwrap all of those inputs in the $_POST and stuff them into variables so that they can be evaluated by the verb part of the include files that follow the assignment. The include files to this point have been mostly functions. Functions don't actually exist until they are called. The verb parts, the included grammar (I did make that one up), do exist and the logic of it is executed as the files are included (processed by PHP) while it reads and evaluates the file. In order for the variables to be usable by the included grammar the variable assignment must precede the included files. You see this in index.php which is currently the only file with includes. This will also change.

We have redone the function select_command() so that it only need be passed the variable $_POST. By unwrapping $_POST we can get to all of the current state. We use a bit of that state, $EI_exists, to modify the creation of this select. We will be seeing this work shortly. We also added a new function, edit_menu_command() which creates a command select for the function edit_menu().

Replace the function select_command() in ~www/tutorial/include/tutorial_function.php with the following:

function select_command($_POST) {
	$EI_exists = $_POST["edit_item_exists"];
	$Command = $_POST["command"];

	echo "<select onchange='updateMenu();' name='".$base_name."'>";	
	echo "<optgroup label=\"List Operations\">";
	echo "<option value='Global Commands'>Global Commands</option>";
	echo "<option value='Add To List'>Add To List</option>";
	echo "<option value='Delete From List'>Delete From List</option>";
	echo "</optgroup>";
	echo "<optgroup label=\"DB Operations\">"; // are we permitted to save item?
	if(($Command != 'Save Item to DB' && $Command != 'Continue Unchanged') && ($EI_exists == 'add' || $EI_exists == 'edit' || $EI_exists == 'delete'
		|| $Command == 'Add Item to DB' || $Command == 'Edit Item in DB' || $Command == 'Delete Item in DB')) { // add the ask $Command == 
			echo "<option value='Save Item to DB'>Save Item to DB</option>";
			echo "<option value='Continue Unchanged'>Continue Unchanged</option>";
	} else {
		echo "<option value='Add Item to DB'>Add Item to DB</option>";
		echo "<option value='Edit Item in DB'>Edit Item in DB</option>";
		echo "<option value='Delete Item in DB'>Delete Item in DB</option>";
	}
	echo "</optgroup>";
	echo "</optgroup>";
	echo "<optgroup label=\"List Operations\">";
	echo "<option value='Edit Menus'>Edit Menus</option>";
	echo "</optgroup>";
	echo "</select>";
}

function edit_menu_command() {
	echo "<select onchange='updateMenu();' name='edit_menu_command'>";	
	echo "<optgroup label='Menu Editing'>";
	echo "<option value='Menu Edit Commands'>Menu Edit Commands</option>";
	echo "<option value='Add Menu'>Add Menu</option>";
	echo "<option value='Rename Menu'>Rename Menu</option>";
	echo "<option value='Move Menu After'>Move Menu After</option>";
	echo "</optgroup>";
	echo "<optgroup label=\"Menu Deletion\">";
	echo "<option value='Delete Menu'>Delete Menu</option>";
	echo "</optgroup>";
	echo "<optgroup label=\"Exit Here\">";
	echo "<option value='Exit Edit Menus'>Exit Edit Menus</option>";
	echo "</optgroup>";
	echo "</select>";
}

This also adds selections and some decorations to group choices in the selects in such a way that is easy to grasp the function. The commands for edit menu are simple enough that I didn't feel the need to pass in the post, that may change.
48 posted on 02/22/2012 6:04:55 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C JavaScript primer)
[ Post Reply | Private Reply | To 47 | View Replies]

To: RobertClark; cuban leaf; InterceptPoint; smith288; 21stCenturion; sand88; Haddit; 2ndamendmentpa; ..
Lovely, another bug in the previous post. Replace the first echo line in the function select_command() with echo "<select onchange='updateMenu();' name='command'>"; It doesn't seem to matter how long I look at this stuff, something is always wrong with the post. Here I missed part of the edit. I have multiple copies of the same code, the code that actually runs on my machine, and the 'neutered' code that will actually display on a web page rather than execute. I try to keep them "the same", but they aren't.

New Connect:

The connect.php has been reworked a bit to accommodate auto-magical db and table creation. This involved dividing connect.php in twain adding a file called ~www/tutorial/include/sql_password.php which contains:

<?php
// this is an in-line and the only place where the db username
// and password should appear.
$db = "tutorial_db";
$link = mysql_connect('localhost', 'admin', 'password');
?>
And copy the following into ~www/tutorial/include/connect.php
<?php
// this is an in-line
$debug = false;
include "include/sql_password.php";
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
if($debug == true) {echo 'Connected to MySQL successfully<br>';}
mysql_select_db($db);
?>
There is a bit of a hazard here in the $debug = false; assignment. Since this is an include and not a function the variable $debug is in scope anywhere after you drop in the connect.php include. This means if you do something like this:
$debug = true;
include "include/connect.php";
You might think that $debug == true, but you would be wrong. You might want to remove debugging entirely from the connect but hang on for a bit. We want all the debugging turned on for the moment so we can see how the bits are flying. Maybe just removing the assign in the connect will get us what we want. The important thing here is to be come aware of the scope of variables. This is covered in exquisite detail in the references I have previously pointed out. You need to know this, Buckaroo.

Now we want to replace the function check_tables() in ~www/tutorial/include/check_tables.php with:

function check_tables() {
// Usage without mysql_list_dbs() deprecated
	include 'include/sql_password.php'; // connects us to db
	if (!$link) {die('Could not connect: ' . mysql_error());}
	mysql_select_db($db);
	$debug = false;
	if($debug == true){echo 'In check_tables() Connected SQL link='.$link.'<br />';}
	$res = mysql_query("SHOW DATABASES");
	if($debug == true){echo "checking database...<br />";}
	$present = false;
	while ($row = mysql_fetch_assoc($res)) {
		if($debug == true){echo $row['Database']." ";}
		if($row['Database'] == $db){$present = true;}
	}
	if($debug == true){echo "<br />";}
	if($present == false) { // db not present, creat it.
		echo "Database ".$db." not present. Creating...<br />";
		$sql = 'CREATE DATABASE '.$db;
		if (mysql_query($sql, $link)) {
			echo "Database ".$db." created successfully<br />";
		} else {
			echo 'Error creating '.$db.': ' . mysql_error() . "<br />";
			die(mysql_error()); // die a horrible death, can't go on...
		}
	}
	mysql_select_db($db);
	$sql = "SHOW TABLES FROM ".$db;
	$result = mysql_query($sql);
	if (!$result) {
		echo "DB Error, could not list tables\n";
		echo 'MySQL Error: ' . mysql_error();
		exit; // die a horrible death, can't go on...
	}
	$items_present = false; // flags for table creation
	$item_menus_present = false;
	while ($row = mysql_fetch_row($result)) { // paw through the results
		if($debug == true){echo "Table: {$row[0]} <br />";}
		//echo "Table: ."$row[0]." ";
		if($row[0] == 'items') {$items_present = true;}
		if($row[0] == 'item_menus') {$item_menus_present = true;}
	}
	mysql_free_result($result); //return some memory
	if($items_present == false) { //make items table
		create_items_table();
	}
	if($item_menus_present == false) { //make item_menus table
		create_item_menus_table();
	}
}

The above code uses the new connect formula. The actual table creation stays the same. One of the things to notice is that the user will be informed whenever a db or table is created, no mater the state of $debug. Another thing is that if we fail to make the db or the table for some reason we die a horrible death. The screen goes blank and truth is hard to see. View Source is your friend at that point, it will often show you just where you went awry. echo Statements are useful too.
49 posted on 02/22/2012 8:36:23 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C JavaScript primer)
[ Post Reply | Private Reply | To 48 | View Replies]

To: RobertClark; cuban leaf; InterceptPoint; smith288; 21stCenturion; sand88; Haddit; 2ndamendmentpa; ..

Edit Menu:

Now we need to add the two new files. The first is edit_menu.php I am a bit torn about this. The object (noun) part of this is pretty small and the only really new elements are the function htmlspecialchars_decode() and the function select_generic() which is where we have been trying to get. The verb part though, I could have stripped out everything but the functionality of 'Add Menu', but then I'd have to put it right back in. Sigh.

Copy all of this into: ~www/tutorial/include/edit_menu.php

<?php 
/*	This function provides for the editing of the Item, Ingredient, and Meal
 * 	menus.
 * 	copyright 2011 by mumble all rights reserved
 *	file: edit_menu.php
 *	
 * 	2011/10/07 - initial working cut
 * 	2011/10/14 - update to current UI - working
* 	2012/02/21 - modified for tutorial - working
 * 
 * 	This function edits the menus created by the select_generic() objects which are used to 
 * 	look into the database.
*/

function edit_menu($_POST) 
{
	$New_menu = htmlspecialchars_decode($_POST["new_menu"]);
	$Current_menu = $_POST["menu_current"];
	$EM_command = $_POST["edit_menu_command"];
	$New_menu = htmlspecialchars_decode($_POST["new_menu"]);  // used in edit_menus as a source (is a textfield)
	
	$debug = false; if($debug) {echo "<br />In edit_menu() post_length=".count($_POST)."<br />";}	 	 
	if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}} 	
		
	if ($Current_menu == '') {$Current_menu = '0';}

	// create a selector for which menu to edit
	// this probably ought to be a function but so far this is the
	// only time I have to do this one.
	echo "<select onchange='updateMenu()' name='menu_current'>";
	if($Current_menu == '0') {echo "<option selected='selected' value='0'>Items</option>";}
	else {echo "<option value='0'>Items</option>";}
	echo "</select>";
		if($Current_menu == '0') {select_generic('item',$_POST,'menu_only','_source');}
	echo "<input id='em_text' type='text' size='32' maxlength='64' value='".$New_menu."' name='new_menu'><br /> Destination: ";
		if($Current_menu == '0') {select_generic('item',$_POST,'menu_only','_destination');}
	echo "<br>Menu Commands: ";
	edit_menu_command();
	echo "<input id='em_exists' type='hidden' value='exists' name='edit_menu_exists'>";

}
// end of the function, the rest is included as the grammar of the function

// we begin with a little general housekeeping.
// set the value of the data bases being worked with
if ($Current_menu == '0') {$menu_db = 'item_menus';}

// before we actually try to execute any commands we see if the inputs are even vaguely reasonable.
if ($EM_command == 'Rename Menu' || $EM_command == 'Add Menu') {  // check for good inputs 
	if($New_menu == "") {
		$Error = "There must be text in the textfield to ".$EM_command; 
		$EM_command = "Menu Edit Commands"; // don't want to return here
	}
}
// fix up the global menu vars to point to the right menu set
if($Current_menu == '0') {$Menu_source = $_POST['item_menu_source'];$Menu_destination = $_POST['item_menu_destination'];}
/*
if($Current_menu == '1') {$Menu_source = $_POST['ingredient_menu_source'];$Menu_destination = $_POST['ingredient_menu_destination'];}
if($Current_menu == '2') {$Menu_source = $_POST['food_menu_source'];$Menu_destination = $_POST['food_menu_destination'];}
*/
//and now we should be ready to actually execute some commands

if ($EM_command == 'Rename Menu') {  // rename menu
	$debug = false;
	include 'include/connect.php';
	$query_str = "UPDATE ".$menu_db." SET name='".$New_menu."' WHERE index0='".$Menu_source."'";
	if($debug) {echo $query_str."<br>";}
	if(!$debug) {$result = mysql_query($query_str) or die(mysql_error());}
	if(!$debug) {$Feedback = "Menu: ".$Menu_source." named ".$New_menu." saved to DB.";}
	if($debug) {echo "Menu: ".$Menu_source." named ".$New_menu." NOT saved to DB.***debugging in edit_menu_rename***<br>";}
}

if ($EM_command == 'Add Menu') {  // add menu
	$debug = true;
	include 'include/connect.php';
	$query_str = "SELECT MAX(index0) as index0 FROM ".$menu_db."";
	if($debug) {echo $query_str."<br>";}
	// SELECT doesn't need a debug shield
	$result = mysql_query($query_str) or die(mysql_error());
	$row = mysql_fetch_array( $result );
	$new_index = $row['index0'] + 1 ;  // next new index
	if($debug) {echo "new index = ".$new_index."<br>";}
	$query_str = "INSERT INTO ".$menu_db." 
	(index0, name) 
	VALUES('".$new_index."', '".$New_menu."' )";
	if($debug) {echo $query_str."<br>";}
	if(!$debug) {$result = mysql_query($query_str) or die(mysql_error());}
	if(!$debug) {$Feedback = "Menu: ".$New_menu." at position ".$new_index." saved to DB.";}
	if($debug) {echo "Menu: ".$New_menu." at position ".$new_index." NOT saved to DB.***debugging in edit_menu_add***<br>";}
}

if ($EM_command == 'Delete Menu') {  // delete menu
	$debug = false;
	if($debug) {echo "Menu src = ".$Menu_source." Menu dst = ".$Menu_destination."<br>";}
	if ($Menu_source == $Menu_destination) { 
		$Error = "Source and Destination menus must be different.<br> Source menu contents get copied to the destination menu.<br> Delete Failed!</p><br>";
	} else {
		include 'include/connect.php';
		$query_str = "SELECT name FROM ".$menu_db." WHERE index0='".$Menu_source."'";
		if($debug) {echo $query_str."<br>";}
		// SELECT needs no debug shield
		$result = mysql_query($query_str) or die(mysql_error());
		$row = mysql_fetch_array( $result );
		$sname = $row['name'];  // source name
		$query_str = "SELECT name FROM ".$menu_db." WHERE index0='".$Menu_destination."'";
		$result = mysql_query($query_str) or die(mysql_error());
		$row = mysql_fetch_array( $result );
		$dname = $row['name'];  // destination name
		$query_str = "SELECT MAX(index0) as index0 FROM ".$menu_db."";
		$result = mysql_query($query_str) or die(mysql_error());
		$row = mysql_fetch_array( $result );
		$max_index = $row['index0'];  // biggest index before delete
		if($debug) {echo "max index = ".$max_index."<br>";}
		$query_str = "DELETE FROM ".$menu_db." WHERE index0='".$Menu_source."'";
		if($debug) {echo $query_str."<br>";}
		$result = mysql_query($query_str) or die(mysql_error());
		//echo "Menu: ".$sname." at position ".$Menu_source." deleted from DB.<br>";
		$Feedback = "Menu: ".$sname." at position ".$Menu_source." deleted from DB.<br>";
		$mv_index = $Menu_source;
		while ($mv_index <= $max_index) {
			//echo "working index = ".$mv_index." max = ".$max_index."<br>";
			$Feedback = "working index = ".$mv_index." max = ".$max_index."<br>";
			$query_str = "UPDATE ".$menu_db." SET index0='".$mv_index."' WHERE index0='".($mv_index + 1)."'";
			if($debug) {echo $query_str."<br>";}
			$result = mysql_query($query_str) or die(mysql_error());
			if($mv_index == $Menu_source) {
				//echo "Moving ".$thing_db."  on Menu ".$sname." to ".$dname."<br>";
				$Feedback = "Moving ".$thing_db."  on Menu ".$sname." to ".$dname."<br>";
				$query_str = "UPDATE ".$thing_db." SET menus='".$Menu_destination."' WHERE menus='".$Menu_source."'";
				if($debug) {echo $query_str."<br>";}
				$result = mysql_query($query_str) or die(mysql_error());
				//echo "".$thing_db."  moved from ".$sname." to ".$dname."<br>";
				$Feedback = "".$thing_db."  moved from ".$sname." to ".$dname."<br>";
			} else {
				echo "Adjusting menu ".$mv_index." in ".$thing_db."  db...<br>";
				$Feedback = "Adjusting menu ".$mv_index." in ".$thing_db."  db...<br>";
				$query_str = "UPDATE ".$thing_db."  SET menus='".($mv_index-1)."' WHERE menus='".$mv_index."'";
				if($debug) {echo $query_str."<br>";}
				$result = mysql_query($query_str) or die(mysql_error());
			}	
			$mv_index++;
		}
	}
}

if ($EM_command == 'Move Menu After') { // check for valid inputs to move after 
	$debug = false;
	//if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}} 	
	if($debug) {echo "Menu_source = ".$Menu_source." Menu_destination = ".$Menu_destination."<br>";}
	include 'include/connect.php';
	$query_str = "SELECT name FROM ".$menu_db." WHERE index0='".$Menu_source."'";
	$result = mysql_query($query_str) or die(mysql_error());
	$row = mysql_fetch_array( $result );
	$sname = $row['name'];  // source name
	$query_str = "SELECT name FROM ".$menu_db." WHERE index0='".$Menu_destination."'";
	$result = mysql_query($query_str) or die(mysql_error());
	$row = mysql_fetch_array( $result );
	$dname = $row['name'];  // destination name
	if($Menu_source == $Menu_destination) { // 
		//echo "<p class='ex'>Can not move ".$sname." after ".$dname."</p><br>";
		$Error = "Move Menu After: Can not move ".$sname." after ".$dname." ";
		$EM_command = 'Menu Edit Commands'; // make command go away.
	}
}
if ($EM_command == 'Move Menu After') {  // move source menu after destination menu
	include 'include/connect.php';
	$query_str = "SELECT name FROM ".$menu_db." WHERE index0='".$Menu_source."'";
	$result = mysql_query($query_str) or die(mysql_error());
	$row = mysql_fetch_array( $result );
	$sname = $row['name'];  // source name
	$query_str = "SELECT name FROM ".$menu_db." WHERE index0='".$Menu_destination."'";
	$result = mysql_query($query_str) or die(mysql_error());
	$row = mysql_fetch_array( $result );
	$dname = $row['name'];  // destination name
	if($Menu_source == $Menu_destination) { // this should never execute
		//echo "<p class='ex'>Can not move ".$sname." after ".$dname."</p><br>";
		$Error = "Can not move ".$sname." after ".$dname." ";
		$EM_command = 'Menu Edit Commands'; // make command go away.
	}
	//echo "Moving menu item ".$sname." after ".$dname."<br>";
	$Feedback = "Moving menu item ".$sname." after ".$dname."<br>";
	// get the index one larger than is being used for temporary storage
	$query_str = "SELECT MAX(index0) as index0 FROM ".$menu_db."";
	$result = mysql_query($query_str) or die(mysql_error());
	$row = mysql_fetch_array( $result );
	$max_index = $row['index0'];  // biggest index 
	if($debug) {echo "max index = ".$max_index."<br>";}
	$mv_index = $Menu_source;
	if($debug) {echo "working index = ".$mv_index." max = ".$max_index."<br>";}

	if($Menu_source > $Menu_destination) { //moving source up, do this
		// move source to max+1  
		$query_str = "UPDATE ".$menu_db." SET index0='".($max_index + 1)."' WHERE index0='".($mv_index)."'";
		if($debug) {echo $query_str."<br>";}
		$result = mysql_query($query_str) or die(mysql_error());
		$query_str = "UPDATE ".$thing_db."  SET menus='".($max_index + 1)."' WHERE menus='".($mv_index)."'";
		if($debug) {echo $query_str."<br>";}
		$result = mysql_query($query_str) or die(mysql_error());
		
		// shift everyone from source-1 to dest up one
		for($mv_index = $Menu_source-1; $mv_index > $Menu_destination; $mv_index--) {
			$query_str = "UPDATE ".$menu_db." SET index0='".($mv_index+1)."' WHERE index0='".($mv_index)."'";
			if($debug) {echo $query_str."<br>";}
			$result = mysql_query($query_str) or die(mysql_error());
			$query_str = "UPDATE ".$thing_db."  SET menus='".($mv_index+1)."' WHERE menus='".($mv_index)."'";
			if($debug) {echo $query_str."<br>";}
			$result = mysql_query($query_str) or die(mysql_error());
		}
		// move max+1 to dest+1
		$query_str = "UPDATE ".$menu_db." SET index0='".($Menu_destination + 1)."' WHERE index0='".($max_index + 1)."'";
		if($debug) {echo $query_str."<br>";}
		$result = mysql_query($query_str) or die(mysql_error());
		$query_str = "UPDATE ".$thing_db."  SET menus='".($Menu_destination + 1)."' WHERE menus='".($max_index + 1)."'";
		if($debug) {echo $query_str."<br>";}
		$result = mysql_query($query_str) or die(mysql_error());
	} else {  // Moving src down the menu, do this
		// move source to max+1  
		$query_str = "UPDATE ".$menu_db." SET index0='".($max_index + 1)."' WHERE index0='".($mv_index)."'";
		if($debug) {echo $query_str."<br>";}
		$result = mysql_query($query_str) or die(mysql_error());
		$query_str = "UPDATE ".$thing_db."  SET menus='".($max_index + 1)."' WHERE menus='".($mv_index)."'";
		if($debug) {echo $query_str."<br>";}	
		$result = mysql_query($query_str) or die(mysql_error());
		
		// shift everyone from source+1 to dest up one
		for($mv_index = $Menu_source+1; $mv_index <= $Menu_destination; $mv_index++) {
			$query_str = "UPDATE ".$menu_db." SET index0='".($mv_index-1)."' WHERE index0='".($mv_index)."'";
			if($debug) {echo $query_str."<br>";}
			$result = mysql_query($query_str) or die(mysql_error());
			$query_str = "UPDATE ".$thing_db."  SET menus='".($mv_index-1)."' WHERE menus='".($mv_index)."'";
			if($debug) {echo $query_str."<br>";}
			$result = mysql_query($query_str) or die(mysql_error());
		}
		// move max+1 to dest
		$query_str = "UPDATE ".$menu_db." SET index0='".($Menu_destination)."' WHERE index0='".($max_index + 1)."'";
		if($debug) {echo $query_str."<br>";}
		$result = mysql_query($query_str) or die(mysql_error());
		$query_str = "UPDATE ".$thing_db."  SET menus='".($Menu_destination)."' WHERE menus='".($max_index + 1)."'";
		if($debug) {echo $query_str."<br>";}	
		$result = mysql_query($query_str) or die(mysql_error());
	}
}
	
?>
This is an interesting file. A lot of the complexity of the verb part has to do with deleting menus (the items need to be moved to a destination menu) and changing the ordering of menus. I chose to order the menus by the value of index0 which implies that as the index0 for a particular menu item, say 'dairy' changes from 4 to 0 to put it at the top of the menu, then all of the items that reference the menus pointed to by 0 or 4 need to be reworked. This is probably not so great. We really need probably yet another table that actually keeps the ordering. We'll try to remember to fix this.
50 posted on 02/22/2012 9:01:21 AM PST by Mycroft Holmes (<= Mash name for HTML Xampp PHP C JavaScript primer)
[ Post Reply | Private Reply | To 49 | View Replies]


Navigation: use the links below to view more comments.
first 1-5051-56 next last

Disclaimer: Opinions posted on Free Republic are those of the individual posters and do not necessarily represent the opinion of Free Republic or its management. All materials posted herein are protected by copyright law and the exemption for fair use of copyrighted works.

Free Republic
Browse · Search
Bloggers & Personal
Topics · Post Article

FreeRepublic, LLC, PO BOX 9771, FRESNO, CA 93794
FreeRepublic.com is powered by software copyright 2000-2008 John Robinson