Jump to content

Recommended Posts

Hi all,

 

I started reading a few tutorials about OOP within PHP recently. At the minute I'm not seeing the advantages over procedural but I'm sure this is largely because most of the tutorials use abstract dog classes that are extended with breeds, or car classes, to get the ideas across.

 

I decided the best thing to do would be to have a bash at making a couple of classes to see first hand what an object oriented approach could do.

 

Below is an address class, and there is also an property class that is extended by a residential class and a commercial class.

 

<?php

class address {

public $addressLine1;
public $addressLine2;
public $addressLine3;
public $postcode;

function __construct($addr1, $addr2, $addr3, $pcode){
	$this->addressLine1 = $addr1;
	$this->addressLine2 = $addr2;
	$this->addressLine3 = $addr3;
	$this->postcode = $pcode;
}

public function getAddress(){
	return array('addressLine1' => $this->addressLine1, 'addressLine2' => $this->addressLine2, 'addressLine3' => $this->addressLine3, 'postcode' => $this->postcode);
}

}

//$add1 = new address("1","2","3","4");
//print_r($add1->getAddress());

?>

<?php

require_once("address.class.php");

abstract class property extends address {

protected $buildingValue;
protected $address;

function __construct($bval,$addr1,$addr2,$addr3,$pcode) {
	$this->buildingValue = $bval;
	$this->address = new address($addr1,$addr2,$addr3,$pcode);
}

function getBuildingValue(){
	return $this->buildingValue;
}

function setBuildingValue($value){
	$this->buildingValue = $value;
}

function updateDetails($bval,$addr1,$addr2,$addr3,$pcode){
	$this->buildingValue = $bval;
	$this->address = new address($addr1,$addr2,$addr3,$pcode);
}

}

class residential extends property {

protected $tenantType;

function __construct($bval,$addr1,$addr2,$addr3,$pcode,$tenant) {
	parent::__construct($bval,$addr1,$addr2,$addr3,$pcode);
	$this->tenantType = $tenant;
}

}

class commercial extends property {

protected $trade;

function __construct($bval,$addr1,$addr2,$addr3,$pcode,$trade){
	parent::__construct($bval,$addr1,$addr2,$addr3,$pcode);
	$this->trade = $trade;
}

}
?>

 

This is the code I am using to create and display the objects:

 

<?php
require_once("property.class.php");
session_start();

$res1 = new residential(250000,"1 Test Road","Testville","Testshire","T1 1TT","Professional");
$com1 = new commercial(260000,"2 Test Road","Testville","Testshire","T1 1TT","Butcher");

#print_r($prop1);

$_SESSION['res1'] = $res1;

#print_r($_SESSION);

$_SESSION['res1']->updateDetails(450000,"144 Test Road","Testvilless","Testshirerer","T1 1TT","Student");

print_r($_SESSION);

print_r($res1->getAddress());

?>

 

The problem is that there is no output from $res1->getAddress(); although if I call the same function from within the address class it works OK. The output from that final print_r is:

 

Array

(

    [addressLine1] =>

    [addressLine2] =>

    [addressLine3] =>

    [postcode] =>

)

 

Any help on this would be much appreciated, as would any general comments about OOP.

 

Thanks in advance.

Link to comment
https://forums.phpfreaks.com/topic/167029-new-to-oop-with-php-struggling-a-little/
Share on other sites

A property is not an address, so you shouldn't use inheritance. Inheritance denotes an "is-a" relationship between the child and parent class. What you have is an "has-a" relationship which is made using aggregation or composition.

 

http://en.wikipedia.org/wiki/Object_composition

Your property class extends the address class, yet in your property constructor you instantiate an address object.  So you need to either call the parent::__constructor of the property class (thus calling address::__construct) or you need to do $res->address->getAddress() (which won't work since address is protected)

Here are the changes I would make:

 

<?php

ini_set('display_errors', 1);
error_reporting(E_ALL);

class Address {

public $line1;
public $line2;
public $line3;
public $postcode;

public function __construct($line1, $line2, $line3, $postcode){
	$this->line1 = $line1;
	$this->line2 = $line2;
	$this->line3 = $line3;
	$this->postcode = $postcode;
}

public function __toString()
{
	return "{$this->line1}<br />{$this->line2}<br />{$this->line3}<br />{$this->postcode}";
}

}

abstract class Property {

protected $buildingValue;
protected $address;

public function __construct()
{
}

public function getBuildingValue()
{
	return $this->buildingValue;
}

public function setBuildingValue($value)
{
	$this->buildingValue = $value;
}

public function getAddress()
{
	return $this->address;
}

public function setAddress($address)
{
	$this->address = $address;
}

}

class Residential extends property {

protected $tenantType;

public function __construct($tenant)
{
	$this->setTenant($tenant);
}

public function setTenant($tenant)
{
	$this->tenantType = $tenant;
}

public function getTenant()
{
	return $this->tenantType;
}

}

class Commercial extends property {

protected $trade;

public function __construct($trade)
{
	$this->setTrade($trade);
}

public function setTrade($trade)
{
	$this->trade = $trade;
}

public function getTrade()
{
	return $this->trade;
}
}


session_start();

$residential = new Residential(250000);
$residential->setAddress(new Address('1 Test Road','Testville','Testshire','T1 1TT','Professional'));

$commercial = new Commercial(260000);
$commercial->setAddress(new Address('2 Test Road','Testville','Testshire','T1 1TT','Butcher'));

$_SESSION['res1'] = $residential;

$_SESSION['res1']->setTenant(450000);
$_SESSION['res1']->setAddress(new Address("144 Test Road","Testvilless","Testshirerer","T1 1TT","Student"));

echo '<pre>', print_r($_SESSION, TRUE), '</pre>';

echo $residential->getAddress();

That you cannot instantiate an object of that class.

 

It might not make sense in the system to just have a property because you operate with either residential or commercial properties. In this case, commercial properties and residential properties would be concrete implementations of the general idea "a property".

Adding mutliple $addresses as a property to an address class defeats the purpose.

 

class Address {
    protected $_address;
    public function __construct($address) {
        $this->_address = $address;
    }
    public function __toString() {
        return $this->_address;
    }
}

class Residential {
    public function setAddress(Address $address) {
        $this->_address = $address;
    }
}

$addresses = array(
   new Address('..'),
   new Address('..')
);

 

Altough I think an Address class is overkill and a waste of memory to something meaningless.

 

OOP has many advantages over procedureal programming:

 

1) encapsulation of shared information between functions:

 

function user_login($username, $password) {
    global $db;//shared information but accessible by other functions who knows the name
    //perform login
}

function user_register($array) {
    global $db;
    //perform registration
}

class User {
    protected $_db;//db is encapsulated within User and thus not accessible by other parties (global $db)
    //login();
    //register();
}

 

2) access levels to define inheritance rules:

 

class User {
    public $id;//will be inherited;
    private $_username;//will not be inherited
    private $_password;//will not be inherited
    protected $_db;//will be inherited
}

 

3) use access levels for functions to define helpers:

 

class User {
     public function someFunction() {
         $this->_someHelperFunction();
     }
}

 

and much more

There's no need to have an abstract class if you aren't defining a method as abstract.

 

Not true. It can also be abstract if it's just not supposed to be instantiated.

 

What purpose does an abstract class serve if there is no abstract method?

 

Like Daniel0 said: That you cannot instantiate an object of that class.

 

Or polymorphism:

 

abstract class Character {}
class Naruto extends Character {}
class SinJu extends Character {}

class Player {
    public function setCharacter(Character $character) {
        $this->_character = $character;
    }
}

 

Now the player may have any character:

 

$player->setCharacter(new Naruto());
$player->setCharacter(new SinJu());

Altough I think an Address class is overkill and a waste of memory to something meaningless.

 

That depends on what you are going to use it for. You could potentially implement some interesting things with an address class such as geolocation and perhaps calculation of the distance between two addresses (like $address->getDistance($otherAddress)).

 

Saying that a particular usage example is overkill in a hypothetical example often doesn't make much sense.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.