PHP Knowledge Base Update -- June 29th, 1999

From: Date: Wed, 30 Jun 1999 08:45:59 +0000
Subject: PHP Knowledge Base Update -- June 29th, 1999
Groups: php.kb 
Request: Send a blank email to php-kb+get-3@lists.php.net to get a copy of this message
There are a few answers that I think may need some work today. Could kind, helpful people check and perhaps edit them in the knowledge base for me? In particular: - counter question could do with a solution - adding a C code function answer is very insufficient Cheers, Nathan ------------------------------------------------------------ Do I need to use locking when keeping a counter in a file? Why does my counter keep resetting to zero? Will I have concurrency problems with my counter? http://e-gineer.com/phpkb/view.phtml/qid/245 ------------------------------------------------------------ M.Brands You need to be aware of concurrency problems when writing a counter. If several people visit your page at the same time, things can go wrong. Here is a short example from the mailing list which explains some of the possible problems. (Assume the counterfile exists and contains 6) process 1 process 2 ---------------------------------------------------------------------- $counterFile = "..."; if (!file_exists($counterFile)) $fp = fopen($counterFile,rw); $num = fgets($fp,20); $num += 1; print "$num"; exec("rm -rf $counterFile"); $counterFile = "..."; if (!file_exists($counterFile)) { exec("echo $num > $counterFile"); exec("echo 1 > $counterFile"); } $fp = fopen($counterFile,rw); $num = fgets($fp,20); $num += 1; print "$num"; exec("rm -rf $counterFile"); exec("echo $num > $counterFile"); Each line represends one little step in time. I'm assume you machine only has one cpu, so that's why only one line of code is executed at a time. (In reality, lines may be interrupted in the middle of doing something, not conveniently after they've finished.) Process 1 encounters a valid file, reads it, inreases the number and erases the file. By this time, process 2 tries to read it to. After that, process 1 creates a new file with the value 7 in it. Process 1 is now finished. Process 2, having failed to open the counterfile, creates a new one (overwrites actually) with the value 1. It then reads the file, increments the number (now 2) and erases the value. Then, a new file with the value 2 is created. So, after both process 1 and 2 have finished, the counter contains 2 and not the expected 8! This may seem far fetched, but if you have enough processes trying to update counter.text at the same time, something like this is going to happen. So, to build a better mousetrap, you need to make sure only one process can update counter.text at one. Concurrent reading is not a problem, as long as a read cannot combined with a write. There are several ways to solve this common problem, such as using a semaphore or locking counter.text with flock. (There are more ways.) Also, you should try not to use the exec's. One, because it's slow, and two, because it's safer to do as much as possible from PHP. (If you did it completely in PHP, you might not have noticed this problem so soon, although it would occur if you waited long enough.) On, and you might want to leave out the 'rm -rf' bit, since it doesn't do anything useful. Even worse, it causes more diskaccess than simply overwriting the content of the counter. If you were to remove the rm, this script would already run a lot better (although it would still be faulty). Btw. you may want to use 0 as a starting value for your counter, since you're starting to count at 2 and not 1 visitor. But only an complete ass (like myself ;) would complain about that... ------------------------------------------------------------ Why does mcrypt add NULLs to my string before encrypting it? http://e-gineer.com/phpkb/view.phtml/qid/248 ------------------------------------------------------------ Sascha Schumann Triple DES (and all other algorithms provided by mcrypt) are block algorithms. That means that most of them work only on fixed size blocks. Triple DES takes 64 bits per block. It simply cannot work on fewer data, so it has to fill up the buffer. ------------------------------------------------------------ How can I read a line at random from a file? http://e-gineer.com/phpkb/view.phtml/qid/249 ------------------------------------------------------------ Fred Isler, Colin Viebrock, Ariel There are a few ways read a line from a file at random. If you don't want to lond the file into memory, do it in two passes, count the lines in the file (unix command wc is probably fastest for it, popen it) then pick an random number, and find that line. You can use head, or tail for it, or do it in php. If you can load it into memory, then use file to get an array, count the array, and pick an element. Here is some code to do this: // get the number of lines in the file $fileLines = file("file.txt"); $i = count($fileLines); // seed and pick a random number between 0 and $i: srand((double)microtime()*1000000); $idx = rand(0,$i); // print your random line: print ("$fileLines[$idx]"); ------------------------------------------------------------ How can I write a forum in PHP? What database schema should I use to implement discussion lists? Where can I find more information about building a bulletin board? http://e-gineer.com/phpkb/view.phtml/qid/250 ------------------------------------------------------------ Many, many helpful people There are a number of different techniques that can be used to build a threaded discussion list. Rather than choose one or outline them all here it is better to point you at a relevant thread in the mailing list archives: http://www.progressive-comp.com/Lists/?l=php3-general&m=93062134631409 Unless you really want to build one yourself you are probably much better off using one of the existing open source systems. A list of PHP projects that you can utilize is available at: http://www.php.net/projects.php3 In this case, Phorum may be of particular interest: http://www.phorum.org ------------------------------------------------------------ I have added a function to file.c and recompiled. Why doesn't it exist in PHP? http://e-gineer.com/phpkb/view.phtml/qid/253 ------------------------------------------------------------ Chad Did you add it to the function list at the top of the file? It has to make itself known to php or it is just text in a file. ------------------------------------------------------------ How can I create a column in MySQL that auto increments? How can I insert data into MySQL with an automatic unique ID? http://e-gineer.com/phpkb/view.phtml/qid/254 ------------------------------------------------------------ Richard Seymour, Christophe LAUER In MySQL you just create a column of type integer and give it the AUTO_INCREMENT attribute. create table foo ( bar integer auto_increment ); http://www.mysql.com/Manual_chapter/manual_Reference.html#CREATE_TABLE ------------------------------------------------------------ How can I create a column in Postgres that auto increments? How can I insert data into Postgres with an automatic unique ID? http://e-gineer.com/phpkb/view.phtml/qid/256 ------------------------------------------------------------ Christophe LAUER, DeJuan Jackson PostgreSQL uses the concept of 'sequences', just like Oracle does. Try: CREATE SEQUENCE name-of-sequence START startnumber; ie: CREATE SEQUENCE jobsequence START 123456; gets you a named autoincrementing field. You can then get the next value and automatically increment the sequence using the following: SELECT NEXTVAL ('name-of-sequence'); To do auto incrementing columns the keyword in PostgreSQL is SERIAL. For example: create table foo (bar SERIAL PRIMARY KEY, other_data TEXT); insert into foo (other_data) values ('This is a test'); select * form foo; --- foo.bar should have been set to 1 It is currently implemented as a sequence, so the above create table statement is equivelent to: create sequence seq_foo_bar; create table foo ( bar INT PRIMARY KEY DEFAULT nextval('seq_foo_bar'), other_data TEXT); ------------------------------------------------------------ How can I stop users on my web server from using system()? How can I setup PHP for safe scripting only? http://e-gineer.com/phpkb/view.phtml/qid/258 ------------------------------------------------------------ Rasmus Lerdorf, Chad Turn on safe-mode and the system()-like functions can only execute whatever programs are located in the designated safe-mode-exec-dir. If you point that to an empty dir people won't be able to execute anything. http://www.php.net/manual/config-security.php3 http://www.php.net/manual/phpfi2.html#safemode ------------------------------------------------------------ How can I sort results by a certain column? http://e-gineer.com/phpkb/view.phtml/qid/260 ------------------------------------------------------------ Steve Lianoglou Let's say the column you want to sort by is "user_num". SELECT * FROM table_name WHERE whatever='whathaveyou' ORDER BY user_num ASC This sorts the rows from smallest to highest, change the ASC to DESC and you get from highest to lowest... ------------------------------------------------------------ Can I use PHP and SSI in the same document? http://e-gineer.com/phpkb/view.phtml/qid/261 ------------------------------------------------------------ Jim Winstead If you are running PHP as an Apache module, check out the virtual() function. You cannot mix SSI and PHP content in the same document. http://www.php.net/manual/function.virtual.php3 ------------------------------------------------------------ How are strings constructed in PHP? What quotes can I use to make strings in PHP? Can I include a variable reference in a string? http://e-gineer.com/phpkb/view.phtml/qid/262 ------------------------------------------------------------ Nathan Wallace, Rasmus Lerdorf Basically a string in PHP is anything between matching quotes: 'I am a string in single quotes' "I am a string in double quotes" You can include quotes inside the string that do not match the quote that started the string. So you can include single quotes in a string that was started (and finishes) with double quotes. So, these will work: "I am a 'single quote string' inside a double quote string" 'I am a "double quote string" inside a double quote string' PHP thinks it has reached the end of the string as soon as it sees that matching quote. So the example "Why doesn't "this" work?" is actually seen by PHP as being "Why doesn't " - a string this - crap letters that PHP doesn't recognize " work?" - a string It is also helpful to know that you can include a quote character of the same type inside a string if you escape it. The escape tells PHP that the next character should just be used as part of the string. For example: "Why doesn't \"this\" work?" is a single string that contains double quote characters. Double quote strings and single quote strings are treated differently by PHP. Double quote strings are interpreted by PHP while single quotes strings are treated exactly as is. For example: $foo = 2; echo "foo is $foo"; // this prints: foo is 2 echo 'foo is $foo'; // this prints: foo is $foo So you should use double quote strings when you want to include a variable. Note however that PHP only supports simple constructs inside quoted strings, so this will work: "$a[$i]" But this won't: "$a[$i][$j]" And as such it is usually advisable to simply pop out of the string when you are doing anything more complex than a simple variable substitution. ie. "some string ". $a[$i][$j] . " more text" The last thing to know about strings is that you can join them together easily using the concatenate operator (.). Here is an example: $var = "crappy ending"; echo "this " . 'is an' . ' example ' . "with a " . $variable; ------------------------------------------------------------ How do I pass a variable to the compare() function when calling it from usort? http://e-gineer.com/phpkb/view.phtml/qid/268 ------------------------------------------------------------ Shawn Bernard, Colin Viebrock You can learn more about usort() here: http://www.php.net/manual/function.usort.php3 An example of when you might like to pass a variable to the compare function is if you wanted to sort by a difference array column. You can't really pass a variable to the compare function. The kludge is to set up a global variable, and set that before calling usort(): function compare() { global $USORT_COLUMN; if ($a[$USORT_COLUMN] == $b[$USORT_COLUMN]) { return 0; } else { return ($a[$USORT_COLUMN] > $b[$USORT_COLUMN]) ? 1 : -1 ; } } $USORT_COLUMN = "name"; usort($array, "compare"); ------------------------------------------------------------ How can I get the ordinal for a number (eg: st for 1st, th for 24th) ? http://e-gineer.com/phpkb/view.phtml/qid/269 ------------------------------------------------------------ Colin Viebrock You can use the date() function in many cases to do this: http://www.php.net/manual/function.date.php3 If you just want to do it for a number in general then try this function: function ordinal($num) { if ($num>10 && $num<20) { $r="th"; } else { switch ($num%10) { case 1: $r="st"; break; case 2: $r="nd"; break; case 3: $r="rd"; break; default: $r="th"; break; } } return $r; }

« previous php.kb (#3) next »