Solved

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

Posted on 2014-11-07
8
69 Views
Last Modified: 2014-11-10
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

0
Comment
Question by:brucegust
  • 4
  • 4
8 Comments
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 40429034
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.
0
 

Author Comment

by:brucegust
ID: 40429067
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...
0
 

Author Comment

by:brucegust
ID: 40429079
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

0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 40429087
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

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 108

Expert Comment

by:Ray Paseur
ID: 40429097
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
0
 

Author Comment

by:brucegust
ID: 40429318
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?
0
 
LVL 108

Accepted Solution

by:
Ray Paseur earned 500 total points
ID: 40429508
Here is an important distinction:

$type->x != $type->$x  The dollar signs have a lot of importance in PHP.

When you create a function definition, your arguments are listed inside the parentheses like this:

function square($num)
{
    return $num * $num;
}

Open in new window


If you want to provide a default value for the function arguments, you do that with an assignment statement:

function square($num=0)
{
    return $num * $num;
}

Open in new window


When you run the function, you provide the value to replace the function arguments, either directly or through a variable.

echo square(3); // 9
$x = 4;
echo square($x); // 16

Open in new window


You don't actually "call" a class.  Assuming it's a normal class definition, you instantiate an object.  The object is an instance of the class.  You can have many instances of the same class (and an array of objects is a very useful data structure).

When you use var_dump() to visualize an object (note the difference between an object and a class) you are going to see a point-in-time picture of all of the object's properties.  You are not going to see local variables, or properties that have not been created yet.  It's smart to notice that if you want to look at local variables, you need to change them into class properties so they are visible with var_dump().  You will undoubtedly encounter some strange behavior one day and you will want to look at local variables, but you can't do that without modifying the class definition. So plan ahead - anything you want to see for diagnostic purposes should be a property of the object.

The speak() methods in the Tiger and Kitten classes replaces the speak() method in the Cat class.  It does nothing until you call it.  This is going to be true for most of the methods that you will write.

There are some things called magic methods that get called for certain environmental events.

I really urge you to read the PHP OOP documentation carefully, for understanding.  It will get you a much better and faster education than trial and error.  Some of this stuff is not intuitive and you have to work through the concepts in order.  The online man pages will help with that.
http://php.net/manual/en/language.oop5.php
0
 

Author Comment

by:brucegust
ID: 40433629
Excellent, Ray!

Thanks!
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Introduction HTML checkboxes provide the perfect way for a web developer to receive client input when the client's options might be none, one or many.  But the PHP code for processing the checkboxes can be confusing at first.  What if a checkbox is…
Consider the following scenario: You are working on a website and make something great - something that lets the server work with information submitted by your users. This could be anything, from a simple guestbook to a e-Money solution. But what…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to count occurrences of each item in an array.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now