Accessing methods from children class in PHP object - php

I have two classes A and B, where B extends A and adds some methods. I have a class C with a method that accepts A as parameter for generalization purposes. The issue is that once inside the method, I want to access the methods of class B on the object, but I'm not able to do so. Don't get error, but have null in the return, when I have dumped the object and know that it holds data.
Sorry if it's seems ridiculous, but I'm trying to use a bahaviour that you would expect in normal inheritance. Maybe be I'm missing something and it is my fault, but have no idea of what is happening here.
Please, if you have any idea of how to do this, help me.
Some code:
public function createProject(AssociatedProjectInterface $project_data){
if(!is_a($project_data, 'class\path\GithubProject')){
throw new InvalidArgumentException('The argument needs to be of type: GithubProject.');
}
$repo = $this->client->api('repo')->create(
$project_data->getTitle(),
$project_data->getDescription(),
null,
!$project_data->getIsPrivate(),
null,
$project_data->getIssuesEnabled(),
$project_data->getWikiEnabled());
}
Thanks.

Note that PHP's type checking is very loose. It calls the method of the class that is passed. The type checking is only taking place at the moment that function is called. So in the example below, testType must be past an object of type A or a descendant of A. After that initial check, no type checking is done at all! So the function can call any method declared in A or B. If a method is declared in both, it is considered overridden and the version in B is used.
<?php
class A {
function foo() {
echo 'A:foo';
}
}
class B extends A {
function foo() {
echo 'B:foo';
}
function bar() {
echo 'B:bar';
}
}
function testType(A $a)
{
$a->foo(); // B:foo
$a->bar(); // B:bar <- This will succeed even though there's no bar() in A.
}
$a = new B();
testType($a);

What you're asking for is NOT expected in normal object-oriented inheritance, but apparently works in PHP. Normally, if a method expects an object of class A, you can pass an object of class B that extends A, but the method will treat the object as though it were of class A. This means that when you call methods inherent to B, you are calling methods that don't exist and an error should be thrown.
In php though, momma don't care. As proof run the following minimal test:
<?php
class A {
public function foo() {
echo "in foo\n";
}
}
class B extends A {
public function bar() {
echo "in bar\n";
}
}
class C {
public function test(A $b) {
$b->foo();//works, because foo exists in the A class definition
$b->bar();//also works for B, but not A
}
}
$a = new A();
$b = new B();
$c = new C();
$c->test($b);
$c->test($a);//Will throw an error because the method bar() is not found
Note that it is considered extremely bad programming practice to ask for A when the code will quite literally die if it requires B. You should really avoid this situation.

Related

Why does PHP's method_exists() CALL (!) a method when it should just return a boolean by definition?

Problem
PHP's method_exists() [doc page] checks if a method exists and returns a boolean. BUT: Under special circumstances (when class and method have the same name) this function really CALLS a method. I'm really confused with this and have attached two reproduceable, copy&paste-ready examples to prove.
Question
Seriously, WTF ? Is this a bug or intended behaviour ? Am I violating some code convention rules that cause this ?
Code that reproduces the problem
Code & compiled result: http://viper-7.com/SFFRLL
<?php
class foo
{
public function foo()
{
echo 'Method foo() in class foo was called !';
}
}
$foo = new foo();
if (method_exists($foo, 'foo')) {
// The line above already triggers the execution of foo();
}
Code that (intentionally) does NOT reproduce the problem
Code & compiled result: http://viper-7.com/MPLe5M
<?php
class foo
{
public function bar()
{
echo 'Method bar() in class foo was called !';
}
}
$foo = new foo();
if (method_exists($foo, 'bar')) {
// Nothing should happen
}
Delete method_exists and the code will still exhibit the problem. That's because old style PHP 4 constructors are still supported, in which the constructor function is named after the class. foo::foo is the constructor and is called on new foo.

PHP: How many of these lines don't work, static vs non-static access

http://codepad.viper-7.com/ezvlkQ
So, I'm trying to figure out:
...?php
$object = new A();
class A
{
static public $foo = 'bar';
function displayFoo()
{
echo $this->$foo;
}
}
A::displayFoo();
A->displayFoo();
?>
About this, how many errors can you find? Can you tell me what they are in real human terms? I can't really interpret what is and what is not okay from the validator that codepad uses...
I’ve updated your code here http://codepad.viper-7.com/UaUE4g
Error 1:
echo $this->$foo;
This should read:
echo self::$foo;
.. as it is static.
Error 2:
A::displayFoo();
The method is an instance method :: is used for access to static methods.
Error 3:
A->displayFoo();
This is an error because A is undefined and if it was it should have read $A. This would be okay:
$object->displayFoo();
.. as $object is an instance of class A.
Next step, consult the manual on the topic static.
Not sure where to start. Static methods belong to the class, normal methods belong to an object, an instantiation of that class. For example, you can have:
Class A {
static public $foo = 'WOOHOOO';
static function displayFoo() {
echo self::$foo;
}
}
echo A::displayFoo();
This works because you're calling the displayFoo method belonging to class A. Or you can do this:
Class A {
public $foo = "WOOHOO";
public function displayFoo() {
echo $this->foo;
}
}
$obj = new A();
$obj->displayFoo();
Now you're creating an object based on the class of A. That object can call its methods. But the object doesn't have static methods. If you were to declare the function static, it would not be available to $obj.
You can't do:
A->displayFoo()
at all, under any circumstances, ever. The -> operator assumes an object, and A can't be an object because its not a variable.
You can read up on static class members in the manual here:
http://php.net/static
Pay close attention to the examples.

$this in php is bound dynamically, right?

I'm getting an error that I think is because I've made some kind of mistake in a refactoring, but I can't find documentation on when $this is bound, and my error could be explained by it being bound statically.
Extra points (I can't actually give you extra points) for links to excellent documentation about this kind of thing in php.
[Edit]
The error that I'm getting is telling me that Subclass::$var doesn't exist when I do, for example, echo $this->var in a superclass. The $var exists in the subclass, though.
$this becomes available after you've called the constructor. Logically you can't use $this in a static function.
Aside from calling $this in a static function there isn't a whole lot that can go wrong timing wise as there is simply no way in PHP.
What exactly is the error you're getting? Code would useful too.
This works in PHP:
class A {
public function foo() {
echo $this->bar;
}
}
class B extends A {
public $bar = 1;
}
$b = new B;
$b->foo(); // 1
It works because of the dynamic scope resolution that PHP has (i.e.: scope is resolved at runtime as opposed to compile time). However, I'd recommend against it, because it is really a particularity of the language for one. For second, failing to declare $bar in a subclass would result in an error. I think that a class should only reference members that it is aware of.
The same code, say in C++:
class A {
public:
void foo() {
std::cout << bar;
}
};
class B : public A {
public:
int bar;
B() {
bar = 1;
}
};
...would give you a compile error (In A::foo(): 'bar' was not declared in this scope).
Yes, $this is bound dynamically, as is evidenced by the fact that the output of the following is "foo":
<?php
class Base
{
public function ecc(){
echo $this->subvar;
}
}
class Sub extends Base
{
public $subvar;
public function __construct(){
$this->subvar = 'foo';
$this->ecc();
}
}
new Sub();
?>

What is function overloading and overriding in php?

In PHP, what do you mean by function overloading and function overriding. and what is the difference between both of them? couldn't figure out what is the difference between them.
Overloading is defining functions that have similar signatures, yet have different parameters. Overriding is only pertinent to derived classes, where the parent class has defined a method and the derived class wishes to override that method.
In PHP, you can only overload methods using the magic method __call.
An example of overriding:
<?php
class Foo {
function myFoo() {
return "Foo";
}
}
class Bar extends Foo {
function myFoo() {
return "Bar";
}
}
$foo = new Foo;
$bar = new Bar;
echo($foo->myFoo()); //"Foo"
echo($bar->myFoo()); //"Bar"
?>
Function overloading is not supported by PHP. It occurs when you define the same function name twice (or more) using different set of parameters. For example:
class Addition {
function compute($first, $second) {
return $first+$second;
}
function compute($first, $second, $third) {
return $first+$second+$third;
}
}
In the example above, the function compute is overloaded with two different parameter signatures. *This is not yet supported in PHP. An alternative is to use optional arguments:
class Addition {
function compute($first, $second, $third = 0) {
return $first+$second+$third;
}
}
Function overriding occurs when you extend a class and rewrite a function which existed in the parent class:
class Substraction extends Addition {
function compute($first, $second, $third = 0) {
return $first-$second-$third;
}
}
For example, compute overrides the behavior set forth in Addition.
Strictly speaking, there's no difference, since you cannot do either :)
Function overriding could have been done with a PHP extension like APD, but it's deprecated and afaik last version was unusable.
Function overloading in PHP cannot be done due to dynamic typing, ie, in PHP you don't "define" variables to be a particular type. Example:
$a=1;
$a='1';
$a=true;
$a=doSomething();
Each variable is of a different type, yet you can know the type before execution (see the 4th one).
As a comparison, other languages use:
int a=1;
String s="1";
bool a=true;
something a=doSomething();
In the last example, you must forcefully set the variable's type (as an example, I used data type "something").
Another "issue" why function overloading is not possible in PHP:
PHP has a function called func_get_args(), which returns an array of current arguments, now consider the following code:
function hello($a){
print_r(func_get_args());
}
function hello($a,$a){
print_r(func_get_args());
}
hello('a');
hello('a','b');
Considering both functions accept any amount of arguments, which one should the compiler choose?
Finally, I'd like to point out why the above replies are partially wrong;
function overloading/overriding is NOT equal to method overloading/overriding.
Where a method is like a function but specific to a class, in which case, PHP does allow overriding in classes, but again no overloading, due to language semantics.
To conclude, languages like Javascript allow overriding (but again, no overloading), however they may also show the difference between overriding a user function and a method:
/// Function Overriding ///
function a(){
alert('a');
}
a=function(){
alert('b');
}
a(); // shows popup with 'b'
/// Method Overriding ///
var a={
"a":function(){
alert('a');
}
}
a.a=function(){
alert('b');
}
a.a(); // shows popup with 'b'
Overloading Example
class overload {
public $name;
public function __construct($agr) {
$this->name = $agr;
}
public function __call($methodname, $agrument) {
if($methodname == 'sum2') {
if(count($agrument) == 2) {
$this->sum($agrument[0], $agrument[1]);
}
if(count($agrument) == 3) {
echo $this->sum1($agrument[0], $agrument[1], $agrument[2]);
}
}
}
public function sum($a, $b) {
return $a + $b;
}
public function sum1($a,$b,$c) {
return $a + $b + $c;
}
}
$object = new overload('Sum');
echo $object->sum2(1,2,3);
Although overloading paradigm is not fully supported by PHP the same (or very similar) effect can be achieved with default parameter(s) (as somebody mentioned before).
If you define your function like this:
function f($p=0)
{
if($p)
{
//implement functionality #1 here
}
else
{
//implement functionality #2 here
}
}
When you call this function like:
f();
you'll get one functionality (#1), but if you call it with parameter like:
f(1);
you'll get another functionality (#2). That's the effect of overloading - different functionality depending on function's input parameter(s).
I know, somebody will ask now what functionality one will get if he/she calls this function as f(0).
Method overloading occurs when two or more methods with same method name but different number of parameters in single class.
PHP does not support method overloading.
Method overriding means two methods with same method name and same number of parameters in two different classes means parent class and child class.
I would like to point out over here that Overloading in PHP has a completely different meaning as compared to other programming languages. A lot of people have said that overloading isnt supported in PHP and by the conventional definition of overloading, yes that functionality isnt explicitly available.
However, the correct definition of overloading in PHP is completely different.
In PHP overloading refers to dynamically creating properties and methods using magic methods like __set() and __get(). These overloading methods are invoked when interacting with methods or properties that are not accessible or not declared.
Here is a link from the PHP manual : http://www.php.net/manual/en/language.oop5.overloading.php
Overloading: In Real world, overloading means assigning some extra stuff to someone. As as in real world Overloading in PHP means calling extra functions. In other way You can say it have slimier function with different parameter.In PHP you can use overloading with magic functions e.g. __get, __set, __call etc.
Example of Overloading:
class Shape {
const Pi = 3.142 ; // constant value
function __call($functionname, $argument){
if($functionname == 'area')
switch(count($argument)){
case 0 : return 0 ;
case 1 : return self::Pi * $argument[0] ; // 3.14 * 5
case 2 : return $argument[0] * $argument[1]; // 5 * 10
}
}
}
$circle = new Shape();`enter code here`
echo "Area of circle:".$circle->area()."</br>"; // display the area of circle Output 0
echo "Area of circle:".$circle->area(5)."</br>"; // display the area of circle
$rect = new Shape();
echo "Area of rectangle:".$rect->area(5,10); // display area of rectangle
Overriding : In object oriented programming overriding is to replace parent method in child class.In overriding you can re-declare parent class method in child class. So, basically the purpose of overriding is to change the behavior of your parent class method.
Example of overriding :
class parent_class
{
public function text() //text() is a parent class method
{
echo "Hello!! everyone I am parent class text method"."</br>";
}
public function test()
{
echo "Hello!! I am second method of parent class"."</br>";
}
}
class child extends parent_class
{
public function text() // Text() parent class method which is override by child
class
{
echo "Hello!! Everyone i am child class";
}
}
$obj= new parent_class();
$obj->text(); // display the parent class method echo
$obj= new parent_class();
$obj->test();
$obj= new child();
$obj->text(); // display the child class method echo
There are some differences between Function overloading & overriding though both contains the same function name.In overloading ,between the same name functions contain different type of argument or return type;Such as:
"function add (int a,int b)" & "function add(float a,float b);
Here the add() function is overloaded.
In the case of overriding both the argument and function name are same.It generally found in inheritance or in traits.We have to follow some tactics to introduce, what function will execute now.
So In overriding the programmer follows some tactics to execute the desired function where in the overloading the program can automatically identify the desired function...Thanks!
Overloading: Declaring a function multiple times with a different set of parameters like this:
<?php
function foo($a) {
return $a;
}
function foo($a, $b) {
return $a + $b;
}
echo foo(5); // Prints "5"
echo foo(5, 2); // Prints "7"
?>
Overriding: Replacing the parent class's method(s) with a new method by redeclaring it like this:
<?php
class foo {
function new($args) {
// Do something.
}
}
class bar extends foo {
function new($args) {
// Do something different.
}
}
?>
PHP 5.x.x does not support overloading this is why PHP is not fully OOP.

PHP Classes: parent/child communication

I'm having some trouble extending Classes in PHP.
Have been Googling for a while.
$a = new A();
$a->one();
$a->two();
// something like this, or...
class A {
public $test1;
public function one() {
echo "this is A-one";
$this->two();
$parent->two();
$parent->B->two();
// ...how do i do something like this (prepare it for using in instance $a)?
}
}
class B extends A {
public $test2;
public function two($test) {
echo "this is B-two";
}
}
I'm ok at procedural PHP.
Your examples are fine, but you are showing a little confusion here:
public function one() {
echo "this is A-one";
$this->two();
$parent->two();
$parent->B->two();
}
what you want is this I think:
class A
{
function one()
{
echo "A is running one\n";
$this->two();
}
function two()
{
echo "A is running two\n";
}
}
class B extends A
{
function two()
{
echo "B is running two\n";
}
}
Then you want to make an object of type B and call function "one"
$myB = new B();
$b->one();
This will output
A is running one
B is running two
This is an example of polymorphic class behavior. The superclass will know to call the current instance's version of the function "two". This is a standard feature of PHP and most object oriented languages.
Note, that a superclass never knows about subclasses, the only reason you can call the "two" method and have B's version run is because the function "two" was defined in the parent (A) class.
It can't be done. First off, class A is class B's parent, so using something with parent is right off the list.
There is a number of things that goes for a child class that does not go for a parent class:
Class B needs A to be present in order to work
Class B can do everything A can plus more
Class B has access (as far as it is allowed to access) all data of class A
None of these things is true in reverse, so together they make up the reason why you cannot call a child's function.
Have a close read of the Object Inheritance section of the PHP manual. Yes, there's a lot of information in http://us2.php.net/oop, but it may help you think about what you can get out of OOP.
here's what you can do:
class A{
public function methodOfA (){
echo "this is a method of A (and therefore also of B)";
}
}
class B extends A{
public function methodOfB (){
echo "this is a method of B";
// you can do {$this->methodOfA ()} if you want because all of A is inherited by B
}
}
$a = new A (); // $a is an A
$a->methodOfA (); // this is OK because $a is an A
// can't do {$a->methodOfB ()} because $a is not a B
$b = new B (); // $b is a B, and it is also an A, because B extends A
$b->methodOfB (); // ok because $b is a B
$b->methodOfA (); // ok becuase $b is an A
Of course, there's much more. There's a good OOP section in the php manual (in artlung's answer).

Categories