i'm new to php and am wondering - is it possible to initialize a class with parameters?
like $obj = new myClass('myID');
i've tried but it gave me an error.
maybe someone can point me to some good tutorials.
thanks
Yes it is, you need to pass the variables through the constructor:
class SomeClass
{
function __construct($some_var)
{
}
}
Please note that in older versions of php the constructor needs to have the name of the class, it´s __construct() since php 5.
Yes, you need to use a class constructor.
Example:
<?php
class ClassWithArgs
{
function __construct($argument1, $argument2)
{
echo "arg 1 = $argument1\n";
echo "arg 2 = $argument2\n";
}
}
$object = new ClassWithArgs('one', 'two');
?>
Example Output
arg 1 = one
arg 2 = two
I suggest you also take a look at the PHP5 OOP documentation, it includes simple examples to get you going: http://php.net/manual/en/language.oop5.php
Related
I've recently worked on some code in which I had to dynamically call a method inside a class.
The solution I ended up using was 2 lines, because the "dynamic" part was only a small section of the actual method name that I needed to call.
This is the solution I ended up using:
$pull = "pull_{$type}_day";
$day = $download->$pull();
Originally, I tried to make this a single line, but it did not work. In a technical sense, why does the above code work but the below code does not?
$day = $download->"pull_{$type}_day"();
If you use a string or part of a string as a method (or property) you need to surround it in {} like this:
#property
echo $foo->{"bar"};
#method call
echo $foo->{"bar"}();
So if you need a variable in the string part, this follows the same rules as any normal string.
echo $foo->{"bar".$bar}();
echo $foo->{'bar'.$bar.'bar'}();
echo $foo->{"bar{$bar}bar"}();
And so on. Here is a full example
class foo{
function pull_1_day(){
echo "bar";
}
}
$a = 1;
(new foo)->{"pull_{$a}_day"}();
Outputs
bar
Sandbox
This follows in the same way PHP allows you to use a string as a variable such as this:
$foo = 'bar';
echo ${"foo"};
Outputs
bar
Sandbox
Same kind of syntax.
Why not use call_user_func()?
I find it easier to read and parse.
Assuming you have:
class pull {
public function pull_foo_day () {
echo "hello";
}
}
$pull = new pull();
$type = "foo";
You can simply do:
call_user_func([$pull, "pull_{$type}_day"]);
Outputs:
hello
See it working here.
<?php
$ar = (object) array('a'=>function(){
echo 'TEST';
});
$ar->a();
?>
I get this error Call to undefined method
Update:
If you are using PHP 5.3 or greater, take a look at other answers please :)
I don't think that's correct syntax, it would give you:
Parse error: syntax error, unexpected T_FUNCTION in....
You need to create a class, add method to it, use new keyword to instantiate it and then you will be able to do:
$ar->a();
class myclass
{
public function a()
{
echo 'TEST';
}
}
$ar = new myclass;
$ar->a(); // TEST
See Classes and Objects for more information.
Anonymous or not, you have a callback function, thus you need to handle it as such. E.g.:
<?php
$ar = (object) array(
'a' => function(){
echo 'TEST';
}
);
call_user_func($ar->a);
?>
For some reason it doesn't seem possibly to run the closure the way you do.
If you modify your code and set another variable to the function, it can be called:
$ar = (object) array('a'=>function(){
echo 'TEST';
});
$a = $ar->a;
$a();
This is no solution. But from what I can see, this seems like a bug or limitation in PHP 5.3.
I am using 5.3.5 when trying this.
There is no function a() but the property a, so you should call it by $ar->a.
Anyway I don't think it's going to work the way you expect it to.
EDIT:
As suggested by Álvaro G. Vicario you should use call_user_func, not echo to call the function and it will work correctly.
Or, just for the fun of it, you can do something like this -
<?php
$ar = new stdClass;
$ar->a = function($to_echo){ echo $to_echo; };
$temp = $ar->a;
//[Edit] - $ar->a("hello"); // doesn't work! php tries to match an instance method called "func" that is not defined in the original class' signature
$temp("Hey there");
call_user_func($ar->a("You still there?"));
?>
i got some trouble to understand scope in OOP. What i want is that $foo->test_item() prints "teststring"...Now it just fails with:
Warning: Missing argument 1 for testing::test_item()
Thanks a lot!
<?php
class testing {
public $vari = "teststring";
function test_item($vari){ //$this->vari doesn't work either
print $vari;
}
}
$foo = new testing();
$foo->test_item();
?>
test_item() should be:
function test_item() {
print $this->vari;
}
There is no need to pass $vari as a parameter.
Well, you've declared a method which expects an argument, which is missing. You should do:
$foo->test_item("Something");
As for the $this->, that goes inside of the class methods.
function test_item(){
print $this->vari;
}
function parameters can not be as "$this->var",
change your class like
class testing {
public $vari = "teststring";
function test_item(){ //$this->vari doesn't work either
print $this->vari;
}
}
$foo = new testing();
$foo->test_item();
And read this Object-Oriented PHP for Beginners
What's happening there is that $foo->test_item() is expecting something passed as an argument, so for example
$foo->test_item("Hello");
Would be correct in this case. This would print Hello
But, you may be wondering why it doesn't print teststring. This is because by calling
print $vari;
you are only printing the variable that has been passed to $foo->test_item()
However, if instead you do
function test_item(){ //notice I've removed the argument passed to test_item here...
print $this->vari;
}
You will instead be printing the value of the class property $vari. Use $this->... to call functions or variables within the scope of the class. If you try it without $this-> then PHP will look for that variable within the function's local scope
I have three classes that all have a static function called 'create'.
I would like to call the appropriate function dynamically based on the output from a form, but am having a little trouble with the syntax. Is there anyway to perform this?
$class = $_POST['class'];
$class::create();
Any advice would be greatly appreciated.
Thanks.
If you are working with PHP 5.2, you can use call_user_func (or call_user_func_array) :
$className = 'A';
call_user_func(array($className, 'method'));
class A {
public static function method() {
echo 'Hello, A';
}
}
Will get you :
Hello, A
The kind of syntax you were using in your question is only possible with PHP >= 5.3 ; see the manual page of Static Keyword, about that :
As of PHP 5.3.0, it's possible to
reference the class using a variable.
The variable's value can not be a
keyword (e.g. self, parent and
static).
What you have works as of PHP 5.3.
ps. You should consider cleaning the $_POST['class'] since you cannot be sure what will be in it.
use call_user_func
heres an example from php.net
class myclass {
static function say_hello()
{
echo "Hello!\n";
}
}
$classname = "myclass";
call_user_func(array($classname, 'say_hello'));
call_user_func($classname .'::say_hello'); // As of 5.2.3
$myobject = new myclass();
call_user_func(array($myobject, 'say_hello'));
I believe this can only be done since PHP 5.3.0. Check this page and search for $classname::$my_static to see the example.
I may be misunderstanding what you want, but how about this?
switch ($_POST['ClassType']) {
case "Class1":
$class1::create();
break;
case "Class2":
$class2::create();
break;
// etc.
}
If that doesn't work, you should look into EVAL (dangerous, be careful.)
I have this:
one string variable which holds the class name ($classname)
one string variable with holds the property name ($propertyname)
I want to get that property from that class, the problem is, the property is static and I don't know how to do that.
If the property weren't static, it would have been:
$classname->$propertyname;
if the property were a method, I could have used call_user_function
call_user_func(array($classname, $propertyname));
But in my case, am I just lost. I am however hoping that it is possible. With the thousands of functions that PHP has, he'd better have something for this as well. Maybe I'm missing something?
Thanks!
Edit:
for those with eval() solutions: thanks, but it is out of the question
for those with get _class _vars() solutions: thanks, but it seems it returns "the default properties of the given class" (php.net), and yes, I would like that value to be changable (even though it does help me in some of the cases)
If you are using PHP 5.3.0 or greater, you can use the following:
$classname::$$propertyname;
Unfortunately, if you are using a version lower than 5.3.0, you are stuck using eval() (get_class_vars() will not work if the value is dynamic).
$value = eval($classname.'::$'.$propertyname.';');
EDIT: I've just said get_class_vars() wouldn't work if the value is dynamic, but apparently, variable static members are part of "the default properties of a class". You could use the following wrapper:
function get_user_prop($className, $property) {
if(!class_exists($className)) return null;
if(!property_exists($className, $property)) return null;
$vars = get_class_vars($className);
return $vars[$property];
}
class Foo { static $bar = 'Fizz'; }
echo get_user_prop('Foo', 'bar'); // echoes Fizz
Foo::$bar = 'Buzz';
echo get_user_prop('Foo', 'bar'); // echoes Buzz
Unfortunately, if you want to set the value of the variable, you will still need to use eval(), but with some validation in place, it's not so evil.
function set_user_prop($className, $property,$value) {
if(!class_exists($className)) return false;
if(!property_exists($className, $property)) return false;
/* Since I cannot trust the value of $value
* I am putting it in single quotes (I don't
* want its value to be evaled. Now it will
* just be parsed as a variable reference).
*/
eval($className.'::$'.$property.'=$value;');
return true;
}
class Foo { static $bar = 'Fizz'; }
echo get_user_prop('Foo', 'bar'); // echoes Fizz
set_user_prop('Foo', 'bar', 'Buzz');
echo get_user_prop('Foo', 'bar'); // echoes Buzz
set_user_prop() with this validation should be secure. If people start putting random things as $className and $property, it will exit out of the function as it won't be an existing class or property. As of $value, it is never actually parsed as code so whatever they put in there won't affect the script.
I think this is the simplest:
$foo = new ReflectionProperty('myClassName', 'myPropertyName');
print $foo->getValue();
To return a variable value that is set by a Static Variable you need to call:
$static_value = constant($classname.'::'.$propertyname);
Check out the documentation :: PHP Constant Documentation
You should be able to do something like:
eval("echo $classname::$propertyname;");
I just did a quick test and got this to work for me. Not sure if there's a better way or not, but I wasn't able to find one.
'eval' looks so close to 'evil', and I hate using it and/or seeing it in code. With a few ideas from other answers, here's a way to avoid it even if your php isn't 5.3 or higher.
Changed to reflect testing based on a comment.
class A {
static $foo = 'bar';
}
A::$foo = 'baz';
$a = new A;
$class = get_class($a);
$vars = get_class_vars($class);
echo $vars['foo'];
Outputs 'baz'.
One thing I noticed is that you can't set variables which are protected in static classes as the eval() command runs in a scope outside the class. The only thing to get around this would be to implement a static method inside the/every class which runs the eval(). This method could be protected as the call_user_func() [to call the setter method] also runs from inside the class.
Potentially relevant: discussion on late static binding in PHP - When would you need to use late static binding?.
get_class_vars is not same as get_object_vars.
I think get_clas_vars should return the original property values.
Even if for you said eval is out of the question, prior PHP 5.3 the easiest solution is still by using eval:
eval("\$propertyval = $classname::\$propertyname;");
echo $propertyval;
Getting and setting both static and non static properties without using Reflection
Using Reflection works but it is costly
Here is what I use for this purpose,
It works for PHP 5 >= 5.1.0 because I'm using property_exist
function getObjectProperty($object, $property)
{
if (property_exists(get_class($object), $property)) {
return array_key_exists($property, get_object_vars($object))
? $object->{$property}
: $object::$$property;
}
}
function setObjectProperty($object, $property, $value)
{
if (property_exists(get_class($object), $property)) {
array_key_exists($property, get_object_vars($object))
? $object->{$property} = $value
: $object::$$property = $value;
}
}
You can use ReflectionClass:
class foo
{
private static $bar = "something";
}
$class = "foo";
$reflector = new ReflectionClass($class);
$static_vars = $reflector->getStaticProperties();
var_dump($static_vars["bar"]);