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;
}
}
Related
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);
I'n just learning PHP by myself, and I have a question, hope you will be able to help.
In fist style
<?php
class Fist_style
{
function method_1()
{
global $a;
return $a + 1;
}
function method_2()
{
global $a;
return $a - 1;
}
function method_3()
{
$call_1 = $this->method_1();
$call_2 = $this->method_2();
}
// In this case, how many times $a was called?
}
In second style
<?php
class Second_style
{
function method_1($a)
{
return $a + 1;
}
function method_2($a)
{
return $a - 1;
}
function method_3()
{
global $a;
//I will call both method_1 and method_2
$call_1 = $this->method_1($a);
$call_2 = $this->method_2($a);
//............
}
// In this case, how many times $a was called
}
?>
The questions are inside my code, and what style will better when develop?
Using globals is very often a recipe for disaster - as many people with experience will be happy to tell you.
The normal way of having state in a class is declaring a class property:
<?
class MyClass
{
public $a;
function __construct($valueForA) {
$this->a = $valueForA;
}
function increment()
{
$this->a += 1;
}
function decrement()
{
$this->a -= 1;
}
function plusminus()
{
$this->increment();
$this->decrement();
}
}
Which can be used like so:
$anInstance = new MyClass(10); // sets a to 10 by calling the __construct method
$anInstance->increment();
echo($anInstance->a); // 11
$anInstance->decrement();
echo($anInstance->a); // 10
Read more about oop in PHP here.
As for the question in your code, the $a is not a method, so it can't be called.
Also, return $a -1; does not change the global $a (not sure if this was the intention).
Edit:
If you have a function increment like
function increment ($var) {
$var = $var - 1;
return $var;
}
then the $var is passed in as a value - if you passed in a 5, php only cares about 5, not the name. Example:
$a = 5;
$incremented = increment($a);
echo($a); // echoes 5;
echo($incremented); //echoes 6
I would suggest reading up on scoping in php.
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)
}
This question already has answers here:
php call class function by string name
(6 answers)
Closed 8 years ago.
In PHP5, variables can be evaluated as functions1 such as:
function myFunc() {
echo "whatever";
}
$callableFunction = 'myFunc';
$callableFunction(); // executes myFunc()
Is there any syntax for assigning object member functions to a variable such as:
class MyClass {
function someCall() {
echo "yay";
}
}
$class = new MyClass();
// what I would like:
$assignedFunction = $class->someCall; // but I tried and it returns an error
$memberFunc = 'someCall';
$class->$memberFunc(); // I know this is valid, but I want a single variable to be able to be used to call different functions - I don't want to have to know whether it is part of a class or not.
// my current implementation because I don't know how to do it with anonymous functions:
$assignedFunction = function() { return $class->someCall(); } // <- seems lengthy; would be more efficient if I can just assign $class->someCall to the variable somehow?
$assignedFunction(); // I would like this to execute $class->someCall()
There is a way, but for php 5.4 and above...
class MyClass {
function someCall() {
echo "yay";
}
}
$obj = new Myclass();
$ref = array($obj, 'someCall');
$ref();
Hm.. actually it works for static too, just use the reference by name..
class MyClass {
static function someCall2() {
echo "yay2";
}
}
$ref = array('MyClass', 'someCall2');
$ref();
And for nonstatic this notation works as well. It creates a temporary instance of the class. So, this is what you need, only you need php 5.4 and above )
The PHP 5.4 solution above is good. If you need PHP 5.3, I don't think you can do much better than the anonymous function approach, but you could wrap that into a function that acts very similar to the PHP 5.4 method:
function buildCallable($obj, $function)
{
return function () use ($obj, $function) {
$args = func_get_args();
return call_user_func_array(array($obj, $function), $args);
};
}
//example
class MyClass
{
public function add($x, $y)
{
return $x + $y;
}
public static function multiply($x, $y)
{
return $x * $y;
}
}
//non-static methods
$callable = buildCallable(new MyClass(), 'add');
echo $callable(32, 10);
//static methods
$callable = buildCallable('MyClass', 'multiply');
echo $callable(21, 2);
This should work for any number of arguments to any (publicly visible) method.
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.