I have this class and I want to get the values in second method runSecond from Gettest method. How would I do that?
class Test {
public static function Gettest($x, $y, $z){
$x = $x;
$x = $x . basename($y);
self::runSecond();
}
private function runSecond(){
//how do I access $x here? I need to know the value of $x, $y and $z here
// and I dont want to pass it like this self::runSecond($x, $y, $z)
}
}
Why do you not want to pass the values into your second method?
Method parameters are the accepted way of doing this.
The only other option you have is to use global or member variables, but for something like this I would highly suggest parameters instead. There is no good reason I can see not to.
If you really, absolutely, have to do this (and I still don't see why), you can use a private member variable like this:
class Test {
private $x;
private $y;
private $z;
public static function Gettest($x, $y, $z){
$x = $x;
$x = $x . basename($y);
$test = new Test();
$test->x = $x;
$test->y = $y;
$test->z = $z;
$test->runSecond();
}
private function runSecond(){
$this->x;
$this->y;
$this->z;
}
}
Note that you have to create an instance of the class to call the second method. Your original way of using self:: would not work to call a non static method, even if you did pass the values as parameters.
Related
This is mostly an imaginary problem, no real life situation, but it's simply do depict with.
In this example we cache a point to a directory. I used to have
common.php
define('PATH_TO_CACHE', '/var/www/cache');
pixel.php
class Pixel
{
private int $x, $y;
public function __construct(int $x, int $y)
{
$this->x = $x;
$this->y = $y;
}
public function draw()
{
// drawing...
file_put_contents(PATH_TO_CACHE.'/test.php', var_export([$this->x, $this->y], true));
}
}
$a = new Pixel(1,4);
$b = new Pixel(4,1);
$c = new Pixel(1,1);
this is so far very simple, but that way it's not so flexible, our code is tight to PATH_TO_CACHE.
After refactoring:
class Pixel
{
private readonly int $x, $y;
private readonly string $pathToCache;
public function __construct(int $x, int $y, string $pathToCache)
{
$this->x = $x;
$this->y = $y;
$this->pathToCache = $pathToCache;
}
public function draw()
{
// drawing...
file_put_contents($this->pathToCache.'/test.php', var_export([$this->x, $this->y], true));
}
}
this is then fully independent now, but how do we instantiate Pixel?
$a = new Pixel(1,4, '/var/www/cache');
$b = new Pixel(4,1, '/var/www/cache');
$c = new Pixel(1,1, '/var/www/cache');
now let me not summarize why it is bad, starting out from redundancy nightmare.
But I cant figure a real solution. How to do it? And let's try keep this object immutable. And Pixel itself cant have that constants, since what if this Pixel can be reused among totally different projects?
I just learned about php anonymous functions and found out that the following code is correct:
Example1:
//$mysqli = new mysqli(...)
(function($x, $y, $conn) {
echo $x, $y; //$x and $y are not visible outside
})(786, 333, $mysqli);
Over the internet I have found examples like
Example2:
$x = 786; $y = 333;
(function($x, $y) {
echo $x, $y;
})();
Or
Example3:
$x = 786; $y = 333;
(function() use($x, $y){
echo $x, $y;
})();
I couldn't find any php documentation or code on stackoverflow which suggest example1 is correct syntax. Please tell me with official reference if example1 like syntax is allowed in php.
The first example is effectively defining the function and then calling it with the values. Something like...
(definition of function)(values to pass);
You can split into two parts to show how this works...
$fn =function($x, $y, $conn) {
echo $x, $y; //$x and $y are not visible outside
};
($fn)(786, 333, $mysqli);
//$mysqli = new mysqli(...)
(function($x, $y, $conn) {
echo $x, $y; //$x and $y are not visible outside
})(786, 333, $mysqli);
This is perfectly valid, and just follows from two things:
The function(...) { ... } syntax creates and returns a Closure object
A Closure object can be invoked directly as though it was a function name
There is no special syntax, it's just one of an infinite number of ways you can put the building blocks of PHP together.
There are lots of other combinations you can do for the same reason, e.g.:
class Foo
public static function make_function() {
return function($x, $y, $conn) {
echo $x, $y;
};
}
}
(Foo::make_function())(786, 333, $mysqli);
But also:
class Foo
public static function make_function($conn) {
return function($x, $y) use ($conn) {
echo $x, $y;
};
}
}
(Foo::make_function($conn))(786, 333, $mysqli);
As with your example, specifying a use clause doesn't make much difference in this specific case because we're executing the function straight away. But it allows you to "capture" a value in one place and then pass the other arguments later, e.g.
class Foo
public static function make_function($conn) {
return function($x, $y) use ($conn) {
echo $x, $y;
};
}
}
$f = Foo::make_function($mysqli);
// later...
$f(786, 333);
In the code below I would expect that real_change and change methods to change the variable $n passed by reference in the constructor.
abstract class y {
private $x;
function __construct(&$x) {
$this->x = &$x;
}
function real_change() {
$this->x = 'real change';
}
}
class x extends y {
function change() {
$this->x = 'changed';
}
}
$n = 'intact';
$c = new x($n);
$c->change();
echo $n.PHP_EOL; // prints "intact"
$c->real_change();
echo $n.PHP_EOL; // prints "real change"
Why is this happening?
How could I achieve to create a method in an abstract class that modifies a variable referenced in a property?
Many thanks.
In your abstract class, $x is marked as private, so it's not available to your extended class. $this->x will essentially just create a new public $x variable in class x.
If you set the variable to protected it will give access to all extended classes, and allow you to set it properly.
See updated playground here.
More information on visibility via the PHP docs, can be found here.
I'm learning php oop and seems like i still do not understand of how some things work as my code, which, imo, looks properly doesn't work and returns few errors. This is the code:
<?php
class Vector {
private $x;
private $y;
public function __construct($x, $y) {
if (is_nan($x) || is_nan($y)) {
$this->x = 0 && $this->y = 0;
} else {
$this->set($x, $y);
}
}
public function __destruct() {
var_dump($x, $y);
}
public function setx($x) {
if (is_numeric($x)) {
$this->x;
}
}
public function sety($y) {
if (is_numeric($y)) {
$this->y;
}
}
public function retLength() {
return $x;
}
public function addVector() {
$sum=$x+$y;
}
public function dotProduct() {
$dot_product = array_sum(array_map(function($x,$y) { return $x*$y; }, $array1, $array2));
}
}
$wekt= new Vector($x, $y);
echo $wekt->addVector(5,7);
Errors i get are: undefined variables "x" and "y" on line 42 (which is $wekt= new Vector($x, $y); ) and "Call to undefined method Vector::set()".
Specification for this class is:
two private attributes $x and $y (seems to be ok)
constructor receives $x and $y and on receive checks if these are numbers. Constructor is supposed to output message about just created vector.
I do not understand much all this constructor and probably this is one of reasons why this code doesn't work as it is intended to.
destructor is supposed to output info about destroyed object.
there should be available functions to change values of $x and $y
there should be available function to return $x
two more functions: one outputting sum of two vectors, second function supposed to output scalar product which takes as value a number.
There are two things in your code going wrong. See the following code:
class Vector {}
$wekt= new Vector($x, $y);
echo $wekt->addVector(5,7);
Where are $x and $y defined? This is the main reason you are getting the error. You class has a different scope then the global scope, meaning everything you define there is only accessible by $wekt-> as $wekt is defined in the global scope.
Now the second thing is addVector():
echo $wekt->addVector(5,7);
You ask to echo the return of this method, yet no return is defined in that function. Secondly where is the $x and $y defined within the scope of that function?
Change it to something like:
class Vector {
private $list = [];
public function addVector($x, $y) {
$this->list[] = new Vector($x, $y);
return $x + $y;
}
}
I need to check if two PHP object are equal in terms of equal values. Of course I could easily add an isEqualTo(...) method to the class that compares all relevant values. However the concrete class will change in the near future and I would like to know if there is any automated way to do this.
Example:
class Contact {
private name; // String
private phone; // Int
private someObject; // Custom Object
public function getName() {
return $this->name;
}
public function setName($newName) {
$this->name = $newName;
}
public function getPhone() {
return $this->phone;
}
public function setPhone($newPhone) {
$this->phone = $newPhone;
}
public function getSomeObject() {
return $this->someObject;
}
public function setSomeObject($newObj) {
$this->someObject = $newObj;
}
// Manual Solution
public function isEqualTo($contact) {
result = $this->name == $contact->getName();
result &= $this->phone == $contact->getPhone();
result &= $this->someObject == $contact->getSomeObject();
return result;
}
}
This would obviously work. Of course I am aware of the the limitation of comparing someObject (need to be the exact some object to be true) but this is OK.
However the class Contact will be extended in the near future. Everytime I add new properties/values to the class I have to add them to isEqualTo as well. No big deal but a little bit cumbersome.
So, is there any way to implement isEqualTo to automatically all available public properties?
I found get_class_vars and get_object_vars but these methodes will not work with getters and setters but only with vars that can be accessed directly.
I found get_class_methodes but this return all methodes and not only getters and setters. Filtering the methodes names by get... and set... would work of course, but this would be more like a hack than a "nice and clean" soltution.
In short: Is there any "correct" way to automatically check two PHP object for equality?
I wouldn't go so far as to say that this is the "correct" way, but since you don't want to implement/maintain your own comparison function/method you might be interested in php's default behaviour including the comparison of protected/private properties:
<?php
class Foo {
private $x,$y,$z;
public function __construct($x,$y,$z) {
$this->x = $x;
$this->y = $y;
$this->z = $z;
}
}
$f1 = new Foo(1,2,3);
$f2 = new Foo(4,5,6);
$f3 = new Foo(1,2,3);
var_dump(
$f1==$f2,
$f1==$f3
);
prints
bool(false)
bool(true)
which might or might not be sufficient for you.
As pointed out by Alma Do, circular references like e.g.
<?php
class Foo {
private $x,$y,$z;
public function __construct($x,$y,$z) {
$this->x = $x;
$this->y = $y;
$this->z = $z;
}
public function setZ($z) {
$this->z = $z;
}
}
$f1 = new Foo(1,2,3);
$f2 = new Foo(4,5,6);
$f3 = new Foo(1,2,3);
$f1->setZ($f3);
$f3->setZ($f1);
var_dump(
$f1==$f2,
$f1==$f3
);
will cause a Fatal error: Nesting level too deep - recursive dependency?.
You could use Reflection to do this, but i don't think it's a good idea. Maybe serialize() is a better solution?
function isEquals(self $obj){
return serialize($obj)===serialize($this)
}