PHP syntax: constructing a class from a member variable - php

I am trying to make a class from a member variable like this:
<?
class A{
private $to_construct = 'B';
function make_class(){
// code to make class goes here
}
}
class B{
function __construct(){
echo 'class constructed';
}
}
$myA = new A();
$myA->make_class();
?>
I tried using:
$myClass = new $this->to_construct();
and
$myClass = new {$this->to_construct}();
but neither worked. I ended up having to do this:
$constructor = $this->to_construct;
$myClass = new $constructor();
It seems like there should be a way to do this without storing the class name in a local variable. Am I missing something?

Have you tried this?
$myClass = new $this->to_construct;

Are you using PHP 4 or something? On 5.2.9 $myClass = new $this->to_construct(); works perfectly.
In the end it's what you have to live with, with PHP. PHP syntax and semantics are VERY inconsistent. For example, an array access to the result of a call is a syntax error:
function foo() {
return array("foo","bar");
}
echo $foo()[0];
Any other language could do that but PHP can't. Sometimes you simply need to store values into local variables.
Same is true for func_get_args() in older versions of PHP. If you wanted to pass it to a function, you needed to store it in a local var first.

If I read well between the lines you are trying to do something like this. Right?
class createObject{
function __construct($class){
$this->$class=new $class;
}
}
class B{
function __construct(){
echo 'class B constructed<br>';
}
function sayHi(){
echo 'Hi I am class: '.get_class();
}
}
class C{
function __construct(){
echo 'class C constructed<br>';
}
function sayHi(){
echo 'Hi I am class: '.get_class();
}
}
$wantedClass='B';
$finalObject = new createObject($wantedClass);
$finalObject->$wantedClass->sayHi();
--
Dam

Related

Using local variable from call in a function

After 9 hours of struggling to get this right, I have turned to the internet for help. I can't seem to find any relevant answers doing a Google search.
I currently have a class called Test. Test accepts a single argument.
<?php
class test {
private $varpassed;
public function getVarpas() {
return $this->varpassed;
}
Public function setVarpas($value) {
$this->varpassed= $value;
}
public function stringGen(){
$testvar = $this->varpassed;
echo $testvar;
}
}
The stringGen function should return the $varpassed variable whenever its called. The value for $varpassed is set using the setVarpas function. However, when ever I call the stringGen() method I only seem to be getting the following error:
Fatal error: Using $this when not in object context in file.php line 14.
Pointing to this line:
$testvar = $this->varpassed;
Is there any other way to pass the variable to the stringGen method? I've tried using:
self::$this->varpassed;
Which also throws an error.
first create an instance of the object (so you can use $this in the context), for example:
$test = new test();
then you can call:
$test->setVarpas('Hello World!');
now you can call:
$test->stringGen();
you have to do something like this
$var = new test();
$var->setVarpas("Hello");
$var->stringGen(); // this will echo Hello
$this is used when you are withing class. outside class you have to use class object.
1) Change this: class test() to class test
2) Create and instance first something like $t1 = new test();
3) Call the function $t1->setVarpas(5);
4) Now you can call the function $t1->stringGen();
Fixed:
<?php
class test
{
private $varpassed;
public function getVarpas() {
return $this->varpassed;
}
Public function setVarpas($value) {
$this->varpassed= $value;
}
public function stringGen(){
$testvar = $this->varpassed;
echo $testvar;
}
}
$t1 = new test();
$t1->setVarpas(5);
$t1->stringGen();
OUTPUT:
5
You should not declare a class with parentheses.
Use
class test {
instead of
class test(){

Approach class constant through class member variable

I have trouble accessing a constant of a class via the object operator(->).
I have these 2 classes:
class withConstant {
const MY_CONSTANT = 5;
}
class usingConstant {
public $class = null;
function __construct() {
$this->class = new withConstant();
}
}
When I do this:
$myClass = new usingConstant();
echo $myClass->class::MY_CONSTANT;
I get an error Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM). However, I can get around it with this:
$myClass = new usingConstant();
$myClass = &$myClass->class;
echo $myClass::MY_CONSTANT;
I prefer to access the constant without assigning the member variable to another variable first.
This is the closest I can come to what you're actually after achieving unfortunately:
echo constant(get_class($myClass->class).'::MY_CONSTANT');
Note that this is incredibly inefficient, since it looks up the class to determine it's name, then looks it up again to reference the constant.
You can make a getter function in withConstant and call that.
class withConstant {
const MY_CONSTANT = 5;
function getConstant(){
return self::MY_CONSTANT;
}
}
Then you can call that function:
$myClass = new usingConstant();
echo $myClass->class->getConstant();

can I create a class dynamically with $? (dollar-sign)

In PHP sometimes it would be nice if I could define a function or a class with a variable name like
$myfunctionname="test";
function $myfunctionname(){
//...
}
so it would create the function test()
or with classes too like:
$foo = bar;
class $foo {
// lots of complicated stuff
// ...
}
but this doesen't work. like this it would give parse errors!
Is there a solution to this?
(I know, this is not good practise, but just as a workaround, it would be handy)
EDIT: My actual problem:
I have a framework with a migration process where every migration step is in a separate php include file in a folder.
Each file contains only one migration class that contains the name of the include file.
Because the class has to have that certain name, I would like to create the name of the class to a generic name that is created by the filename constant __FILE__
Yes, you can, but I dont want you to.
$classname = "test";
eval("class {$classname}{ public function hello(){ echo \"hello!\"; } }");
$evil_class = new $classname();
$evil_class->hello(); // echo's "hello!"
now, if you don't mind me I'm going for a shower.
You can use a factory pattern:
class poly_Factory {
public function __construct() {
$class = 'poly';
return new $class();
}
}
If that is anything you want to get to.
http://net.tutsplus.com/tutorials/php/understanding-and-applying-polymorphism-in-php/
Scroll down to step 4, last part...
I know you did not ask for that, but what can your question be good for else?
No. This code throws a parse error on line 3 because of the $:
$foo = 'bar';
class $foo {
function hello() {
echo "World";
}
}
$mybar = new bar();
$mybar->hello();
Result:
Parse error: syntax error, unexpected T_VARIABLE, expecting T_STRING on line 3
And as Jan Dvorak pointed out in the comments: even if you figure out a way to do this, don't do this.
If you want to create a value object you can just use the stdClass builtin type.
$object = new stdClass;
$object->someValue = "Hello World";
echo $object->someValue;
See it in Action
If you want to assign methods then you have to use the magic __call function, here is how I would do it.
class AnonObject{
private $properties = array();
private $methods = array();
public function __get($property){
return array_key_exists($property, $this->properties)?$this->properties[$property]:null;
}
public function __set($property, $value){
if (!is_string($value) && is_callable($value)){
if ($value instanceof \Closure){
// bind the closure to this object's instance and static context
$this->methods[$property] = $value->bindTo($this,get_class($this));
} else {
// invokable objects
$this->methods[$property] = $value;
}
} else {
$this->properties[$property] = $value;
}
}
public function __call($method, $args){
if (array_key_exists($method, $this->methods)){
call_user_func_array($this->methods[$method], $args);
} else {
throw new RuntimeException("Method ".$method." does not exist on object");
}
}
}
See it In Action
Note, as stated by several other people this is bad practice. If the goal of this exercise is to compose the behavior of an instance of an object at runtime a more maintainable solution would be to use the Strategy Pattern

Using a variable as class name

I have the following:
User::model()->exists($someParamsHere);
Is there a way to make the class name 'User' dynamic? So something like this:
$className::model()->exists($someParamsHere);
But that doesn't seem to work.
I also read something about the ReflectionClass, but i'm not really sure how to use it.
I tried this, but off course the model() method is never called this way:
$reflectionMethod = new ReflectionMethod($className, 'exists');
$reflectionMethod->invoke(null, $someParamsHere);
$className::model() works with PHP 5.3 and above, if I'm not mistaken. A workaround is to use CActiveRecord::model($className). See the documentation for CActiveRecord.model().
In PHP >= 5.3 works fine:
<?php
class Foo {
static function Bar() {
return "Bar";
}
static function getFoo() {
return new static();
}
function getBar() {
return static::Bar();
}
}
$class = "Foo";
print $class::Bar() . "\n";
print $class::getFoo()->Bar() . "\n";
Result:
Bar
Bar

PHP string to object name

Ok I have a string...
$a_string = "Product";
and I want to use this string in a call to a object like this:
$this->$a_string->some_function();
How the dickens do I dynamically call that object?
(don't think Im on php 5 mind)
So you the code you want to use would be:
$a_string = "Product";
$this->$a_string->some_function();
This code implies a few things. A class called Product with the method some_function(). $this has special meaning, and is only valid inside a class definition. So another class would have a member of Product class.
So to make your code legal, here's the code.
class Product {
public function some_function() {
print "I just printed Product->some_function()!";
}
}
class AnotherClass {
public $Product;
function __construct() {
$this->Product = new Product();
}
public function callSomeCode() {
// Here's your code!
$a_string = "Product";
$this->$a_string->some_function();
}
}
Then you can call it with this:
$MyInstanceOfAnotherClass = new AnotherClass();
$MyInstanceOfAnotherClass->callSomeCode();
I seem to have read this question differently from everyone else who's responded, but are you trying to use variable variables?
In the code you've shown, it looks like you're trying to call a function from string itself. My guess is that you want to call a function from a class with the same name as that string, in this case "Product."
This is what that would look like:
$this->Product->some_function();
It seems you might instead be looking for something like this:
$Product = new Product();
$Product->some_function();
EDIT: You need to be running PHP5 in order to do any method chaining. After that, what you have is perfectly legal.
Let's see if I got your intentions correctly...
$some_obj=$this->$a_string;
$some_obj->some_function();
So you've got an object, and one of it's properties (called "Product") is another object which has a method called some_function().
This works for me (in PHP5.3):
<?PHP
class Foo {
var $bar;
}
class Bar {
function some_func(){
echo "hello!\n";
}
}
$f = new Foo();
$f->bar = new Bar();
$str = 'bar';
$f->$str->some_func(); //echos "hello!"
I don't have PHP4 around, but if it doesn't work there, you might need to use call_user_func() (or call_user_func_array() if you need to pass arguments to some_function()

Categories