Link to home
Start Free TrialLog in
Avatar of Bruce Gust
Bruce GustFlag for United States of America

asked on

Definitions and Theory (Part II) - Is this right?

Below is some code that I'm working on. I've got several comments that strive to explain the various components and I'm wanting confirmation as far as whether or not these explanations are correct.

Thanks in advance for helping me understand this better!

<?php
class htmlpage {
	protected $headerTop; //the following values are "protected" in order to ensure that they remain exclusive to the htmlpage Class. This is healthy programming because it prevents situations where unintended usages of the Property name (i.e. $style) don't result in wires getting crossed and apps blowing up because of the way the page is subsequently processed
	protected $metatags;
	protected $style;
	protected $scripts;
	protected $headerBottom;
	protected $body;
	protected $footer;
	protected $URL;
	
	public function __construct($title='Sandbox') { //here' where I'm declaring and / or defining my Property values
	$this->metatags=''; //by leaving this blank, I'm giving myself the opportunity to define this in the context of some kind of interactivity in the context of a Function. As an aside, you don't declare a variable / property with a function and expect it to be shared by other Functions in the same Class apart from using the Construct Function.
	$this->style='';
	$this->scripts='';
	$this->body='';
	
	$this->headerTop = '<!DOCTYPE html>
	<html lang="en">
	<head>
	<title>'.$title.'</title>
	<link href="style.css" rel="stylesheet" type="text/css" />
	</head>
	<body>
	<div id="content">
	'; //hard coding the value of my $headerTop Property
	
	$this->headerBottom= '
	</head>
	<body>
	<div id="wrapper">
	'; //hard coding the value of my $headerBottom Property
	
	$this->footer='
	</idv> <!--close wrapper-->
	</body>
	</html>
	';//hard coding the value of my $footer Property
	
	$this->setURL();
	
	}
	
	public function getURL() {
	return $this->URL;
	} //apparently I'm going to be defining my URL Property value in the context of either this Function or the one directly beneath it. Either way, the Property value is the one being "returned" by one of these two functions. 
	
	public function setURL($URL=null) {
		if(isset($URL))
		{
		$this->URL=$URL;
		}
		else
		{
		$this->URL='http://'.$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];
		return;
		}
	}
	
	public function setMetaTags($metaTags) {
	$this->metaTags .=$metaTags;
	return; //I can expect this Property value to be establishd as a result of a variable that's going to be passed into this Function
	
	public function setStyle($style) {
	$this->style .=$style;
	return;
	} //same thing as $metaTags
	
	public function setScript($scripts) {
	$this->scripts .=$scripts;
	return;
	} //same thing as $metaTags
	
	public function setBody($body) {
	$this->body .=$body;
	return;
	} // same thing as $metaTags
	
	public function display() {
	echo $this->headerTop;
	echo $this->metaTags;
	echo $this->style;
	echo $this->scripts;
	echo $this->headerBottom;
	echo $this->body;
	echo $this->footer;
	return;
	} //this Function is taking all of the Property values that have been declared and defined and displaying them by "echo-ing" them
	
}

/*just to clarify what I've learned thus far, if I were to attempt to define a Property value in the context of a Function such as 

public $csv; //declare my Property

	public function newCSV() {
		if(empty($_POST['csv_name']))
		{
		print "there's no CSV to look at";
		}
		else
		{
		$this->csv=$_POST['csv_name'];
		}
	}

..I've got a problem if I write something like this:

public function loadCSV()
	{
	$this->csv_file_name="csv/$this->csv";
	var_dump($this->csv_file_name);
	}	

I've got a problem becasue there's no line of communication between these two Functions. If I want this to work, I have to establish my $csv Property value in the context of a Construct like this:

	public function __construct() {
		if(empty($_POST['csv_name']))
		{
		print "there's no CSV to look at";
		}
		else
		{
		$this->csv=$_POST['csv_name'];
		}
	}
	
	public function loadCSV()
	{
	$this->csv_file_name="csv/$this->csv";
	var_dump($this->csv_file_name);
	$handle=fopen($this->csv_file_name, "r");
	}
	
Now this works! The key is the manner in which I define the $csv Property value. It has to be done as a Construct. That's the only way in which you can "share" Property values between Functions in a Class. Otherwise, you get an error when you write what you have on line 112 in that your code doesn't "see" $this->csv. But when you define it in the context of a Construct Function, you're gold! 
	

Open in new window

Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

First thing you want to do, right now and never look back again, is adopt a coding standard that lines up the curly braces and indents each level of control structures by 4 characters.  This is nearly unreadable as written.  And you will waste an unbelievable amount of time struggling to figure out the logic in your programming if you don't follow indentation rules.
Avatar of Bruce Gust

ASKER

OK.

I didn't copy and paste, but this is code that I re-wrote myself from another resource so let me go back and institute your suggestion...
I think this more along the lines of what you're recommending. If it's not, if you could provide a small example, I'll make that my template going forward.

<?php
class htmlpage {
protected $headerTop; //the following values are "protected" in order to ensure that they remain exclusive to the htmlpage Class. This is healthy programming because it prevents situations where unintended usages of the Property name (i.e. $style) don't result in wires getting crossed and apps blowing up because of the way the page is subsequently processed
protected $metatags;
protected $style;
protected $scripts;
protected $headerBottom;
protected $body;
protected $footer;
protected $URL;

	public function __construct($title='Sandbox') { //here' where I'm declaring and / or defining my Property values
	$this->metatags=''; //by leaving this blank, I'm giving myself the opportunity to define this in the context of some kind of interactivity in the context of a Function. As an aside, you don't declare a variable / property with a function and expect it to be shared by other Functions in the same Class apart from using the Construct Function.
	$this->style='';
	$this->scripts='';
	$this->body='';

	$this->headerTop = '<!DOCTYPE html>
	<html lang="en">
	<head>
	<title>'.$title.'</title>
	<link href="style.css" rel="stylesheet" type="text/css" />
	</head>
	<body>
	<div id="content">
	'; //hard coding the value of my $headerTop Property

	$this->headerBottom= '
	</head>
	<body>
	<div id="wrapper">
	'; //hard coding the value of my $headerBottom Property

	$this->footer='
	</idv> <!--close wrapper-->
	</body>
	</html>
	';//hard coding the value of my $footer Property

	$this->setURL();

	}

	public function getURL() {
	return $this->URL;
	} //apparently I'm going to be defining my URL Property value in the context of either this Function or the one directly beneath it. Either way, the Property value is the one being "returned" by one of these two functions. 

	public function setURL($URL=null) {
		if(isset($URL))
		{
		$this->URL=$URL;
		}
		else
		{
		$this->URL='http://'.$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];
		return;
		}
	}

	public function setMetaTags($metaTags) {
	$this->metaTags .=$metaTags;
	return; //I can expect this Property value to be establishd as a result of a variable that's going to be passed into this Function
	}

	public function setStyle($style) {
	$this->style .=$style;
	return;
	} //same thing as $metaTags

	public function setScript($scripts) {
	$this->scripts .=$scripts;
	return;
	} //same thing as $metaTags

	public function setBody($body) {
	$this->body .=$body;
	return;
	} // same thing as $metaTags

	public function display() {
	echo $this->headerTop;
	echo $this->metaTags;
	echo $this->style;
	echo $this->scripts;
	echo $this->headerBottom;
	echo $this->body;
	echo $this->footer;
	return;
	} //this Function is taking all of the Property values that have been declared and defined and displaying them by "echo-ing" them

}

/*just to clarify what I've learned thus far, if I were to attempt to define a Property value in the context of a Function such as 

public $csv; //declare my Property

public function newCSV() {
	if(empty($_POST['csv_name']))
	{
	print "there's no CSV to look at";
	}
	else
	{
	$this->csv=$_POST['csv_name'];
	}
}

..I've got a problem if I write something like this:

public function loadCSV() {
$this->csv_file_name="csv/$this->csv";
var_dump($this->csv_file_name);
}	

I've got a problem becasue there's no line of communication between these two Functions. If I want this to work, I have to establish my $csv Property value in the context of a Construct like this:

public function __construct() {
	if(empty($_POST['csv_name']))
	{
	print "there's no CSV to look at";
	}
	else
	{
	$this->csv=$_POST['csv_name'];
	}
}

public function loadCSV() {
$this->csv_file_name="csv/$this->csv";
var_dump($this->csv_file_name);
$handle=fopen($this->csv_file_name, "r");
}

Now this works! The key is the manner in which I define the $csv Property value. It has to be done as a Construct. That's the only way in which you can "share" Property values between Functions in a Class. Otherwise, you get an error when you write what you have on line 112 in that your code doesn't "see" $this->csv. But when you define it in the context of a Construct Function, you're gold! */
?>

Open in new window

I'm concerned that you still have some confusion about the use of $this-> and object properties.  Let me try to explain with an example.  Please read this over and observe its behavior.
http://iconoun.com/demo/temp_brucegust.php

<?php // demo/temp_brucegust.php

// THIS IS THE MOST IMPORTANT LINE IN THE ENTIRE CODE SET
error_reporting(E_ALL);

/**
 * Define a Cat class that has properties and methods
 */
Class Cat
{
    // THIS IS A CLASS PROPERTY.
    // "PROTECTED" MEANS THAT IT IS VISIBLE TO THIS CLASS AND ANY CLASS THAT EXTENDS THIS CLASS.
    // WE REFER TO IT WITH $this->type
    // PROPERTIES LISTED HERE AT THE TOP OF THE CLASS DEFINITION COME OUT FIRST IN var_dump()
    protected $type;

    // THIS IS THE CLASS CONSTRUCTOR
    // IT SETS THE $type PROPERTY
    public function __construct($x = 'unknown')
    {
        $this->type = $x;
    }

    // THIS IS AN ACTION THE OBJECT CAN TAKE.  IT IS BASICALLY EMPTY FOR NOW
    public function speak()
    {
        return NULL;
    }
}

/**
 * Extend the Cat class to create a Tiger
 */
Class Tiger extends Cat
{
    // THIS CONSTRUCTOR CALLS THE PARENT CONSTRUCTOR AND THEREBY SETS THE TYPE OF CAT
    public function __construct()
    {
        parent::__construct('Jungle Cat');
    }

    public function speak()
    {
        return 'Roar';
    }
}

/**
 * Extend the Cat class to create a Kitten
 */
Class Kitten extends Cat
{
    // THIS CONSTRUCTOR CALLS THE PARENT CONSTRUCTOR AND THEREBY SETS THE TYPE OF CAT
    public function __construct()
    {
        parent::__construct('House Cat');
    }

    public function speak()
    {
        return 'Meow';
    }
}

// SOME EXAMPLES
echo '<pre>';

// THE CAT ALONE IS NOT VERY VALUABLE
echo PHP_EOL . "Cat Object by itself" . PHP_EOL;
$x = new Cat;
var_dump($x);
echo PHP_EOL;

// BUT WE CAN CREATE MORE INTERESTING ANIMALS
echo PHP_EOL . "Tiger Object created by extending the Cat Class" . PHP_EOL;
$simba = new Tiger;
$voice = $simba->speak();
var_dump($voice);
var_dump($simba);
echo PHP_EOL;

echo PHP_EOL . "Kitten Object created by extending the Cat Class" . PHP_EOL;
$pussy = new Kitten;
$voice = $pussy->speak();
var_dump($voice);
var_dump($pussy);
echo PHP_EOL;

Open in new window

My coding standards are a modified version of the Zend standards.  Here are my rules:

1. Curly braces open and close line up vertically
2. Except for HEREDOC, each level of control structure indents 4 characters
3. Whenever possible, repeated assignment statements line up with the equal signs in a column
4. Arrays are written out on multiple lines (each line is one element)
5. Variables are always lower-case.  Logical "blanks" in variable names are underscores
6. Clarity of purpose trumps any other consideration in deciding how to write the code
OK, Ray! I've got your demo below with a couple of comments that either explain or request some feedback.

Bottom line: Pretty straightforward. My only two questions were:

Here:

   public function __construct($x = 'unknown') //in the context of what you're got here in your parenthesis, you declare $x as a variable, then define it as "unknown"
    {
        $this->type = $x;
    }

Open in new window


It seems like $type->$x establishes a template that says "Type is going to be whatever "$x" has been set to. In your child classes, you simply put the type of cat in parenthesis- parent::__construct('Jungle Cat'). It obviously works, but how come you don't have to duplicate the format of your Parent Class by saying the parent::__construct($x='Jungle Cat')?

Second question, I'm operating under the impression that whenever you call a Class, you simultaneously put into motion every Function within that class. That's not accurate is it? The reason I'm asking is because when you do...

// BUT WE CAN CREATE MORE INTERESTING ANIMALS
echo PHP_EOL . "Tiger Object created by extending the Cat Class" . PHP_EOL;
$simba = new Tiger;
$voice = $simba->speak();
var_dump($voice);
var_dump($simba);
echo PHP_EOL;

Open in new window


I'm expecting var_dump($simba); to yield not just the type of cat, but also the results of $voice = $simba->speak();, which would be "Roar," but that's not the case, is it?

In other words, just because you do a var_dump for a particular Class, you're only going to get the "preliminaries," you're not going to get the results of every function within that class. That's why when you do a var_dump for $samba, the variables that are "dumped" are those produced by the construct function and that's it. The "speak" function within the Tiger class doesn't fire unless you call it specifically. Is that correct?
ASKER CERTIFIED SOLUTION
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Excellent, Ray!

Thanks!