Share the Love! Free Programming eBooks

Leave a comment Standard

GoalKicker.com is giving away these free programming books and I thought I would share the love for anyone who hasn’t seen them yet. There are more available from their website but these are the ones I was most interested in. Enjoy!

Screen Shot 2018-01-31 at 4.26.46 PM

Screen Shot 2018-01-31 at 4.26.54 PM

Screen Shot 2018-01-31 at 4.27.01 PM

Screen Shot 2018-01-31 at 4.27.11 PM

Screen Shot 2018-01-31 at 4.27.18 PM

Screen Shot 2018-01-31 at 4.27.24 PM

Screen Shot 2018-01-31 at 4.27.37 PM

Screen Shot 2018-01-31 at 4.27.44 PM

Advertisements

PHP Tutorial: Cookies vs Sessions

Leave a comment Standard

If you’re interested in making any kind of web based application then learning how to use sessions and cookies is a must. Many people don’t understand how these work and how they different from each other, and why you would choose to use one versus the other. So put on your thinking caps and let’s get started.

What is a Cookie?

A cookie is a data file that’s written to your browser’s localStorage with data you want to keep track of for a user. So what’s localStorage? The best real world analogy I can give you is to think about it like a 3 ring binder that you can add, update and remove files from. In this example a cookie would be a piece of paper in your 3 ring binder.

How Do Cookies Work?

When you navigate around the Internet your browser is constantly sending and receiving information from the websites you want to access. These are called HTTP headers. HTTP headers contain important information about the requests and responses being sent back and forth from a browser to a server. When someone has an active cookie from your website in their browser’s localStorage it automatically passed in the HTTP headers to the site of origin in the $_COOKIE variable of PHP. Since headers have to be sent before any output setting a cookie must always go at the top of your file.

How do I Create a Cookie?

<?php
$name = "myCookie";
$value = "hello world!";
$expires = time() + 60 * 60 * 24; //1 day
$path = "/";
$domain = "yourwebsite.com";
$secure = 0; //0 for false, 1 for true
$httponly = 0; //0 for false, 1 for true

//let's tell the browser to create our cookie
setcookie($name, $value, $expires, $path, $domain, $secure, $httponly);

//let's make a cookie array too
setcookie("cookieArray[0]", "A");
setcookie("cookieArray[1]", "B");
setcookie("cookieArray[2]", "C");

//you must refresh the page before your new cookies are visible
echo "refresh the page to see your cookies: " . $_COOKIE['myCookie'];

//this will loop through and display your array cookies
foreach ($_COOKIE['cookieArray'] as $key => $value)
{
 echo "<br/>array cookie $key => $value";
}
?>

In this first example we’ve created a cookie called myCookie that stores the value of hello world! In order to see something printed on the screen you must refresh the page. This is because the HTTP headers must be sent from the server to your browser and then from your browser back to the server before they show up in the $_COOKIE variable.

Expires is an optional value that tells the browser how long to keep our cookie before it deletes it. By using the current time() and then adding on an extra 24 hours our cookie will only stick around for a day before the browser deletes it. So in this example if your cookie is created at today at 12noon EST it will expire tomorrow at 12noon EST. When your cookie is expired you’ll have to create a new one if you want to store your $value again.

Next we’ve set a path for our cookie. This is also an optional field and will default to / if you don’t give it a value. This tells the browser where this cookie will be available. So let’s say your website is http://yourwebsite.com and you only want this cookie to be available when you’re inside the http://yourwebsite.com/users/ section or your website. If that were the case we’d change the path to /users/ and then our cookie will only be accessible when we’re in the users directory. When we leave the path at / it means our cookie is available on any part of the domain we’ve given it.

The domain of your cookie is optional. If you don’t provide a domain for your cookie it may default to your current domain name. You can also set your domain name to a subdomain. So for instance, if we had a subdomain of http://users.yourwebsite.com we would set our domain to users.yourwebsite.com then our cookie would only be available when we’re inside our users subdomain.

The secure section of the cookie is optional and should only be set to true if you’re using https.

The httponly is optional and tells newer browser to only make your cookie accessible in the HTTP header. Not all browsers support this functionality, however it has been added to help prevent against cross site scripting (XSS) attacks.

How do I Access Cookie Values?

<?php
//this shows you a single cookie
echo $_COOKIE['myCookie'];

//this shows you all available cookies
print_r($_COOKIE);
?>

Once you have a cookie set you can access it by using the $_COOKIE variable in PHP and then pass it the name of the cookie you want to access or you can use a print_r() call to print all available cookies.

How do I Delete a Cookie?

<?php
//unset the single cookie
unset($_COOKIE['myCookie']);

//unset the array cookies
unset($_COOKIE['cookieArray']);

//update the cookie's expiration date to sometime in the past
setcookie("myCookie", false, time()-1);
setcookie("cookieArray[0]", false, time()-1);
setcookie("cookieArray[1]", false, time()-1);
setcookie("cookieArray[2]", false, time()-1);
?>

Sometimes you want to remove a cookie. There are two different ways to do this. The first is to unset() the cookie and the second is to update the expiration date to a time in the past which will force your browser to remove it. Just like when we set a cookie, you must refresh the page before you will see that your cookie has been removed.

How do I Edit a Cookie?

<?php
//to edit a single cookie value
setcookie("myCookie", "My new value");

//to edit a cookie array
setcookie("cookieArray[0]", "one");
setcookie("cookieArray[1]", "two");
setcookie("cookieArray[2]", "three");
?>

As long as the cookie exists all you need to do is set the cookie with the same name and give it a different value. You won’t see that the values in your cookie have changed until you refresh the page since cookies are sent in an HTTP header.

Cookie Trouble Shooting

  • If you’re having trouble setting a cookie and you’re getting a headers already sent error then you have some kind of output (text, spaces, html, images, etc) that are being displayed to the screen before you’re calling your setcookie() function.
  • Once you’ve added, edited or deleted a cookie you must refresh the page before you can see that your changes have taken place. This is because cookies are sent in HTTP headers.
  • Cookies must be deleted with the exact same parameters as they were set with.
  • Cookie arrays are stored as one file for each index in the array. For this reason large arrays are not recommended. If you need to store lots of data in a cookie it’s more useful to use a single cooke and concatenate the values with implode() then retrieve the data  using explode().
  • If one of the values in your cookie resolves to a false your cookie will be deleted. For this reason you shouldn’t use true/false booleans but instead use 0 and 1.
  • It is not recommended to serialize your cookie values as this can cause security holes.
  • If the user’s browser has cookies disabled or will not allow cookies to be stored then you won’t be able to create a cookie in their localStorage. This problem gave rise to the creation of sessions.

What Is a Session?

Sessions are the best solution for short term storage of data and dealing with user’s browsers that don’t allow the creation of cookies. Sessions will attempt to create a cookie and if the attempt fails will instead propagate via the URL. However a session will only persist over the duration of a user’s visit on your website. Once the user leaves your site the cookie (if one was created) is deleted so there is no persistent information retained about the user in the browser’s localStorage once they’ve left your website.

How do I Create a Session?

<?php
//you have to start the sessions before you can use them
session_start();

//set a single session value
$_SESSION['mySession'] = "hello world!";

//set an array in a session
$_SESSION['myArray'] = new array('A', 'B', 'C');

//set an object in a session
$_SESSION['myObject'] = new myObject();
//this tells php your done making changes to the session
session_write_close();

//session values are immediately available
echo $_SESSION['mySession'];
print_r($_SESSION['myArray']);
print_r($_SESSION['myObject']);
?>

All sessions must be started with the session_start() call unless you have them set to auto start in your php.ini file. Usually this isn’t the case with most hosting providers. In addition session_start can take parameters to configure the length of the session and the storage location, etc, however most hosting providers don’t let you change these settings so I won’t cover them here.

Sessions are sent via HTTP headers just like cookies are (when PHP tries to create a temporary cookie), however since they can persist without cookies the data is immediately accessible once it has been initialized. This means you won’t have to refresh the page to access the data you’ve stored in them.

How do I Access Session Values?

<?php
session_start();

echo $_SESSION['mySession'];
print_r($_SESSION['myArray']);
print_r($_SESSION['myObject']);
?>

Unlike cookies where you have to refresh the page before you can access them, session values are immediately available once they’ve been set. All you have to do is start the sessions (unless sessions have been set to auto start) and then look for the name of the session you want to access.

How do I Delete a Session?

<?php
session_start();

//remove a single session values
unset($_SESSION['mySession']);
unset($_SESSION['myArray']);
unset($_SESSION['myObject']);

//alternative way to remove a session values
$_SESSION['mySession'] = false;
$_SESSION['myArray'] = null;
$_SESSION['myObject'] = '';
//this tells php your done making changes to the session
session_write_close();

//remove all session values
session_destroy();
?>

The best way to remove a session is to unset it, however you can also set the value to falsey or call session_destroy() to remove all session values.

How do I Edit Session Values?

<?php
//you have to start the sessions before you can use them
session_start();

//edit a single session value
$_SESSION['mySession'] = "new value!";

//edit an array in a session
$_SESSION['myArray'] = new array('one', 'two', 'three');

//edit an object in a session
$_SESSION['myObject'] = new myNewObject();

//this tells php your done making changes to the session
session_write_close();

//session value changes are immediately available
echo $_SESSION['mySession'];
print_r($_SESSION['myArray']);
print_r($_SESSION['myObject']);
?>

You can edit session values the same way you set them initially.

Session Troubleshooting

  • If you’re having trouble getting a session started and you’re getting  headers already sent errors then you have some kind of output (text, spaces, html, images, etc) that are being displayed to the screen before you’re calling your start_session() function.
  • Sessions will only last for the duration of a user’s visit or for the session_expiration time that’s set in the php.ini file. You can learn more about session configuration values in the PHP manual.
  • Make sure you’re not doing an unset($_SESSION) as this will make it impossible to register any new values in the $_SESSION.
  •  You can’t use reference variables in sessions.
  • If register_globals are enabled they will overwrite variables with the same $_SESSION name. For instance if you have a session named mySession and register_globals is enabled and you create a $mySession variable it will overwrite the $_SESSION[‘mySession’] value with whatever you’ve assigned to $mySession.
  • If you’re having a problem changing values in your session make sure you’re calling session_write_close() after you’ve made changes to session values. This is especially important if you’re doing a lot of asynchronous ajax calls.

Should I Use a Session or a Cookie?

The best way to answer this question is do you need data on a user to persist once they’ve closed their browser? Sessions will only last for the duration of a user’s visit on your website, they will disappear as soon as the user has closed all windows and tabs that they have open for your website. Cookies, on the other hand, will remain on a user’s computer until the user removes them from their browser or they expire.

Pros & Cons of Sessions vs Cookies

Type Pros Cons
Sessions Excellent for short term data storage

Can access immediately after initialization

Will create a temporary cookie if cookies are enabled/supported, otherwise propagated on the URL

Can be used for authentication

Only last for the duration of the user’s visit

Susceptible to XSS attacks

Cookies Excellent for long term storage of data

Can be used for authentication

Must be enabled/supported on the browser

Must refresh the page before you can access cookie data

Susceptible to XSS attacks

PHP Tutorial: Run Multiple Tic-Tac-Toe Game Instances (no database required)

Leave a comment Standard

Someone asked me about this in a comment recently so this post is specifically for you but I’m sure there are other people who will benefit from it as well. If you haven’t read the tic-tac-toe game tutorial yet then you’ll need to start there. This tutorial assumes you’ve already completed that and now you want to run two or more tic-tac-toe boards on the page simultaneously.

Or if you want to skip this tutorial you can
download the source code or try the working example

Concepts

The neat thing about classes is that you can use them to create multiple instances with varying states and data even though they all have the same methods and properties. Think about a monster RPG game. Each monster has a different name and breed and picture and strength — but they all have those things in common even though the values are different. Our tic tac toe class works the same way, we can create multiple instances of the game and they’ll each have different states — whose turn it is, which places on the board are filled — but they’ll all work the same way. In order to run multiple instances of our tic tac toe games we’re going to have to update our games so they can be uniquely identified by an instance number. The reason for this is so that when you play the game on instance 1 we know you want to update the state of instance 1 when you submit the form. If we didn’t give each game it’s own instance identifier then every time you made a move on one board it would reflect that move on all instances of the board at the same time.

Creating The Instance Form

Let’s change our index file so that we’re allowing the user to choose how many instances of the game they want to play. We start by removing where we created a new game from the top of the file. Since we want multiple instances we need to create the new game for every instance we have and since we don’t know how many instances we have at this point it needs to move down in our code base. Now once the user has selected how many instances of the game they want to play we need to dynamically generate that many. Using a for loop we loop through the number of instances they selected and create a game for each of those instances in our new $_SESSION[‘game’] array. Before this was only a single game, making it an array means we now have multiple games in our game session variable. Finally we create a new game instance and tell it to start playing. This is what our new index file looks like.

<?php
/***
* File: index.php
* Author: design1online.com, LLC
* Created: 4.6.2015
* License: Public GNU
* Description: PHP/MySQL Version of 2 Player Tic Tac Toe
* that allows playing multiple instances of the game at the same time
***/
require_once('oop/class.game.php');
require_once('oop/class.tictactoe.php');

//this will store their information as they refresh the page
session_start();

define('MAX_INSTANCES', 5); //the maximum number of games they can play at the same time

//trying to set number of instances to play
if (isset($_POST['instances'])) {
 if (is_numeric($_POST['instances']) && $_POST['instances'] > 0) {
 $_SESSION['instances'] = $_POST['instances'];
 }
}

?>
<html>
 <head>
 <title>Tic Tac Toe - Multiple Instances</title>
 <link rel="stylesheet" type="text/css" href="inc/style.css" />
 </head>
 <body>
 <div id="content">
 <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
 <h2>Let's Play Tic Tac Toe!</h2>
 <?php
 //we need to know how many instances to create
 if (!isset($_SESSION['instances'])) {
 ?>
 <p>How many games would you like to instantiate?</p>
 <select name="instances">
 <?php
 for ($i = 1; $i <= MAX_INSTANCES; $i++) {
 echo "<option value=\"$i\">$i</option>";
 }
 ?>
 </select>
 <input type="submit" name="submit" value="Let Me Play!" />
 <?php
 } else {
 echo "<table width=\"100%\">
 <tr>";
 
 for ($i = 1; $i <= $_SESSION['instances']; $i++) {
 
 //if they haven't started a game yet let's load one
 if (!isset($_SESSION['game'][$i]['tictactoe'])) {
 $_SESSION['game'][$i]['tictactoe'] = new tictactoe($i);
 }
 
 echo "<td>";
 
 //play the game passing it the game data for that instance
 $_SESSION['game'][$i]['tictactoe']->playGame($_POST);
 
 echo "</td>";
 }
 
 echo "</tr>
 </table>";
 }
 ?>
 </form>
 </div>
 </body>
</html>

Adding Instances To The Class

The first thing we need to do is add an instance identifier to our tictactoe class. Since we need to know which game the player is trying to play adding a $this->instance value to our class will let us keep track of which game is which. Once that’s done we update our checks for $_POST data to make sure we’re using the correct data for the correct instance. Voila! Our games now only update when they see $_POST data that pertains to them. Our new tictactoe class file looks like this:

<?php
/***
* File: oop/class.tictactoe.php
* Author: design1online.com, LLC
* Created: 1.31.2012
* License: Public GNU
* Description: tic tac toe game
***/

class tictactoe extends game
{
 var $instance = 0; //the instance of this game
 var $player = "X"; //whose turn is
 var $board = array(); //the tic tac toe board
 var $totalMoves = 0; //how many moves have been made so far 

 /**
 * Purpose: default constructor
 * Preconditions: none
 * Postconditions: parent object started
 **/
 function tictactoe($instance)
 {
 /**
 * instantiate the parent game class so this class
 * inherits all of the game class's attributes 
 * and methods
 **/
 $this->instance = $instance;
 game::start();
 
 $this->newBoard();
 }
 
 /**
 * Purpose: start a new tic tac toe game
 * Preconditions: none
 * Postconditions: game is ready to be displayed
 **/
 function newGame()
 {
 //setup the game
 $this->start();
 
 //reset the player
 $this->player = "X";
 $this->totalMoves = 0;
 
 //reset the board
 $this->newBoard();
 }
 
 function newBoard() {
 
 //clear out the board
 $this->board = array();
 
 //create the board
 for ($x = 0; $x <= 2; $x++)
 {
 for ($y = 0; $y <= 2; $y++)
 {
 $this->board[$x][$y] = null;
 }
 }
 }
 
 /**
 * Purpose: run the game until it's tied or someone has won
 * Preconditions: all $_POST content for this game
 * Postconditions: game is in play
 **/
 function playGame($gamedata)
 {
 if (!$this->isOver() && isset($gamedata[$this->instance . 'move'])) {
 $this->move($gamedata);
 }
 
 //player pressed the button to start a new game
 if (isset($gamedata[$this->instance . 'newgame'])) {
 $this->newGame();
 }
 
 //display the game
 $this->displayGame();
 }
 
 /**
 * Purpose: display the game interface
 * Preconditions: none
 * Postconditions: start a game or keep playing the current game
 **/
 function displayGame()
 {
 
 //while the game isn't over
 if (!$this->isOver())
 {
 echo "<div id=\"board\">";
 
 for ($x = 0; $x < 3; $x++)
 {
 for ($y = 0; $y < 3; $y++)
 {
 echo "<div class=\"board_cell\">";
 
 //check to see if that position is already filled
 if ($this->board[$x][$y])
 echo "<img src=\"images/{$this->board[$x][$y]}.jpg\" alt=\"{$this->board[$x][$y]}\" title=\"{$this->board[$x][$y]}\" />";
 else
 {
 //let them choose to put an x or o there
 echo "<select name=\"{$this->instance}_{$x}_{$y}\">
 <option value=\"\"></option>
 <option value=\"{$this->player}\">{$this->player}</option>
 </select>";
 }
 
 echo "</div>";
 }
 
 echo "<div class=\"break\"></div>";
 }
 
 echo "
 <p align=\"center\">
 <input type=\"submit\" name=\"{$this->instance}move\" value=\"Take Turn\" /><br/>
 <b>It's player {$this->player}'s turn.</b></p>
 </div>";
 }
 else
 {
 
 //someone won the game or there was a tie
 if ($this->isOver() != "Tie")
 echo successMsg("Congratulations player " . $this->isOver() . ", you've won the game!");
 else if ($this->isOver() == "Tie")
 echo errorMsg("Whoops! Looks like you've had a tie game. Want to try again?");
 
 echo "<p align=\"center\"><input type=\"submit\" name=\"{$this->instance}newgame\" value=\"New Game\" /></p>";
 }
 }
 
 /**
 * Purpose: trying to place an X or O on the board
 * Preconditions: the position they want to make their move
 * Postconditions: the game data is updated
 **/
 function move($gamedata)
 { 

 if ($this->isOver())
 return;

 //remove duplicate entries on the board 
 $gamedata = array_unique($gamedata);
 
 foreach ($gamedata as $key => $value)
 {
 if ($value == $this->player)
 { 
 //update the board in that position with the player's X or O 
 $coords = explode("_", $key);
 
 //make sure we use the data from the right instance
 if ($coords[0] == $this->instance) {
 $this->board[$coords[1]][$coords[2]] = $this->player;

 //change the turn to the next player
 if ($this->player == "X")
 $this->player = "O";
 else
 $this->player = "X";
 
 $this->totalMoves++;
 }
 }
 }
 
 if ($this->isOver())
 return;
 }
 
 /**
 * Purpose: check for a winner
 * Preconditions: none
 * Postconditions: return the winner if found
 **/
 function isOver()
 {
 //top row
 if ($this->board[0][0] && $this->board[0][0] == $this->board[0][1] && $this->board[0][1] == $this->board[0][2])
 return $this->board[0][0];
 
 //middle row
 if ($this->board[1][0] && $this->board[1][0] == $this->board[1][1] && $this->board[1][1] == $this->board[1][2])
 return $this->board[1][0];
 
 //bottom row
 if ($this->board[2][0] && $this->board[2][0] == $this->board[2][1] && $this->board[2][1] == $this->board[2][2])
 return $this->board[2][0];
 
 //first column
 if ($this->board[0][0] && $this->board[0][0] == $this->board[1][0] && $this->board[1][0] == $this->board[2][0])
 return $this->board[0][0];
 
 //second column
 if ($this->board[0][1] && $this->board[0][1] == $this->board[1][1] && $this->board[1][1] == $this->board[2][1])
 return $this->board[0][1];
 
 //third column
 if ($this->board[0][2] && $this->board[0][2] == $this->board[1][2] && $this->board[1][2] == $this->board[2][2])
 return $this->board[0][2];
 
 //diagonal 1
 if ($this->board[0][0] && $this->board[0][0] == $this->board[1][1] && $this->board[1][1] == $this->board[2][2])
 return $this->board[0][0];
 
 //diagonal 2
 if ($this->board[0][2] && $this->board[0][2] == $this->board[1][1] && $this->board[1][1] == $this->board[2][0])
 return $this->board[0][2];
 
 if ($this->totalMoves >= 9)
 return "Tie";
 }
}

Conclusion

Try the working example! In this tutorial we talked about instances and how you can use a class to dynamically create multiple instances each of which keep track of their own state and values. If you’ve been following my game tutorials then I hope you’re starting to see how powerful classes are and how iterative improvements can be used to enhance your gameplay, functionality and user experience.

PHP Tutorial: Number Guessing Game (no database required)

Comments 4 Standard

Wow I guess it’s been a while since I’ve posted anything. I’ve been busy moving and working on my games but I did find a few minutes to make this little game. This randomly picks a number and then lets the player try to guess the number. If you like this game you might also like my Ajax Tic-Tac-Toe game or Ajax Hangman game. This assumes that you’ve already done some of my other game tutorials so you are familiar with my game manager and how it works. You can read the code below or you can be lazy and can download the code or view a working example.

<?php
/***
* File: oop/class.guessnumber.php
* Author: design1online.com, LLC
* Created: 8.21.2014
* License: Public GNU
***/

class guessnumber extends game
{
    var $guesses;              //int - maximum guesses per game
    var $randomNumber = null;  //int - the random number they're trying to guess
    var $min = 50;             //int - the lowest value the random number can have
    var $max = 500;            //int - the highest value the random number can have

    /**
    * Purpose: default constructor
    * Preconditions: none
    * Postconditions: parent object started
    **/
    function guessnumber()
    {
        /**
        * instantiate the parent game class so this class
        * inherits all of the game class's attributes 
        * and methods
        **/
        game::start();
    }
    
    /**
    * Purpose: start a new guessing game
    * Preconditions: maximum number of guesses
    * Postconditions: game is ready to be displayed
    **/
    function newGame($max_guesses = 5, $min = null, $max = null)
    {
        //set the min and max values for the random number
        if (!$min)
            $min = $this->min;
         else
            $this->min = $min;
            
        if (!$max)
            $max = $this->max;
        else 
            $this->max = $max;
            
        //setup the game
        $this->start();
        
        //generate the random number
        $this->randomNumber = rand($min, $max);
            
        //set how many guesses they get before it's a game over
        if ($max_guesses)
            $this->setGuesses($max_guesses);
    }
    
    /**
    * Purpose: set or retrieve maximum guesses before game over
    * Preconditions: the data submitted from the form
    * Postconditions: guess is calculated
    **/
    function playGame($postdata)
    {
        //player pressed the button to start a new game
        if ($postdata['newgame'] || empty($this->guesses))
            $this->newGame();
            
        //player is trying to guess a number
        if (!$this->isOver() && $postdata['number'])
            echo $this->guess($postdata['number']);
                
        //display the game
        $this->displayGame();
    }
    
    /**
    * Purpose: set or retrieve maximum guesses they can make
    * Preconditions: amount of guesses (optional)
    * Postconditions: guesses has been updated
    **/
    function setGuesses($amount = 0)
    {        
        $this->guesses += $amount;
    }
    
    /**
    * Purpose: display the game interface
    * Preconditions: none
    * Postconditions: start a game or keep playing the current game
    **/
    function displayGame()
    {
        //while the game isn't over
        if (!$this->isOver())
        {
            echo "<div id=\"range\">I'm thinking of a number from " . number_format($this->min) . " to " . number_format($this->max) . ".</div>
                  <div id=\"select_number\">
                        Your Guess:
                        <input type=\"text\" name=\"number\" />
                        <input type=\"submit\" name=\"submit\" value=\"Guess\" />
                  </div>";
        }
        else
        {
            //they've won the game
            if ($this->won)
                echo successMsg("Congratulations you guessed my number $this->randomNumber! You've won the game.<br/>
                                Your final score was: $this->score");
            else if ($this->health < 0)
            {
                echo errorMsg("Game Over! Good try, my number was $this->randomNumber.<br/>
                                Your final score was: $this->score");
            }

            echo "<div id=\"start_game\"><input type=\"submit\" name=\"newgame\" value=\"New Game\" /></div>";
        }
    }
    
    /**
    * Purpose: guess a number in this word
    * Preconditions: a game has started
    * Postconditions: the game data is updated
    **/
    function guess($number)
    {            

        if ($this->isOver())
            return;

        if (!$number || !is_numeric($number))
            return errorMsg("Oops! Please enter a number.");
            
         if ($number < $this->min)
            return errorMsg("You must enter $this->min or higher.");
            
         if ($number > $this->max)
            return errorMsg("You must enter $this->max ot lower.");

        
        //if the word contains this number
        if ($number == $this->randomNumber) {
            $this->won = true;
        }
        else //word doesn't contain the number
        {
        
            //reduce their health
            $this->setHealth(ceil(100/$this->guesses) * -1);
            
            //calculate 1/6 the random number to get a distance factor
            $distance = floor($this->randomNumber / 8);
            

            if ($this->isOver())
                return;
            else {
                if ($number < $this->randomNumber - ($distance * 4) || $number > $this->randomNumber + ($distance * 4))
                    return errorMsg("So cold.");
                else if ($number < $this->randomNumber - ($distance * 3) || $number > $this->randomNumber + ($distance * 3))
                    return errorMsg("You're getting warmer...");
                else if ($number < $this->randomNumber - ($distance * 2) || $number > $this->randomNumber + ($distance * 2))
                    return errorMsg("Warm, Warm, Warm.");
                else if ($number < $this->randomNumber - $distance || $number > $this->randomNumber + $distance)
                    return errorMsg("You getting hot!");
                else
                    return errorMsg("You're really hot!!");
            }
        }
    }
}

PHP Tutorial: Create a nl2br function that doesn’t add tags inside of textarea contents

Comment 1 Standard

So this really bugs me and I thought I would share. Let’s say you want to allow someone to post their own custom html in a message or on a part of your website. If you’re using nl2br to format that message and they have <textarea> tags inside of their content then when you apply nl2br it adds <br> tags to the content inside of their textarea. For example:

$query = mysql_query("SELECT custom_html FROM users WHERE uid='$uid'") or die ('cannot load user custom html content');
$user_content = mysql_fetch_assoc($query);
echo nl2br($user_content['custom_html']);

If the user’s custom_html had:

Hi guys!
My name is Joe.
<textarea>this is
my html content</textarea>

Applying nl2br to that would result in the following:

Hi guys!<br />My name is Joe.<br /><textarea>this is<br />my html content</textarea>

So here you can see that we have <br /> tags inside of our textarea. When we display this on the page the textarea displays the <br> tags instead of indenting the content to a new line like we expect it to. This is where my code snippet comes into play.

//replace your nl2br function with our new nl2br_textarea function
function nl2br_textarea($message)
{
    $message = nl2br($message);

    function scrub_textarea($data) {
        return str_replace(array("<br>", "<br/>", "<br />"), "", $data[0]);
    }
    return preg_replace_callback('#<textarea[^>]*>(.*?)</textarea>#is',scrub_textarea,$message);
}

Using our nl2br_textarea function our original code would be updated to look like this:

$query = mysql_query("SELECT custom_html FROM users WHERE uid='$uid'") or die ('cannot load user custom html content');
$user_content = mysql_fetch_assoc($query);
echo nl2br_textarea($user_content['custom_html']);

Which means the output of user’s custom_html will now be this where we actually see a line break in the textarea without the additional <br> tags thrown into the mix:

Hi guys!<br />My name is Joe.<br /><textarea>this is/nmy html content</textarea>

PHP Tutorial: Dynamically Cache and Combine All CSS Files

Comments 10 Standard

Does your website use a lot of CSS files? If so did you know you can increase your website’s speed by caching and combining all of your CSS files into a single file?

Why Is It Useful?

Every time your browser loads a page on your website it has to make a request for all of the resources included or displayed on your page. Resources consist of things like image files, JS files, XML files and CSS files. If you find that you have more than one CSS file that you need to include on your website the requests required to load each of those files can sometimes take longer than a single request to load a single larger file. If you combine and cache your CSS files into a single file you can improve your website’s response time.

What’s a Cache?

A cache is a snapshot of a file at a moment in time. Typically you want to cache files that are static, meaning they don’t change often. If your file changes are fairly frequent then you end up generating a cache file too frequently for it to be of any use. That’s why this is a great technique to use with CSS files since they aren’t static but they don’t change that often either.

Setup

  1. Create two files, one called cache.css and another called cache.php.
  2. Place both of them in the same folder directory that you keep your style sheets in. We’ll use the CSS file to create a snapshot of all of our CSS files in our style sheet directory and we’ll use the PHP file to check generate and return the contents of our cache file.
  3. Change the permissions on the cache.php file to 0755. This will allow your PHP file to modify your cache.css file.
  4. Update the website page headers so instead of loading each of your individual .css files you’re now only loading your cache.php file

Before

<html>
     <head>
		<link href="stylesheets/filename1.css" rel="stylesheet" type="text/css" />
		<link href="stylesheets/filename2.css" rel="stylesheet" type="text/css" />
		<link href="stylesheets/filename3.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
          This is what the header would look like before updating to the single file. Notice how you're making reference links to multiple .css files. Each of those requires your browser to make a request in order to load the three separate files.
    </body>
</html>

After

<html>
     <head>
		<link href="stylesheets/cache.php" rel="stylesheet" type="text/css" />
    </head>
    <body>
          This is what the header looks like. It now references our cache.php file which will give it the cached version of our CSS files.
    </body>
</html>

The Code

Inside of your cache.php file put the following code:

<?php 
/**
* File: cache.php
* Author: design1online.com, LLC
* Purpose: updates and loads the current css cache file
**/
$path = "path_to_your_public_directory/";
$dir = "name_of_your_css_folder_directory/";
$cachefilename = "cache.css";
$files_to_cache = array(
 	"filename1.css",	//add all of your css file names
 	"filename2.css", 	//that are inside your_css_folder_directory
 	"filename2.css"		//that you want to cache
);

//check for file changes
if ($handle = opendir($path . $dir)) {
 	while (false !== ($entry = readdir($handle))) 
        {
 		//if any of the $files_to_cache have changed recently we need to update the cache file
                //to do this we compare the last modified times on the files to see if one of our
                //$files_to_cache was updated more recently than our cache file
 		if (is_file($entry) && is_readable($entry) && substr($entry, -3, 3) == "css" &&
 		date(date(filemtime($entry)) > filemtime($path . $dir . $cachefilename)))
                {
                        //we've found a $file_to_cache that was updated more recently than the cache file
                        //so open the cache file and prepare to overwrite the contents with the changes
			$cachefile = fopen($path . $dir . $cachefilename, "w");

			//write all of the $files_to_cache to the cache file
			foreach ($files_to_cache as $filename)
			{
				$copyfile = fopen($path . $dir . $filename, "r");
				fwrite($cachefile, fread($copyfile, filesize($filename)));
				fclose($copyfile);		
			}

                        //close the connection to the cache file - this also updates the last modified time
                        //on the cache file so that it won't try to re-generate the cache file again until 
                        //a $files_to_cache has been changed again
			fclose($cachefile);

                        //since we found one file that was changed and we've updated the cache file 
                        //we no longer need to look for other files that may have potentially been updated, so 
                        //this will tell the loop to stop running
			break;
		}
        }
}

//output the contents of the cache file
//the header content type will make sure the
//browser interprets the file contents as text/css
header("Content-type: text/css");

//clear the buffers to prevent overflows
ob_clean();
flush();

//open and return the contents of the cachefile
//you'll notice your cache file contains all of your
//$files_to_cache merged into one
readfile($path . $dir . $cachefilename);

Last But Not Least

Update the $path, $dir and $cachefile name as needed at the top of your new cache.php file. This will tell the file where to find your css stylesheets and which ones you want to cache. Since this script looks at the last modified dates on our $files_to_cache we need to make sure and update one of the files in our $files_to_cache list in order for it to generate our initial cache.css file. To do this I would recommend making a change to one of your $files_to_cache or using touch to update the last modified time stamp on one of your $files_to_cache. Once you’ve done that you can view any page you updated to use cache.php as it’s stylesheet (see setup step 4) in any web browser to view the results of your efforts.

PHP Tutorial: Mixing HEX Colors within a Range

Leave a comment Standard

This seems to be coming up more often with the client games I’ve been working on. Now everyone wants  dynamic images and colors. This function will produce a random hexcode color within the range of the two hexcode colors given. It’s inclusive so you can also get the original colors returned.

<?php
/**
* Purpose: produce a color within a range of two hexcode colors
* Precondition: two hexcode colors, min/max range values optional
* Postcondition: one random color within the range returned
**/
function mixRange($color1, $color2, $MIN = 1, $MAX = 10)
{
    $range = rand($MIN, $MAX);
 
    $r = hexdec(substr($color1,0,2));
    $g = hexdec(substr($color1,2,2));
    $b = hexdec(substr($color1,4,2));
     
    $gr = (hexdec(substr($color2,0,2))-$r)/$MAX; //Graduation Size Red
    $gg = (hexdec(substr($color2,2,2))-$g)/$MAX;
    $gb = (hexdec(substr($color2,4,2))-$b)/$MAX;
     
    return str_pad(dechex($r+($gr*$range)),2,'0',STR_PAD_LEFT) .
        str_pad(dechex($g+($gg*$range)),2,'0',STR_PAD_LEFT) .
        str_pad(dechex($b+($gb*$range)),2,'0',STR_PAD_LEFT);
}
?>