08.07.2007 / Object-oriented PHP :: A guide for fellow ISys junkies

Pages: 1 2 3 4 5 6 7 8

Putting it all together

We’ve gone through a fairly thorough intro to object-oriented PHP, but to help solidify things we need a good example to integrate a lot that we’ve learned. What better way to do it than by recreating the framework you learned during INTEX II?

Here’s the folder structure I’m working with on my server:

/PHPSandbox
      /Includes
            /BO
            /DAO

And here are the files with their respective code:

/PHPSandbox/Includes/BO/ProductBO.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/StrictClass.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/DAO/ProductDAO.php");
 
class ProductBO extends StrictClass {
 
  private $id;
  private $sku;
  private $description;
  private $cost;
  private $vendor;
 
  public function getId() {
    return $this->id;
  }
 
  public function setId($id) {
    $this->id = $id;
  }
 
  public function getSku() {
    return $this->sku;
  }
 
  public function setSku($sku) {
    $this->sku = $sku;
  }
 
  public function getDescription() {
    return $this->description;
  }
 
  public function setDescription($description) {
    $this->description = $description;
  }
 
  public function getCost() {
    return $this->cost;
  }
 
  public function setCost($cost) {
    $this->cost = $cost;
  }
 
  public function getVendor() {
    return $this->vendor;
  }
 
  // This should probably not ever get called outside of our BOs and DAOs.
  // Most likely it will get set when calling VendorBO->addProduct()
  public function setVendor($vendor) {
    $this->vendor = $vendor;
  }
 
  public function save() {
    ProductDAO::saveProduct($this);
  }
 
}
?>

/PHPSandbox/Includes/BO/VendorBO.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/StrictClass.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/DAO/VendorDAO.php");
 
class VendorBO extends StrictClass {
 
  private $id;
  private $name;
  private $address;
  private $city;
  private $state;
  private $zip;
  private $phone;
  private $products;
 
  public function getId() {
    return $this->id;
  }
 
  public function setId($id) {
    $this->id = $id;
  }
 
  public function getName() {
    return $this->name;
  }
 
  public function setName($name) {
    $this->name = $name;
  }
 
  public function getAddress() {
    return $this->address;
  }
 
  public function setAddress($address) {
    $this->address = $address;
  }
 
  public function getCity() {
    return $this->city;
  }
 
  public function setCity($city) {
    $this->city = $city;
  }
 
  public function getState() {
    return $this->state;
  }
 
  public function setState($state) {
    $this->state = $state;
  }
 
  public function getZip() {
    return $this->zip;
  }
 
  public function setZip($zip) {
    $this->zip = $zip;
  }
 
  public function getPhone() {
    return $this->phone;
  }
 
  public function setPhone($phone) {
    $this->phone = $phone;
  }
 
  public function getProducts() {
    return $this->products;
  }
 
  public function setProducts($products) {
    $this->products = $products;
  }
 
  public function addProduct(ProductBO $product) {
    // Verify that product does not already exist in the list
    if (!empty($this->products)) {
      if (in_array($product, $this->products)) {
        trigger_error(printf("%s already exists in the product list", $product->getDescription()), E_USER_ERROR);
      }
    }
 
    //if (!empty($this->products) && in_array($product, $this->products)) {
    //  trigger_error(printf("%s already exists in the product list", $product->getDescription()), E_USER_ERROR);
    //}
 
    // Add product to list
    $this->products[] = $product;
 
    // Set vendor inside product BO
    $product->setVendor($this);
  }
 
  public function removeProduct(ProductBO $product) {
    // Verify that product already exists in the list
    if (empty($this->products) || !in_array($product, $this->products, true)) {
      trigger_error(printf("%s does not exist in the product list", $product->getDescription()), E_USER_ERROR);
    }
 
    // Remove product from the list
    unset($this->products[array_search($product, $this->products, true)]);
 
    // Re-index products list
    $this->products = array_merge($this->products);
 
    // Remove vendor from product BO
    $product->setVendor(null);
  }
 
  public function save() {
    VendorDAO::saveVendor($this);
  }
}
?>

/PHPSandbox/Includes/DAO/ProductDAO.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<?
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/DBConn.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/BO/ProductBO.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/DAO/VendorDAO.php");
 
class ProductDAO {
 
  public static function saveProduct(ProductBO &$product) {
    if ($product->getId()) {
      self::updateProduct($product);
    } else {
      self::insertProduct($product);
    }
  }
 
  private static function updateProduct(ProductBO $product) {
    if (!$product->getVendor()) {
      trigger_error("Product does not have a vendor", E_USER_ERROR);
    }
 
    if (!$product->getVendor()->getId()) {
      trigger_error("The vendor of this product must be saved before saving the product.", E_USER_ERROR);
    }
 
    $mysqli = DBConn::getConn();
 
    $stmt = $mysqli->prepare("UPDATE product SET sku=?, description=?, cost=?, vendorId=? WHERE id=?")
      or die(trigger_error(printf("Mysqli error: %s", $mysqli->error), E_USER_ERROR));
 
    $stmt->bind_param(
      'ssdii',
      $product->getSku(),
      $product->getDescription(),
      $product->getCost(),
      $product->getVendor()->getId(),
      $product->getId());
 
    $stmt->execute();
  }
 
  private static function insertProduct(ProductBO &$product) {
    if (!$product->getVendor()) {
      trigger_error("Product does not have a vendor", E_USER_ERROR);
    }
 
    if (!$product->getVendor()->getId()) {
      trigger_error("The vendor of this product must be saved before saving the product.", E_USER_ERROR);
    }
 
    $mysqli = DBConn::getConn();
 
    $stmt = $mysqli->prepare("INSERT INTO product VALUES (null, ?, ?, ?, ?)")
      or die(trigger_error(printf("Mysqli error: %s", $mysqli->error), E_USER_ERROR));
 
    $stmt->bind_param(
      'ssdi',
      $product->getSku(),
      $product->getDescription(),
      $product->getCost(),
      $product->getVendor()->getId());
 
    $stmt->execute();
 
    $product->setId($mysqli->insert_id);
  }
 
  public static function getProductById($id) {
    $mysqli = DBConn::getConn();
 
    $stmt = $mysqli->prepare("SELECT * FROM product WHERE id = ?")
      or die(trigger_error(printf("Mysqli error: %s", $mysqli->error), E_USER_ERROR));
 
    $stmt->bind_param(
      'i',
      $id);
 
    $stmt->execute();
 
    $stmt->bind_result(
      $id,
      $sku,
      $description,
      $cost,
      $vendorId);
 
    if ($stmt->fetch()) {
      $product = new ProductBO();
      $product->setId($id);
      $product->setSku($sku);
      $product->setDescription($description);
      $product->setCost($cost);
      $product->setVendor(VendorDAO::getVendorById($vendorId));
      return $product;
    } else {
      return false;
    }
  }
 
  public static function getProductsForVendor(VendorBO &$vendor) {
    $mysqli = DBConn::getConn();
 
    $stmt = $mysqli->prepare("SELECT * FROM product WHERE vendorId = ?")
      or die(trigger_error(printf("Mysqli error: %s", $mysqli->error), E_USER_ERROR));
 
    $stmt->bind_param(
      'i',
      $vendor->getId());
 
    $stmt->execute();
 
    $stmt->bind_result(
      $id,
      $sku,
      $description,
      $cost,
      $vendorId);
 
    $productList = array();
 
    while ($stmt->fetch()) {
      $product = new ProductBO();
      $product->setId($id);
      $product->setSku($sku);
      $product->setDescription($description);
      $product->setCost($cost);
      $product->setVendor($vendor);
      $productList[] = $product;
    }
 
    return $productList;
  }
 
  public static function deleteProduct(ProductBO &$product) {
    // If the product is assigned to a vendor, remove it from the vendor's
    // product list just to keep our vendor BO clean
    if ($product->getVendor()) {
        $product->getVendor()->removeProduct($product);
    }
 
    $mysqli = DBConn::getConn();
 
    $stmt = $mysqli->prepare("DELETE FROM product WHERE id = ?")
      or die(trigger_error(printf("Mysqli error: %s", $mysqli->error), E_USER_ERROR));
 
    $stmt->bind_param(
      'i',
      $product->getId());
 
    $stmt->execute();
  }
 
}
?>

/PHPSandbox/Includes/DAO/VendorDAO.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<?
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/DBConn.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/BO/VendorBO.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/DAO/ProductDAO.php");
 
class VendorDAO {
 
  public static function saveVendor(VendorBO &$vendor) {
    if ($vendor->getId()) {
      self::updateVendor($vendor);
    } else {
      self::insertVendor($vendor);
    }
 
    if ($vendor->getProducts()) {
      foreach ($vendor->getProducts() as $product) {
        ProductDAO::saveProduct($product);
      }
    }
  }
 
  private static function updateVendor(VendorBO $vendor) {
    $mysqli = DBConn::getConn();
 
    $stmt = $mysqli->prepare("
      UPDATE vendor SET
        name=?,
        address=?,
        city=?,
        state=?,
        zip=?,
        phone=?
      WHERE
        id=?")
      or die(trigger_error(printf("Mysqli error: %s", $mysqli->error), E_USER_ERROR));
 
    $stmt->bind_param(
      'ssssssi',
      $vendor->getName(),
      $vendor->getAddress(),
      $vendor->getCity(),
      $vendor->getState(),
      $vendor->getZip(),
      $vendor->getPhone(),
      $vendor->getId());
 
    $stmt->execute();
  }
 
  private static function insertVendor(VendorBO &$vendor) {
    $mysqli = DBConn::getConn();
 
    $stmt = $mysqli->prepare("INSERT INTO vendor VALUES (null, ?, ?, ?, ?, ?, ?)")
      or die(trigger_error(printf("Mysqli error: %s", $mysqli->error), E_USER_ERROR));
 
    $stmt->bind_param(
      'ssssss',
      $vendor->getName(),
      $vendor->getAddress(),
      $vendor->getCity(),
      $vendor->getState(),
      $vendor->getZip(),
      $vendor->getPhone());
 
    $stmt->execute();
 
    $vendor->setId($mysqli->insert_id);
  }
 
  public static function getVendorById($id) {
    $mysqli = DBConn::getConn();
 
    $stmt = $mysqli->prepare("SELECT * FROM vendor WHERE id = ?")
      or die(trigger_error(printf("Mysqli error: %s", $mysqli->error), E_USER_ERROR));
 
    $stmt->bind_param(
      'i',
      $id);
 
    $stmt->execute();
 
    $stmt->bind_result(
      $id,
      $name,
      $address,
      $city,
      $state,
      $zip,
      $phone);
 
    if ($stmt->fetch()) {
      $vendor = new VendorBO();
      $vendor->setId($id);
      $vendor->setName($name);
      $vendor->setAddress($address);
      $vendor->setCity($city);
      $vendor->setState($state);
      $vendor->setZip($zip);
      $vendor->setPhone($phone);
      $vendor->setProducts(ProductDAO::getProductsForVendor($vendor));
      return $vendor;
    } else {
      return false;
    }
  }
 
  public static function deleteVendor(VendorBO $vendor) {
    // If the product is assigned to the vendor, delete it
    if ($vendor->getProducts()) {
      foreach ($vendor->getProducts() as $product) {
        ProductDAO::deleteProduct($product);
      }
    }
 
    $mysqli = DBConn::getConn();
 
    $stmt = $mysqli->prepare("DELETE FROM product WHERE id = ?")
      or die(trigger_error(printf("Mysqli error: %s", $mysqli->error), E_USER_ERROR));
 
    $stmt->bind_param(
      'i',
      $product->getId());
 
    $stmt->execute();
  }
 
}

/PHPSandbox/Includes/StrictClass.php

1
2
3
4
5
6
7
8
9
10
11
12
13
<?
abstract class StrictClass {
 
  public function __get($var_name) {
    trigger_error("Class '" . get_class($this) . "' does not have member '$var_name' publicly available", E_USER_ERROR);
  }
 
  public function __set($var_name, $var_value) {
    trigger_error("Class '" . get_class($this) . "' does not have member '$var_name' publicly available", E_USER_ERROR);
  }
 
}
?>

/PHPSandbox/Includes/DBConn.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?
Class DBConn {
 
  static private $host = '***YOUR MYSQL HOST***';
  private static $username = '***YOUR USERNAME***';
  private static $password = '***YOUR PASSWORD***';
  private static $db = '***YOUR DATABASE NAME***';
 
  // Prevent class instantiation
  private function __construct() {
    trigger_error('Instantiation is not allowed.', E_USER_ERROR);
  }
 
  // Return a new connection
  // Note that connection pooling is not a feature of mysqli
  // If you get a gabajillion hits to your site per minute, it may
  // be worth implementing your own connection pool, but
  // this will work for the majority of cases
  public static function getConn() {
    $mysqli = new mysqli(self::$host, self::$username, self::$password, self::$db);
 
    if (mysqli_connect_errno()) {
        trigger_error(printf("Mysqli error: %s", mysqli_connect_error()), E_USER_ERROR);
    }
 
    return $mysqli;
  }
 
  // Prevent class cloning
  public function __clone()
  {
    trigger_error('Clone is not allowed.', E_USER_ERROR);
  }
}
 
?>

Once we have our core files set up, we can now test them out with a couple functions I’ve set up. Note that these are strictly for testing, but they can give you an idea of how the different classes and objects interoperate and how you could go about programming a full application using object-oriented PHP.

/PHPSandbox/TestFunctions.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/BO/ProductBO.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/DAO/ProductDAO.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/BO/VendorBO.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/PHPSandbox/Includes/DAO/VendorDAO.php");
 
function createNewVendorWithNewProducts() {
  $brinkton = new VendorBO();
  $brinkton->setName("Brinkton Manufacturing");
  $brinkton->setAddress("100 N 100 S");
  $brinkton->setCity("Provo");
  $brinkton->setState("UT");
  $brinkton->setZip("84606");
  $brinkton->setPhone("801-555-5555");
 
  $chair = new ProductBO();
  $chair->setSku("KAL-12KDUFLKDU134");
  $chair->setDescription("Blackstone Chair");
  $chair->setCost(119.45);
  $brinkton->addProduct($chair);
 
  $desk = new ProductBO();
  $desk->setSku("JKD-14LKJDFIUL183");
  $desk->setDescription("Swingline Table");
  $desk->setCost(212.98);
  $brinkton->addProduct($desk);
 
  // This will cascade and save all the products
  $brinkton->save();
}
 
function removeExistingProductFromExistingVendor() {
  $brinkton = VendorDAO::getVendorById(3);
  $products = $brinkton->getProducts();
  $productToRemove = $products[0];
 
  // This will both remove the product from the database
  // and remove it from the vender BO that is loaded
  ProductDAO::deleteProduct($productToRemove);
}
?>

That’s it! That’s all I’ve got! If you have any questions or just want to chat, feel free to join the intimate conversation or email me. Thanks for reading.

Pages: 1 2 3 4 5 6 7 8

Tags: , ,


Comments

08.07.2007 / Michael Jackson said:

Nice site you have here Aaron! There’s just one small point that I think you might be interested in. You mentioned that PHP doesn’t support object overloading, but it actually does. Several special methods can be set up on objects, including __get, __set, and __call. This may not be the same implementation as is found in other languages, but it is overloading. Check it out.

08.08.2007 / Aaron Hardy said:

Hey Michael, thanks for joining the intimate conversation! I guess I should have been more clear on my explanation (which I’ve since changed), but I’ve always thought PHP’s attempt at supporting method overloading is pretty weak sauce–more of a hack then true, native overloading as found in other languages (like you noted.) So when I said there are hacks to support the functionality, I guess I just grouped PHP’s way of overloading in with it.

For those of you who may be interested in the functionality Michael’s talking about, here’s PHP’s documentation on overloading.

In any case, it’d probably be fair to remove overloading from my “not supported” list and actually dedicate a section to explaining how it is (kind of) supported in PHP. Thanks for bringing up the issue! I hope you enjoy the rest of the article!

08.08.2007 / Scott said:

Hi Aaron, you did this tutorial just in time for me! I decided to teach myself PHP and good tutorials on using patterns and OOP in PHP is hard to find. I do want to point out that in Intex DAO’s were not static classes, we used the singleton pattern to instantiate a DAO once and then passed a reference to the DAO around. Though I’ve found tutorials on the web showing ways of implementing the singleton pattern in PHP, I cannot find anyone addressing the issue of how to make sure a object is only created once given that in PHP you cannot use “synchronized” key word to insure that a function isn’t called multiple times at the exact same time.

Also, and more important to me, I would like to understand how to create objects and classes that are instantiated and then used across all sessions. for example, if I create a class that has a static variable called “$counter” that starts and 0 and gets incremented every time a function in the class is called, the first time a page is loaded, the counter will increment to 1, the next time a the page is loaded, the object appears to be destroyed and recreated thus the counter is reset to 0 and will never be incremented past 1. Is it possible to create objects in PHP that can be passed around to all sessions that may be connected to the server?

08.08.2007 / Aaron Hardy said:

Hey Scott!! Thanks for joining…the intimate conversation. I’m glad I could be of service, if only a little. You’ve got some really good questions and I’m glad you posted them here publicly, because I’m not much of an authoritative source when it comes to the PHP core engine. With that in mind, I’ll do my best to provide insight where I can.

First off, I guess I completely forgot that we were using the singleton pattern for our DAOs during INTEX II! In any case, I don’t see much of an advantage to using the singleton pattern over static methods in this case. I’d still choose the static methods over the singleton pattern, but I’d love to hear some rebuttal from someone as to why I shouldn’t.

Okay, onto the stuff you were pondering. I think most of your difficulties in finding what you’re looking for is due to the difference in how PHP runs on the server compared to other frameworks like Java or .NET. With Java, you wrote your code and then you had to manually (by clicking a button, likely) compile it before opening it up in a browser for the first time. Then, you never had to re-compile your code until you had some code change that you wanted to take effect on the website. On the other hand, PHP is different. In the simplest of explanations, a PHP page is re-compiled each time it is called by a user. That’s why you don’t have to hit any compile button in your IDE when you want to check out the new changes you’ve made. There are some exceptions where you can actually compile PHP as a long-term executable or you can cache your pages, but again, my explanation is a simplistic one and I can’t elaborate much on the exceptions.

Also, Java can be very thread-based whereas PHP…not so much. Although there are web server environments that are threaded, PHP’s support is fairly limited. In fact, you’ll find a lot of articles where people say that the PHP development team recommends that you don’t run PHP on Apache 2 in multi-threaded mode, but I have yet to see the original source of that statement.

So, taking the differences into consideration, there is no “synchronized” keyword in PHP because there are no threads to synchronize. The same goes for using objects across all sessions. One of the noted benefits of PHP is that everything in memory is cleaned up after each session. There are no “application variables” (as they’re called in ASP) where you can set up a variable that exists over multiple sessions.

This doesn’t mean there aren’t ways to implement functionality similar to what you’re looking for though. PHP has the session_set_save_handler() method that can help save a user’s session to a database or file. You can read about it here:

session_set_save_handler() documentation

Here’s an implementation without using the session_set_save_handler() function:

Application variables in PHP

And if you’re interested in hacking up some threading in PHP, here’s an example:

Multi-threaded PHP

Needless to say, none of these options are super-duper pretty, but that’s not really PHP’s niche.

Anyone else want to comment? Please, I invite you to join….the intimate conversation.

08.09.2007 / Andrew Hegerhorst said:

Way to go on the tutorial, Aaron. For us php noobs it’s a keeper! I was reading through it and had a question, so I thought I would throw it out. Sadly, this will demonstrate exactly how new to php I am. ;)
Here’s the question:

Do you have any thoughts as to when the require function should be used as opposed to the include function? I have read about it a little, but being new to php I would appreciate any thoughts you may have on the subject.

Again, great job on the tutorial…

08.10.2007 / Fernando Mladineo said:

Hey Aaron,

Just started reading your PHP tutorial and I’m already learning new things. I just wanted to point out that you made reference to sayHello() on page 2 instead of sayWoot(). Keep up the good work!

08.10.2007 / Aaron Hardy said:

Hey Andrew and Fernando! I do appreciate you all joining…the intimate conversation! Let’s see what we can do here…

Andrew, when it comes to the difference between include() and require(), you can’t get much better than what PHP’s documentation has to say about it, so I’ll just copy it in here:

“require() and include() are identical in every way except how they handle failure. They both produce a Warning, but require() results in a Fatal Error. In other words, don’t hesitate to use require() if you want a missing file to halt processing of the page. include() does not behave this way, the script will continue regardless.”

Here’s the reference: Documentation on require()

Another thing to add to that is your server may react to warnings and fatal errors differently than another server, depending on your PHP configuration. If you want to see how it works on your particular server, try this example (make sure test.php does NOT exist):

include(”test.php”);
echo “Am I still processing?”;

Then try this one (again, test.php shouldn’t exist):

include(”test.php”);
echo “Am I still processing?”;
?>

And, although you may have already figured it out, include_once() and require_once() check to see if the file was loaded before. If it was, then it ignores the command and doesn’t load the file again. Personally, out of the four options (include(), include_once(), require(), and require_once()) I always choose require_once(). Hope that helps!

Fernando, thanks for the heads up! I’ve made the corrections. Three of them in fact. After writing the article, I thought I’d be a little more creative than the usual HelloWorld, but apparently I let a few slip through the cracks. Enjoy!

05.24.2008 / Dave said:

Just wanted to tell you that you did a great job in laying out this PHP tutorial.
I’ve picked up quite a handful of good tips by reading it.
just wanted to let you know that somebody out there thought this was quite handy!
later


Leave a Comment

Your email address is required but will not be published.




Comment


Warning: stristr() [function.stristr]: Empty delimiter in /home/.navyblue/aaronius/aaronhardy.com/wp-content/plugins/wassup/wassup.php on line 2093