Class Inheritance Problem - php

I have A.php and B.php
A.php
<?php
error_reporting(E_ALL);
ini_set("display_errors",1);
class myClass
{
function hello()
{
return 'hello';
}
}
?>
B.php
<?php
error_reporting(E_ALL);
ini_set("display_errors",1);
require_once('/A.php');
$a = new myClass();
testing();
function testing()
{
echo $a ->hello();
}
?>
B.php inherits A.php ,
if i run B.php,but it show
"Fatal error: Call to a member function hello() on a non-object."
So the question is simple, how can i correct this ,but "$a = new myClass();" is not inside the function, since in .NET world can do this, i believe PHP also possible.
And one more question is, what is the modify of function in A.php ,if i have not state private/public/protected?

This is not inheritance. B.php merely includes A.php. This means all the code in A.php becomes available to the execution context of B.php.
Inheritance is a class relationship
class A{}
class B extends A{}
Class B can be said to inherit from A. So, a hierarchy has been formed.
Much as we humans inherit traits from our parents, classes inherit properties from their parents. For this reason, it is very common to talk about these classes in terms of their place in the hierarchy. Class A is a parent to class B. Class B is a child to class A.
But the actual problem you are having, the source of the error message, is a scope issue. You create $a in the global scope but attempt to access it from within a function's scope, in this case testing().
The best way to solve this is to pass your instances of myClass into testing()
$a = new myClass();
testing( $a );
function testing( $myClassObj )
{
echo $myClassObj->hello();
}
And to answer your final question - in PHP5 - class members not explicitly declared with an access modifier become implicitly public.

If you want to use $a in the function, you need to either put
global $a;
as the first line of the function, or access it as $GLOBALS['a']

use this
function testing()
{
global $a;
echo $a ->hello();
}

A couple of things I would change here, I'll explain in a moment.
A.php
<?php
error_reporting(E_ALL);
ini_set("display_errors",1);
class myClass
{
// Here, access modifier.
public function hello()
{
return 'hello';
}
}
?>
B.php
<?php
error_reporting(E_ALL);
ini_set("display_errors",1);
require_once('/A.php');
testing();
function testing()
{
// Here, change where variable is defined to place it in scope.
$a = new myClass();
echo $a ->hello();
}
?>
When no access specifier is given on a method, it defaults to public. However, it is generally better to just declare what you want the method to have. You will appreciate this if you find yourself actively coding in multiple languages as they will each have a different default.
Right now the variable $a is not in the scope of the function testing(). Allow me to rearrange your program and you shall see why. You could have written it, like so:
B.php
<?php
function testing()
{
echo $a ->hello();
}
error_reporting(E_ALL);
ini_set("display_errors",1);
require_once('/A.php');
$a = new myClass();
testing();
?>
You see, where testing() is now defined, $a does not exist. It hasn't been defined yet. So it is not inside testing()'s scope. You'll have to either define $a inside testing() or else pass it in as a parameter. In my first pass, I changed your code to define $a inside testing(). If you will need to use it in multiple functions, then I would suggest changing testing() to take it as a parameter. Like this:
function testing(myClass $a) {
echo $a->hello();
}
Then pass it in this way:
$a = new myClass();
testing($a);

I believe $a is not defined in the function. Try using global $a first, and then calling hello().

Related

Do I need to declare a variable before initialise it in PHP constructor

I have a question about variable declare in PHP, I know this question may be little bit stupid. I have the following code
<?php
Class Test{
function __construct(){
$this->test = 'helloworkd';
}
function test(){
echo $this->test;
}
}
$test = new Test();
$test->test();
It seems like I can use the test variable without declaring it. My question is why the test() method can access the test variable? Is the test a global variable?
Thanks for your help!
My question is why the test() method can access the test variable?
PHP unlike some other languages allows you to assign values to variables without first declaring them. The interpreter will initialize them for you. This is poor practice because it makes code harder to read and debug, and because it can cause errors if you try to read a variable that was never declared:
<?php
$nonexistentArray['key'] = 7; //Bad practice, but PHP won't complain
$a = $fakeArray['key']; //Undefined variable error
Even in the second case, PHP will continue to execute the rest of the script, but it will complain.
Is the test a global variable?
No. It lives in the local scope.
<?php
function myFunc(){
//$arr was never declared, but PHP won't complain
$arr['key'][]=7;
}
myFunc();
//Undefined var error. The $arr that was initialized in myFunc is not global
print_r($arr);
A good IDE will complain if you try to use a variable that you never declared. In your case, when in the constructor you do:
$this->test = 'helloworkd';
PHP will initialize this class property for you. Now the rest of your code can use it, including the test() method. If it seems like a global var, it's not. It's a class property. If you tried to access it as just test from outside the class, you would not be able to. You'd have to use the accessor operator -> in $test->test or $this->test.
Many "test"! You have asign test="helloworld" in the contructor, so it takes a value for every new Test() is made.
$x = new Test();
$y = new Test();
echo $x->test(); //"helloworld"
echo $y->test(); //"helloworld"
I would declare your variable. This makes the code more readable for yourself any any others that see your code.
For example:
<?php
Class Test {
public $test;
function __construct($test){
$this->test = $test;
}
function test(){
echo $this->test;
}
So now we have a public variable that is accessible through an instance of this class by calling
$instance->test;
If you do not want this then you can change public to private or protected
You can read about this here: http://php.net/manual/en/language.variables.scope.php
Whatever you pass as an argument when creating an instance of this class will be assigned to the $test variable.
My question is why the test() method can access the test variable?
It can't. It is trying to access a constant test, if you want to access the class variable, use $this->test.
For example:
<?php
echo foo;
Will echo out a string "foo" and also spits out a notice: Use of undefined constant foo - assumed 'foo' in ...
<?php
class test{
public $test;
public function __construct(){
$this->test = 'helloworkd';
}
$newtest = new Test();
echo $newtest->test;
?>

require file inside function PHP

I have two classes, class A and class B, and in a function in class A I want to call a function in B, but the it also requires constants from another file. After requiring both the config.php and classB.php files, I am able to create an instance of class B, but when I try to call the function in B, it gives me a warning saying the constant has not been defined.
In config.php:
$constant = 'blah';
Inside class A I have:
function functionA() {
require_once "config.php";
require_once "classB.php";
$b = new B();
$b -> functionB($constant);
}
The call to function B is giving an error saying $constant is not defined, but when I call new B() there is no problem. Am I doing something wrong?
Aron is correct. In this case you want to use include or require. You must make sure that you have no function or class declarations in the files you're including though.
This is occurring because the require will not occur on every call to the method, just the first. The subsequent calls to the method will result in an undefined variable error.
Additional top tip: You can return values from included files to assign them directly to a variable
A.php:
return 'abc';
B.php:
Class B {
public static function load()
{
$x = include 'A.php';
var_dump($x);
}
}
I imagine that your code should look as follows:
function functionA() {
require "config.php";
require_once "classB.php";
$b = new B();
$b -> functionB($constant);
}
use the sentence include 'config.php';
instead of require_once, if your config.php file just has variable declarations.

How can I emulate PHP's crazy global thing?

If I have a file a.php which I can't edit.
<?php
$a = 1;
function a() {
global $a;
echo $a;
}
a();
then running php a.php prints 1 nicely. But if I have b.php:
<?php
function b() {
include "a.php";
}
b();
Then running php b.php doesn't print anything.
What can I type before the include "a.php" to make it behave the same without editing a.php?
(Obviously other than defining $a. In my real-world example it has to work for a complicated a.php).
Try adding a global into your new function:
function b() {
global $a;
include "a.php";
}
At the moment I wonder if PHP is treating $a as local to your b() function.
Addendum: in response to your comment, it seems that you need to grab arbitrary variables that your include has created locally in your function, and remake them as global. This works for me on 5.3.20 on OSX 10.6.8:
function b() {
include 'a.php';
// Move variables into global space
foreach (get_defined_vars() as $name => $value) {
global $$name;
// global wipes the value, so just reset it
$$name = $value;
echo "Declared $name as global\n";
}
}
b();
// Your global vars should be available here
Obviously you can remove the echo once you're happy it works.
Defining a function inside a function? Yuck. But I guess you have a real-world situation that doesn't allow any other way. But for the record, this is REALLY BAD PRACTICE
Adding global $a to b() should work.
function b() {
global $a;
include "a.php";
}
I don't know what variables need to be defined. a.php is really complicated
Then the only way I can think of is not using a function in b.php, so you're in the global scope when including a.php. I can see no other way.
It sounds like a.php is some legacy or 3rd party script that you have to wrap in your own application. I had a similar problem once and the solution was not pretty. First, you will have to find out, what global variables exist (grep global or similar helps).
This is the relevant part of my "Script Adapter" class:
private function _includeScript($file, $globals)
{
foreach ($globals as $global) {
global $$global;
}
ob_start();
require $file;
$this->_response->setBody(ob_get_clean());
}
As you see, I had to catch the output too. The class also emulates $_GET and catches header calls to assign everything to a Response object, but for your case only this method is important. It gets called with the file name and an array of global variable names as parameters:
_includeScript('a.php', array('a'));

Scope loss in included files in php

There are a few posts relevant to this but I'm not seeing anything near to the situation I'm struggling with.
I've inherited a rather large codebase which the original designer has taken some interesting methods of design. I'm attempting to call a method of a class that's defined. The class file itself has some global variables set. I call this method from a function, where also, I've included this file. When the method runs, the global variables are no longer defined. See below:
My File:
<?php //myScript.php
echo("Calling foo(): ");
foo();
function foo() {
include '../../php/class.bar.php';
$bar = new bar();
$bar->doSomething();
}
?>
../../php/class.bar.php:
$GLOBAL_ARRAY_ONE[0] = 'Here I am';
$GLOBAL_ARRAY_ONE[1] = 'JT';
class bar {
public $itsFoo = array();
public $itsBar = array();
public function doSomething() {
global $GLOBAL_ARRAY_ONE;
$this->itsFoo[0] = $GLOBAL_ARRAY_ONE[0];
$this->itsFoo[1] = $GLOBAL_ARRAY_ONE[1];
var_dump($this->itsFoo);
}
}
So, when I run "myScript.php" The output is: calling foo(): NULL
I personally wouldn't declare global arrays in a script like that but, I see no reason why I shouldn't have access to them.
Any ideas? Thanks!
Since you include the file inside a function - GLOBALS cannot be defined there (neither a class). What you probably want to do is to include class.bar.php outside (of foo()):
<?php //myScript.php
include '../../php/class.bar.php';
echo("Calling foo(): ");
foo();
function foo() {
$bar = new bar();
$bar->doSomething();
}
?>

Static variables in PHP

I have found different information regarding static variables in PHP but nothing that actually explains what it is and how it really works.
I have read that when used within a class that a static property cannot be used by any object instantiated by that class and that a static method can be used by an object instantiated by the class?
However, I have been trying to research what a static variable does within a function that is not in a class. Also, does a static variable within a function work somewhat like closure in javascript or am I totally off in this assumption?
I have read that when used within a class that a static property cannot be used by any object instantiated by that class
It depends on what you mean by that. eg:
class Foo {
static $my_var = 'Foo';
}
$x = new Foo();
echo $x::$my_var; // works fine
echo $x->my_var; // doesn't work - Notice: Undefined property: Foo::$my_var
and that a static method can be used by an object instantiated by the class???
Yes, an instantiated object belonging to the class can access a static method.
The keyword static in the context of classes behave somewhat like static class variables in other languages. A member (method or variable) declared static is associated with the class and rather than an instance of that class. Thus, you can access it without an instance of the class (eg: in the example above, I could use Foo::$my_var)
However, I have been trying to research what a static variable does within a function that is not in a class.
Also, does a static variable within a function work somewhat like closure in javascript or am I totally off in this assumption.
Outside of classes (ie: in functions), a static variable is a variable that doesn't lose its value when the function exits. So in sense, yes, they work like closures in JavaScript.
But unlike JS closures, there's only one value for the variable that's maintained across different invocations of the same function. From the PHP manual's example:
function test()
{
static $a = 0;
echo $a;
$a++;
}
test(); // prints 0
test(); // prints 1
test(); // prints 2
Reference: static keyword (in classes), (in functions)
static has two uses in PHP:
First, and most commonly, it can be used to define 'class' variables/functions (as opposed to instance variables/functions), that can be accessed without instantiating a class:
class A {
public static $var = 'val'; // $var is static (in class context)
public $other_var = 'other_val'; // non-static
}
echo A::$var; // val
echo A::$other_var // doesn't work (fatal error, undefined static variable)
$a = new A;
echo $a->var // won't work (strict standards)
echo $a->other_var // other_val
Secondly, it can be used to maintain state between function calls:
function a() {
static $i = 0;
$j = 0;
return array($i++, $j++);
}
print_r(a()); // array(0, 0)
print_r(a()); // array(1, 0)
print_r(a()); // array(2, 0)
//...
Note that declaring a variable static within a function works the same regardless of whether or not the function is defined in a class, all that matters is where the variable is declared (class member or in a function).
A static variable in a function is initialized only in the first call of that function in its running script.
At first i will explain what will happen if static variable is not used
<?php
function somename() {
$var = 1;
echo $var . "<br />";
$var++;
}
somename();
somename();
somename();
?>
If you run the above code the output you gets will be 1 1 1 . Since everytime you called that function variable assigns to 1 and then prints it.
Now lets see what if static variable is used
<?php
function somename() {
static $var = 1;
echo $var . "<br />";
$var++;
}
somename();
somename();
somename();
?>
Now if you run this code snippet the output will be 1 2 3.
Note: Static keeps its value and stick around everytime the function is called. It will not lose its value when the function is called.
class Student {
static $total_student = 0;
static function add_student(){
return Student::$total_student++;
}
}
First: for the add_student function, the best practice is to use static not public.
Second: in the add_student function, we are using Student::$total_student,not use $this->total_student. This is big different from normal variable.
Third:static variable are shared throughout the inheritance tree.
take below code to see what is the result:
class One {
static $foo ;
}
class Two extends One{}
class Three extends One{}
One::$foo = 1;
Two::$foo = 2;
Three::$foo = 3;
echo One::$foo;
echo Two::$foo;
echo Three::$foo;`

Categories