I'm at a loss. I have gone over my two classes extensively for hours. Nothing is static, nothing is being statically referenced, yet I cannot get rid of this error.
Class A's file (ClassA.php)
<?php
namespace MyProject\A;
require_once "B.php";
use MyProject\B as B;
class A
{
private $privateVariable;
public function __construct()
{
$b = new B\B();
$this->privateVariable = $b->something;
}
}
Class B's file (B.php)
<?php
namespace MyProject\B;
class B
{
public $something;
public function __construct()
{
$this->something = "Some (dynamic) string value";
}
}
I am not new to classes, however I've never had this issue before (without having at least a static variable or method or static reference).
The errors I get are:
Strict Standards: Accessing static property MyProject\B\B::$something as non static in A.php on line (this line: $this->privateVariable = $b->something)
and
Notice: Undefined property: MyProject\B\B::$something in A.php on line (this line: $this->privateVariable = $b->something)
I think anyone reading this understands that I want to get B's variable $something into A's variable $privateVariable while maintaining class B as an instance within class A upon instantiation of class A like:
<?php
namespace MyProject\Something;
require_once "A.php";
use MyProject\A as A;
$a = new A\A()
// $a's private variable $privateVariable should be set to "Some (dynamic) string value"
Any help regarding this issue is greatly appreciated!
EDIT
Changed code to better reflect original code (changing use AS to use as and changing the way use was calling the appropriate classes
PHP Version: 5.6
EDIT 2
I honestly have no idea what was going on.
I uploaded my files to the server
I then checked that they were uploaded properly
I was still receiving those errors
I then commented all my code except the lines above
I still received the error
I then uncommented the lines I had just commented out (using CTRL+Z)
I then reuploaded the document
I ensured that they were uploaded properly
Now everything works.
I apologize for this issue but I think it was more of a bug than an actual code issue. I'll just blame Godaddy for this one (yes, I know Godaddy is great choice sarcasm)
Here, full working single file example:
namespace MyProject\ClassA {
use MyProject\ClassB\B;
class A {
private $privateVariable;
public function __construct() {
$b = new B();
$this->privateVariable = $b->something;
print $this->privateVariable;
}
}
}
namespace MyProject\ClassB{
class B{
public $something;
public function __construct()
{
$this->something = "Some (dynamic) string value";
}
}
}
namespace MyProject\Something {
use MyProject\ClassA\A;
$a = new A();
}
Test it.
Update:
You use :
use MyProject\A as A;
$a = new A\A();
But use MyProject\A point to a namespace not a class.
So this is right:
use MyProject\A\A as A;
$a = new A();
And another note use this : use \MyProject\A\A with \ at first place.
I think your namespaces are incorrect. My bet is PHP couldn't instantiate the class and assumed you were calling it statically. I cleaned up the namespaces and created one giant file and it runs fine
namespace MyProject\ClassB;
class B
{
public $something;
public function __construct()
{
$this->something = "Some (dynamic) string value";
}
public function getStr() {
echo $this->something;
}
}
namespace MyProject\ClassA;
use \MyProject\ClassB\B as B;
class A
{
private $privateVariable;
public function __construct()
{
$b = new B();
$this->privateVariable = $b->something;
$b->getStr();
}
}
namespace MyProject\Something;
use \MyProject\ClassA\A as A;
$a = new A();
There's an observation worth noting: You don't write use ... AS ... you write use ... as .... AS should be all lower cases. Therefore; the correct use statement should have read: use MyProject\ClassB as cB. The Code-Excerpt below will illustrate these points.
<?php
namespace MyProject;
require_once "ClassB.php";
use MyProject\B as cB;
class A {
private $privateVariable;
public function __construct() {
$b = new cB();
$this->privateVariable = $b->getSomething();
}
}
?>
<?php
namespace MyProject;
class B{
public $something;
public function __construct(){
$this->something = "Some (dynamic) string value";
}
// YOU MAY WANT TO CREATE A FUNCTION TO GET THE SOMETHING
public function getSomething(){
return $this->something;
}
}
Or using aliasing....
<?php
namespace MyProject\ClassA;
require_once "ClassB.php";
use MyProject\ClassB as cB;
class A {
private $privateVariable;
public function __construct(){
$b = new cB\B();
$this->privateVariable = $b->getSomething();
}
}
?>
<?php
namespace MyProject\ClassB;
class B{
public $something;
public function __construct(){
$this->something = "Some (dynamic) string value";
}
// YOU MAY WANT TO CREATE A FUNCTION TO GET THE SOMETHING
public function getSomething(){
return $this->something;
}
}
To run the code (The First Example - without Aliasing):::
<?php
namespace MyProject\Something;
use MyProject\A as A;
require_once "A.php";
require_once "B.php";
$a = new A();
var_dump($a);
// PRODUCES:::
object(MyProject\A)[1]
private 'privateVariable' => string 'Some (dynamic) string value' (length=27)
Test it out yourself HERE.
Related
I have written two class at two different file, for example file classA.php and classB.php, the file written below.
file classA.php
class a {
public function __construct() {
require_once('classB.php');
$classB = new b();
}
}
$classA = new a();
file classB.php
class b {
public function __construct() {
echo "Hello World!";
}
}
And the code work fine, and output Hello World! as well. But when I write both of the class like this
class a {
public function __construct() {
class b {
public function __construct() {
echo "Hello World!";
}
}
$classB = new b();
}
}
$classA = new a();
It showing an error
Fatal error: Class declarations may not be nested
Which i think both of them should be do the same thing, yesterday i found something about "arbitrary places" but i don't find the correct answer for what it is.
I just want to know why both of them, showing different result? or maybe something about include or require that i didn't know?
NOTE
I'm not asking what the different between require() and include() functions
Your answer is in the PHP documentation:
When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward. However, all functions and classes defined in the included file have the global scope.
So, unlike for variables, it doesn't matter where the require_once line is: the class will always be at the global scope.
Note that even the namespace of the including file is not applied to the included file, so the included functions and classes are not just in the global scope but also the root namespace.
You are not allowed to define a class within the definition of another class (unless using the new anonymous class features I'm guessing).
You can define multiple classes within the same file but not one class within the code of another class.
If using Composer to generate classmap based autoloading it will correctly work with multiple classes defined in 1 file.
class a {
public function __construct() {
require_once('classB.php');
$classB = new b();
}
}
$classA = new a();
Is not same as
class a {
public function __construct() {
class b {
public function __construct() {
echo "Hello World!";
}
}
$classB = new b();
}
}
This willl also work:
require_once('classB.php');
class a {
public function __construct() {
$classB = new b();
}
}
$classA = new a();
if you use include() or require(). That means You can use their properties like variable,methos,etc.
Example: You have vars.php file
<?php
$color='red';
$car='BMW';
?>
THen You can use $color and $car in html like this :
<h1>Welcome to my home page!</h1>
<?php include 'vars.php';
echo "I have a $color $car.";
?>
class is something like properties. You can use by creating instance of that.
You will get more idea from source
So I came across a code like this and it makes use of one of the Bar class properties called testObj while it's not defined so I expected this to be wrong but I tested it my own and no errors:
<?php
class Foo{
public function __construct()
{
echo 'Echo From Foo';
}
}
class Bar{
public function __construct(Foo $foo)
{
$this->testObj = $foo;
}
}
$bar = new Bar(new Foo);
Why is that so? Does this have anything to do with the "Dynamic/Loose Type"ness of PHP or something else?
Properties can be defined dynamically and their visibility is defaulted to public as can be seen in the example below:
class X {
public function test()
{
$this->y = 'test';
}
}
$x = new X();
$x->test();
echo $x->y; // test
You can also do this without being in the class, so if I wanted to add another property, I could just do the following:
class X {
public function test()
{
$this->y = 'test';
}
}
$x = new X();
$x->test();
echo $x->y; // test
$x->z = 'blah';
echo $x->z; // blah
Remember, when a class in instantized it is just an object which can be manipulated as any other object.
Note: If I don't call test() in the above code, it will result it an error (undefined property) because the variable has not been defined except in the test() function.
Live Example
Repl
This is perfectly normal, you can dynamicaly assign every propteries to a PHP class without error. Event if you should declare it properly to keep track of your object structure.
If you want it to throw an error, you can use the __get magic function and ReflectionClass to determine wich property is setted and wich you can't set even if I didn't see any advantage of doing this.
I'm absolutely sure this has been asked before, but I cannot find it anywhere.
So I have two classes. A and B
class classA
{
public $var1;
public $classbVar;
public function init()
{
// This is here because other script is run before it is called
// in the live code.
// it basically checks that the file exists. There is a reason for this.
if (file_exists('classB.php'))
{
require_once('classB.php');
}
else
{
echo "An error has occurred loading the second class.";
}
$this->var1 = "something";
$this->classbVar = new classB
echo $this->classbVar->doSomething();
}
}
In a separate file
class classB extends classA
{
public function doSomething()
{
echo $this->var1;
}
}
In a third file, I'm calling classA and running the init function. This is not real code, but identical to what I have written.
So why doesn't this work. if I VAR_DUMP I get null.... What have I done wrong or misunderstood?
LET ME BE MORE CLEAR:
There is a third file which calls classA as below;
require_once('classA.php')
$classA = new classA;
$classA->init();
My apologies for any confusion, I did this on the fly a little bit, as I am sure I am missing something simple here. Surely the way I am trying to do this will work somehow.
There are 2 problems here that cause your output to be null:
You are generating a new $classA object and any values you set on that, will not automatically be set on the $classbVar object as that is a completely different object of a class that just extends the A class, not the $classA object you have just generated. With the exception of a static property of course...
If you want to set the value of a property in an object, you need $this->var1 instead of $var1. Note if you set the value in your $classA object, it is still not set for the $classbVar object.
Put require_once above class declaration (this is not big issue but it's more clear)
Assign variables to class properties because they way you did the scope of them is only within the method.
$var1 = "something";
should be changed to
$this->var1 = "something";
Also the class values are not shared unless they are declared as static. So to access the properties from parent class you can do following:
class classA
{
public $var1;
public function init()
{
$this->var1 = "something";
}
}
// other file
require_once("A class location");
class classB extends classA
{
public function doSomething()
{
echo $this->var1;
}
}
$b = new classB();
$b->init();
$b->doSomething();
or more clean way:
class A
{
protected $var1;
public function __construct()
{
$this->var1 = "something";
}
}
// other file
require_once("A class location");
class B extends A
{
public function doSomething()
{
return $this->var1;
}
}
$b = new B();
echo $b->doSomething();
// or shorter syntax
echo {new B()}->doSomething();
Instead of using require_once() it's better to use PSR-4 autoloader.
I searched everywhere but did not find any solution to this question.
Following is my code where I want to access the $myvar of the super class in the subclass but I don't know how? when I use $this keyword it accesses the variable in the same class but not the one in super class. please any help will be greatly appreciated.
<?php
class First{
protected $myvar = "First Class";
}
class Second extends First{
public $myvar = "Second Class";
function __construct(){
echo $this -> myvar;// here I want to access the $myvar of super class
}
}
$obj = new Second();
?>
Note: I can achieve the same functionality in java by using the super keyword.
You may create a custom function that returns the variables from the parent class BUT keep in mind that the variables should be "private":
class First{
private $myvar = "First Class";
protected function get_variable($var_name)
{
return $this->{$var_name};
}
}
class Second extends First{
public $myvar = "Second Class";
function __construct() {
echo parent::get_variable('myvar');
}
}
$obj = new Second();
The way you try to do this will not work, as Rizier mentioned. Maybe static properties can be useful to you (depending on your needs ofcourse)
<?php
class a {
protected static $var = 'a';
}
class b extends a {
protected static $var = 'b';
public function __construct() {
echo self::$var;
echo parent::$var;
}
}
$b = new b();
You could also reconstruct a in b. You'd be able to leverage the inheritance for methods and maybe other properties, while being able to use the default value in a-constructor.
<?php
class a {
protected $var = 'a';
}
class b extends a {
protected $var = 'b';
public function __construct() {
echo $this->var;
$a = new a();
echo $a->var;
}
}
$b = new b();
The main question I think you should answer is why you want a class to inherit from another but still want to be able to change/modify stuff in the parent. That's kinda counterproductive for the whole inheritance design.
You can't you are overwritten in when creating the sub class which inherits from the parent class. So you would have to change the name for it.
You override the parent parameter with:
public $myvar = "Second Class";
Remove this line to use the inherits from parent class or change the name of the child class parameter.
This question already has answers here:
Use global variables in a class
(4 answers)
Closed 10 years ago.
I'm starting with OOP in PHP and there is something I'd like to do. Let me show an example:
classes.php
<?php
class a {
public function a() {
echo 'a';
}
}
class b {
public function calla() {
$x->a();
}
}
?>
index.php
<?php
include('classes.php');
$x = new a();
$d = new b();
$d->calla();
?>
Is this possible? I know I can do something like:
class b {
public function calla($object) {
$object->a();
}
}
and
$d->calla($x);
but is the first example possible to do?
So you want to use $x as global variable? Syntax is the same, object or not:
class b {
public function calla() {
$GLOBALS['x']->a();
}
}
... or:
class b {
public function calla() {
global $x;
$x->a();
}
}
Of course, it's a horrible design that injects hard to track dependencies and will probably lead to unexpected side effects and head-scratching.
Additionally, a() is a poor method name for class a because it's the PHP 4 syntax for constructors. If you run this code:
<?php
class a {
public function a() {
echo 'a';
}
}
class b {
public function calla() {
$GLOBALS['x']->a();
}
}
$x = new a();
$d = new b();
$d->calla();
... you'll see that a() runs twice. Guess why?
I think I understand what you're trying to ask but you're mixing up parameters visibility concept with object passing in class methods. So let's clean up...
In your classes.php file the method calla() of the class b as absolutely nothing to do with class a, unless $x itself is an instance of the class a.
In your index.php file you instantiate $x as class a, but it is a global variable, and the class b has no visibility on it. Moreover, your call to $d->calla() would return an error because you are accessing a private method from outside.
Your third example gets closer to the solution, passing the instance to the calla() method helps class b seing the instance of class a, I guess you want to edit your index.php file to:
<?php
include('class.php');
$x = new a();
$d = new b();
$d->calla($x);
?>
But this still won't work until you change the private methods to public ones.