In my beginning PHP class, we are having our first go at Objects and classes. My assignment question is:
Create (a) a parent class (aka “superclass”) named “Human” with one variable named “legs” and one function (aka “method”) named “walk”, (b) set the default value of “legs” to 2, and (c) make the “walk” function display “Human can walk.” when it is called.
Create (a) a child class (also known as “subclass”) named “Kids” which will inherits all members of the “Human” class, (b) create a variable “hands” of the Kids class and set its default value to 2, and (c) create a function named “jump” of the Kids class which displays a message “A kid can jump.”
Create an object of the “Kids” class named ”Kuma”, and (c) use the "Kuma" object to display the numbers of legs and call the “walk” function.
The result should print:
2 legs
Humans can walk.
2 hands
A kid can jump.
Here's my code so far. I'm having difficult with the instructions in #3.
class Human {
var $legs = 2;
var $content = "<p>Humans can walk.</p>";
function Walk($Kuma) {
echo $this->legs . " legs";
echo $this->content;
}
}
class Kids extends Human {
var $hands = 2;
var $content2 = "<p>A kid can jump.</p>";
function Jump($Kuma) {
echo $this->hands;
echo $this->content2;
}
}
$obj = new Kids(Kuma);
$obj -> Walk(Kuma);
?>
class Human {
var $legs = 2;
var $content = "<p>Humans can walk.</p>";
function Walk() {
echo $this->legs . " legs";
echo $this->content;
}
}
class Kids extends Human {
var $hands = 2;
var $content2 = "<p>A kid can jump.</p>";
function Jump() {
echo $this->hands;
echo $this->content2;
}
}
$kuma = new Kids(); // creating OBJECT kuma
$kuma -> Walk(); // calling the walk function
?>
for example:
$object = new Human(); // creating OBJECT named object of CLASS Human
You have done a few weird things in your example. For example, I have no idea, from the instructions you gave, why you want the Walk and Jump methods to output information about hands and legs.
Here would be my suggestion:
class Human {
public $legs = 2;
public function walk() {
echo 'Human can walk.';
}
}
class Kids extends Human {
public $hands = 2;
public function jump() {
echo 'A kid can jump.';
}
}
$Kuma = new Kids();
echo $Kuma->legs . " legs\n";
$Kuma->walk();
echo "\n";
echo $Kuma->hands . " hands\n";
$kuma->jump();
A few things to note:
I have used good coding practice in declaring variables and method scope (in this case public). Honestly, good coding practice would also have the class properties (legs/arms) be declared as protected and available only via getters/setters.
I did not enforce any HTML formatting within the class (I actually just used end of line characters in my example which could be substituted with HTML line breaks or paragraphs or whatever you might need). I probably would have actually not even had the class itself be responsible for output when calling methods except that is explicitly asked for. (I would have simply done return of the raw text and let caller determine formatting for output).
I remove hands/legs output from walk/jump. This has nothing to do with those methods and should not be mixed.
Related
I know it is basic php question but I had something that I didn't understand, it is about the return; when I call a function, the bellow code is just an exemple.
Case : In TEST2 when I do my check then I return, that return; do the job and stop the execution of the next code TEST3 Good.
Now in TEST1 I Call a function _checkThat(), and this function do a check then redirect. the problem is it returns shure but the next code will also be executed TEST2 and TEST3 Why ? why when I put the content of that function directly in TEST1 it returns and stop the execution of next code ?
<?php class Some_Class_IndexController extends Some_Other_Controller_Front_Action
{
$name = $this->getRequest()->getParam('name'); //Output: "john"
$email = $this->getRequest()->getParam('email'); //Output: "john#gmail.com"
$phone = $this->getRequest()->getParam('phone'); //Output: 09000000
//TEST1
if(isset($name)) {
$this->_checkThat($name);
}
//TEST2
if(isset($email)) {
if($email === "john#gmail.com") {
//some code to redirect to another page
return;
} else {
//some code to redirect to another page
return;
}
}
//TEST3
if(isset($name)) {
$this->_checkthat();
}
private function _checkThat($name) {
if ($name !== "john") {
//some code to redirect to another page
return;
}
}
}
Other question, Can I use continue; in this case :
if(isset($name)) {
Mage::log('check passed'); //This just write in logs
continue; // or something else
} else if (!isset($name)) {
// some code
}
Although as already mentioned in comments your example code is not correct, your problem here:
if(isset($name)) {
$this->_checkThat($name);
}
is that you do nothing with result returned by _checkThat(). And obviously you should return it:
if(isset($name)) {
return $this->_checkThat($name);
}
As a sidenote, I should mention that naming methods with _ to mark them protected/private is out-of-date practice since php5.
Here is a simple guide.
Inheritance – reusing code the OOP way
Inheritance is a fundamental capability/construct in Object oriented programming where you can use one class, as the base/basis for another class or many other classes.
Why do it?
Doing this allows you to efficiently reuse the code found in your base class.
Say, you wanted to create a new employee class since we can say that employee is a type/kind of `person’, they will share common properties and methods.
Making some sense?
In this type of situation, inheritance can make your code lighter because you are reusing the same code in two different classes. But unlike old-school PHP:
You only have to type the code out once.
The actual code being reused, can be reused in many (unlimited) classes
but it is only typed out in one place conceptually, this is sort-of
like PHP includes().
Take a look at the sample PHP code:
// 'extends' is the keyword that enables inheritance
class employee extends person
{
function __construct($employee_name) {
$this->set_name($employee_name);
}
}
Reusing code with inheritance:
Because the class employee is based on the class person, employee automatically has all the public and protected properties and methods of ‘person’.
Nerd note: Nerds would say that employee is a type of person.
The code:
class employee extends person
{
function __construct($employee_name){
$this->set_name($employee_name);
}
}
Notice how we are able to use set_name() in employee, even though we did not declare that method in the employee class. That is because we already created set_name() in the class person.
Nerd Note: the person class is called (by nerds,) the base class or the parent class because it is the class that the employee is based on. This class hierarchy can become important down the road when your projects become more complex.
Reusing code with inheritance:
As you can see in the code snippet below, we can call get_name on our employee object, courtesy of person.
The code:
<?phpinclude("class_lib.php"); ?>
<?php
// Using our PHP objects in our PHP pages.
$stefan = new person("Stefan Mischook");
echo "Stefan's full name: " . $stefan->get_name();
$james = new employee("Johnny Fingers");
echo "---> " . $james->get_name();
?>
This is a classic example of how OOP can reduce the number of lines of code (don’t have to write the same methods twice) while still keeping your code modular and much easier to maintain.
Overriding methods 1
Sometimes (when using inheritance,) you may need to change how a method works from the base class.
For example, let us say set_name() method in the 'employee' class, had to do something different than what it does in the person class.
You override the person classes version of set_name(), by declaring the same method in employee.
The code snippet:
<?php
class person
{
protected function set_name($new_name) {
if ($new_name != "Jimmy Two Guns") {
$this->name = strtoupper($new_name);
}
}
}
class employee extends person
{
protected function set_name($new_name) {
if ($new_name == "Stefan Sucks") {
$this->name = $new_name;
}
}
}
?>
Notice how set_name() is different in the employee class from the version found in the parent class: person.
<Overriding methods: 2
Sometimes you may need to access your base class’s version of a method you overrode in the derived (sometimes called ‘child’) class.
In our example, we overrode the set_name() method in the employee class. Now I have
used this code:
hperson::set_name($new_name);
to access the parent class’ (person) version of the set_name() method.
The code:
<?php
class person
{
// explicitly adding class properties are optional - but
// is good practice
var $name;
function __construct($persons_name) {
$this->name = $persons_name;
}
public function get_name() {
return $this->name;
}
// protected methods and properties restrict access to
// those elements.
protected function set_name($new_name) {
if ($this->name != "Jimmy Two Guns") {
$this->name = strtoupper($new_name);
}
}
}
// 'extends' is the keyword that enables inheritance
class employee extends person
{
protected function set_name($new_name) {
if ($new_name == "Stefan Sucks") {
$this->name = $new_name;
}
else if ($new_name == "Johnny Fingers") {
person::set_name($new_name);
}
}
function __construct($employee_name)
{
$this->set_name($employee_name);
}
}
?>
Notes: Using the symbol:
::
… allows you to specifically name the class where you want PHP to search for a method:
person::set_name()
… tells PHP to search for set_name() in the person class.
There is also a shortcut if you just want refer to current class’s parent – by using the parent keyword.
The code:
protected function set_name($new_name)
{
if ($new_name == "Stefan Sucks") {
$this->name = $new_name;
}
else if ($new_name == "Johnny Fingers") {
parent::set_name($new_name);
}
}
At the moment I am working on a parser, comprised of a Document class that takes input and determines a number of processing steps to be taken. The logic of each step is dynamic to various circumstances, so is handed off to a Processor class which is passed to the Document at construction.
The goal is that my use of it will eventually look something like:
$document = new Document($input, Processors\XYZ::class);
$document->parse();
$document->output();
Document->__construct() also creates and stores in a property a new instance of the passed processor class. This leads to the part I am unsure of: The Processor instance also needs a link back to the Document. I am not sure whether I should be passing that by reference or not. I haven't found anything about this particular use of references - http://php.net/manual/en/language.references.pass.php is only really talking about functions, nothing to do with classes or instances.
I threw together this minimal test:
class base {
//function __construct($maker) {
function __construct(&$maker) {
if (!is_a($maker, makeSay::class, true)) { echo 'oh no!<br/>';}
$this->maker = $maker;
}
function say() {echo 'Base, made by ' . $this->maker->name;}
}
class child extends base {
function say() {echo 'Child, made by ' . $this->maker->name;}
}
class makeSay {
public $name = 'default';
function __construct($thing, $name) {
if (!is_a($thing, base::class, true)) { echo 'oh no!<br/>';}
$this->thing = new $thing($this);
$this->name = $name;
}
function say() {$this->thing->say();}
}
$a = new makeSay(child::class, 'This Guy');
$a->say();
... which has similar logic to the constructors in my real script, but it seems as though there is no difference in execution whether base->__construct() looks like function __construct(&$maker) or function __construct($maker).
Is there any difference to be expected between the two?
I have a Calc class that I think was improperly placed in the codebase I am working with. For the class structure see code below.
Currently
Spec class acts as a storage of data, similar to C struct
Calc class is a library of computational functions class that is instantiated as part of other classes, whenever those classes need to do some computation. Calc class also houses Spec class, so that it can do computations using variables of Spec.
Plot class is an example of a business object representing a graph.
Controller class is a business object representing a controller of sorts in my application, where some computations are made and are displayed in text for user page "View", and a graph is also created which is also displayed to the user on the "View" page.
class Spec
{
public $a;
public $b;
public $c;
}
class Calc
{
public $spec;
function __construct()
{
$this->spec = new Spec();
}
function calcParameter()
{
$this->spec->c = $this->spec->a + $this->spec->b;
}
}
class Plot
{
public $calc;
function __construct()
{
$this->calc = new Calc();
}
function calcPlot()
{
$this->calc->spec->c = $this->calc->spec->a * $this->calc->spec->b;
}
}
class Controller
{
public $calc;
public $plot;
function __construct()
{
$this->calc = new Calc();
$this->plot = new Plot();
}
function doBusinessLogic()
{
//calc for local
$this->calc->spec->a = 5;
$this->calc->spec->b = 5;
$this->calc->calcParameter();
print "total is {$this->calc->spec->c}<br>\n";
//later this format is used by JS to display computational results
$plotJSON = json_encode($this->calc);
//calc for plot
$this->plot->calc->spec->a = 7;
$this->plot->calc->spec->b = 143;
$this->plot->calcPlot();
print "total is {$this->plot->calc->spec->c}<br>\n";
//later this format is used by JS to display a plot
$plotJSON = json_encode($this->plot);
print "
<div id='plot' style='display:none'>$plotJSON</div>
<script>
var plot = JSON.parse(document.getElementById('plot').innerHTML);
document.write('JS says - there are ' + plot.calc.spec.c + ' plot points<br>');
</script>
";
}
}
//runs the above
(new Controller())->doBusinessLogic();
JS is used like so:
var plot = JSON.parse(document.getElementById('plot').innerHTML);
document.write('JS says - there are ' + plot.calc.spec.c + ' plot points<br>');
Question
I am under impression that the Calc class was not correctly placed (not designed properly), and as such, it is injected into various places just to do computations. I am thinking that Calc should be a class with no parameters and that Spec should not be part of Calc. And that Calc must only contain functions that do computations, and callers of Calc will supply their own data and receive results. Thereby Calc will become a static library of functions to be used by others. But then is this the best way?
How can I refactor this to minimize coupling? Keeping in mind that JSON format is either to be preserved, or being mindful that any changes in code may require changes to JS code as well.
Before I go knee-deep refactoring this, the design I have now works. Is there a need to refactor at all? Just checking.
Okay, based on what I see so far, the Calc class should not exist at all. The calcParameter method should be a member of the Spec class.
The calcPlot method of Plot should also be a member of the Spec class (it deals entirely with Spec fields as currently written.) You still might want to keep Plot around though if it does other interesting things to its Spec object.
Like this:
class Spec {
public $a;
public $b;
public $c;
function calcParameter() {
$this->c = $this->a + $this->b;
}
function calcPlot() {
$this->c = $this->a * $this->b;
}
}
class Plot {
public $spec;
function __construct() {
$this->spec = new Spec();
}
function calcPlot() {
$this->spec->calcPlot()
}
}
class Controller {
public $spec;
public $plot;
function __construct() {
$this->spec = new Spec();
$this->plot = new Plot();
}
function doBusinessLogic() {
//spec for local
$this->spec->a = 5;
$this->spec->b = 5;
$this->spec->calcParameter();
print "total is {$this->spec->c}<br>\n";
//later this format is used by JS to display computational results
$plotJSON = json_encode($this->spec);
//spec for plot
$this->plot->spec->a = 7;
$this->plot->spec->b = 143;
$this->plot->calcPlot();
print "total is {$this->plot->spec->c}<br>\n";
//later this format is used by JS to display a plot
$plotJSON = json_encode($this->plot);
print "
<div id='plot' style='display:none'>$plotJSON</div>
<script>
var plot = JSON.parse(document.getElementById('plot').innerHTML);
document.write('JS says - there are ' + plot.spec.c + ' plot points<br>');
</script>
";
}
}
//runs the above
(new Controller())->doBusinessLogic();
Okay, so the book says: "when creating a new object, you can pass a list of arguments to the class being called. These are passed to a special method within the class, called the constructor, which initializes various properties.
I don't know what "passing" is, really, especially not in this context. I also read that if you use a constructor method, it takes the name of the class. So, if you have
class User
{
function __constructor($param1, $param2)
{
echo "User construct."
}
}
user();
What is supposed to happen? I can't tell because my pastebins say it's a "possible CRF attack", whatever that means....
Moving right along, we come to a later section in the book where code says:
$bothCatsObject = new tiger();
echo "Tigers have...";
echo "Fur: " . $bothCatObject->fur . "";
echo "Stripes: " . $bothCatObject->stripes;
class cat
{
public $fur; // Cats have fur.
function __construct()
{
$this->fur = "TRUE";
}
}
class tiger extends Cats
{
public $stripes; // Tigers have stripes.
function __construct()
{
parent::__construct(); // Call parent construct first.
$this->stripes = "True";
}
}
Is the point of this second block of code to show that when an object is called, its constructs activate and set the properties in active memory or something? Or, perhaps is it to say that when a properties is called, if the property its value is set within the constructor, it will have a value. If its value isn't set within a constructor (e.g., if it's set within a non-constructor method), an error will be returned?
The book says 'this code takes advantage of the benefits of constructor inheritance in the typical manner'. So, I'm hoping I'm not too far away. I'm wondering why constructors are useful. What are some applications where constructors are necessary, if I need to know that at this point in my study?
Finally, in this case, the "cats" class is never assigned an object. Because "tiger" extends the cats class, can the cats class be called via the tiger object? Here's an example of what I mean:
$bothCatsObject = new tiger();
$bothCatsObject->catTest(); //Does this return an error?
class cat
{
public $fur; // Cats have fur.
function __construct()
{
$this->fur = "TRUE";
}
function catTest()
{
echo "The object works for cats and tigers."
}
}
class tiger extends Cats
{
public $stripes; // Tigers have stripes.
function __construct()
{
parent::__construct(); // Call parent construct first.
$this->stripes = "True";
}
function tigerTest()
{
echo "The object works for tigers and cats."
}
}
Along these same lines, can I call the functions built into the "tiger" class from a new cat object because the tiger class is sibling to the cat class? In other words, would replacing lines 1 and 2 of the previous code block with this code work, or would it return an error:
$bothCatsObject = new cat();
$bothCatsObject->tigerTest(); //Does this return an error?
First of all, run your script in your local machine.
ok :
class User
{
function __constructor($param1, $param2)
{
echo "My Name is {$param1} {$param2} ;)";
}
}
when you initialize the user class, it will automatically run the __construct function:
$user = new User("John","Smith");
// this will output "My Name is John Smith ;)"
Constructors run anytime you create a new instance of the class. an example is:
Lets say you want to start a database connection and do some heavy work, you can write a a constructor that checks if there is already a db connection and if not create it and handles setting all the default configuations
$database = new Database();
// will automatically create a connection
// ex: mysql_connect("username","password","....
// mysql_select_db(...
// and so on
I'm implementing a Log system for PHP, and I'm a bit stuck.
All the configuration is defined in an XML file, that declares every method to be logged. XML is well parsed and converted into a multidimensional array (classname => array of methods). So far, so good.
Let's take a simple example:
#A.php
class A {
public function foo($bar) {
echo ' // Hello there !';
}
public function bar($foo) {
echo " $ù$ùmezf$z !";
}
}
#B.php
class B {
public function far($boo) {
echo $boo;
}
}
Now, let's say I've this configuration file:
<interceptor>
<methods class="__CLASS_DIR__A.php">
<method name="foo">
<log-level>INFO</log-level>
<log-message>Transaction init</log-message>
</method>
</methods>
<methods class="__CLASS_DIR__B.php">
<method name="far">
<log-level>DEBUG</log-level>
<log-message>Useless</log-message>
</method>
</methods>
</interceptor>
The thing I'd like AT RUNTIME ONLY (once the XML parser has done his job) is:
#Logger.php (its definitely NOT a final version) -- generated by the XML parser
class Logger {
public function __call($name,$args) {
$log_level = args[0];
$args = array_slice($args,1);
switch($method_name) {
case 'foo':
case 'far':
//case .....
//write in log files
break;
}
//THEN, RELAY THE CALL TO THE INITIAL METHOD
}
}
#"dynamic" A.php
class A extends Logger {
public function foo($log_level, $bar) {
parent::foo($log_level, $bar);
echo ' // Hello there !';
}
public function bar($foo) {
echo " $ù$ùmezf$z !";
}
}
#"dynamic" B.php
class B extends Logger {
public function far($log_level, $boo) {
parent::far($log_level, $bar);
echo $boo;
}
}
The big challenge here is to transform A and B into their "dynamic" versions, once the XML parser has completed its job.
The ideal would be to achieve that without modifying the code of A and B at all (I mean, in the files) - or at least find a way to come back to their original versions once the program is finished.
To be clear, I wanna find the most proper way to intercept method calls in PHP.
What are your ideas about it?
PS: and of course, there should be NO CONSEQUENCE on the client code (no different if interception is enabled or not).
You could use eval() to actually define the classes, but you should be very careful. The eval() function can be very dangerous.
Something like this:
$parentName = 'Bar';
eval('class Foo extends ' . $parentName . ' { }');
http://php.net/eval
This solution once again uses eval, but I'll post it for your consideration anyway because I think it's a really nice way of dynamic inheritance.
The method here is to use an intermediary class which extends some default class that can be changed (in this instance to a different class also extending the default).
I'm uncertain as to what it is in your setup that is not allowing for this kind of working -- if you clarify this I could perhaps provide a better recommendation.
<?php
/*
* One of the following classes will be the superclass of the Child
*/
class Ancestor {
function speak() {
echo 'Ancestor <br />';
}
}
class Mum extends Ancestor {
function speak() {
parent::speak();
echo 'Mum <br />';
}
}
class Dad extends Ancestor {
function speak() {
parent::speak();
echo 'Dad <br />';
}
}
/*
* Decide on which class we wish to make the superclass of our Child
*/
$parentClass = null;
if (isset($_GET['parent'])) {
$parentClass = $_GET['parent'];
if (!class_exists($parentClass)) {
$parentClass = "Ancestor";
}
}
if (!is_null($parentClass)) {
eval("class ChildParent extends $parentClass {};");
} else {
class ChildParent extends Ancestor {};
}
if (class_exists('ChildParent')) {
class Child extends ChildParent
{
function speak() {
parent::speak();
echo 'Child <br />';
}
}
}
/*
* Show what's going on
*/
echo 'Either | Mum | Dad <br />';
$child = new Child();
$child->speak();*