I couldn't find a answer to my question and I am thinking there is something easy I am missing..
I am trying to reference a a value within a object with a variable in a class. In this case I want the line on the bottom:
echo $b->ref->$a->type
to output 'testing' like the following two will:
echo $b->ref->test; // outputs 'testing'
$c = $a->type;
echo $b->ref->$c; // outputs 'testing'
Full code:
<?php
class A {
public $type;
public function set_type($type) {
$this->type = $type;
}
}
class B {
public $ref;
public function set_reference($ref) {
$this->ref = $ref;
}
}
$a = new A();
$b = new B();
$b->set_reference( (object) array('test' => 'testing', 'test2' => 'testing2') );
$a->set_type('test');
echo $b->ref->test; // outputs 'testing'
echo '<br />';
echo $a->type; // outputs 'test'
echo '<br />';
$c = $a->type;
echo $b->ref->$c; // outputs 'testing'
echo '<br />';
echo $b->ref->$a->type; // error
What am I missing to be able to do this? Or, is this not possible?
Same as always.
echo $b->ref->{$a->type};
Did you tried this:
echo $b->ref->{$c};
Related
How could I access specific parameter from a function, example:
function someFunction()
{ echo $a = 7;
echo $b = 70;
}
someFunction();//770
How can I return only $a or $b, is possible ?
echo vs return
First of all, I think it is important to note that echo and return have very different behaviors and are used in very different contexts. echo simply outputs whatever is passed to it, either to an html page, or to the server log.
<?php
$a = 5;
function printFoo() {
echo 'foo';
}
echo '<h1>Hello World!</h1>'; // prints an h1 tag to the page
echo $a; // prints 5 to the page
foo(); // prints foo to the page
?>
return on the other hand is used to "[end] execution of the current function, and return its argument as the value of the function call." return can only ever take one argument. It can also only be executed once in a function; once it is reached, the code will jump out of the function back to where the function was invoked.
<?php
function getFoo() {
return 'foo';
}
// print the value returned by getFoo() directly
echo getFoo();
// store it in a variable to be used elsewhere
$foo = getFoo(); // $foo is now equal to the string 'foo'
function getFooBar() {
return 'foobar'; // code beyond this statement will not be executed
echo 'something something';
return 'another foobar';
}
echo getFooBar(); // prints 'foobar'
?>
function paramters
As it stands, someFunction can only return $a or $b or an array containing $a and $b, which may become a problem if, say, you need to print out $c. To make the function more reusable, you can pass it an argument and then reuse the function wherever you like.
<?php
function printSomething($myVar) {
echo $myVar;
}
$a = 7;
$b = 70;
$c = 770;
printSomething($a) . '\n';
printSomething($b) . '\n';
printSomething($c) . '\n';
printSomething(7000); // you don't have to pass it a variable!
// Output:
// 7
// 70
// 700
// 7000
?>
If you wish to return only one parameter then you just use the return statement.
<?php
function someFunction()
{
$a = 7;
$b = 70;
return [$a, $b];
}
$arrayS = someFunction();//array containing $a and $b
echo $arrayS[0]."\n";
echo $arrayS[1]."\n";
echo "\n";
echo "Another way to access variables\n";
echo someFunction()[0]."\n";
echo someFunction()[1]."\n";
Here i tried to define a function under stdClass object.
<?php
$x= function($name){return "Hello ".$name;};
echo $x("Sun");
$hey = (object)[ "x" => function($name){return "Hello ".$name;}, "y" =>"Hello Venus"];
echo $hey->x("Mercury");
echo $hey->y;
But it says: Fatal error: Call to undefined method stdClass::x()
This is the closest you can get:
$x = function ($name) { return 'hello ' . $name; };
$obj = new stdClass();
$obj->x = $x;
echo call_user_func($obj->x, 'john'); // this will work
echo $obj->x('john'); // this will not work
You won't need to use call_user_func with php7 though.
I'm wondering if this was possible and I could not find a way to do it so I ask. How can I get the name of the variable where in a instance of a class is present.
Pseudo code:
class test{
public $my_var_name = '';
function __construct(){
//the object says: Humm I am wondering what's the variable name I am stored in?
$this->my_var_name = get_varname_of_current_object();
}
}
$instance1 = new test();
$instance2 = new test();
$boeh = new test();
echo $instance1->my_var_name . ' ';
echo $instance2->my_var_name . ' ';
echo $boeh->my_var_name . ' ';
The output would be like:
instance1 instance2 boeh
Why! Well I just wanna know its possible.
I have no idea why, but here you go.
<?php
class Foo {
public function getAssignedVariable() {
$hash = function($object) {
return spl_object_hash($object);
};
$self = $hash($this);
foreach ($GLOBALS as $key => $value) {
if ($value instanceof Foo && $self == $hash($value)) {
return $key;
}
}
}
}
$a = new Foo;
$b = new Foo;
echo '$' . $a->getAssignedVariable(), PHP_EOL; // $a
echo '$' . $b->getAssignedVariable(), PHP_EOL; // $b
I created this code trying to answer for How to get name of a initializer variable inside a class in PHP
But it is already closed and referenced to this question,
just another variant easy to read, and I hope I didn't break any basic concept oh php development:
class Example
{
public function someMethod()
{
$vars = $GLOBALS;
$vname = FALSE;
$ref = &$this;
foreach($vars as $key => $val) {
if( ($val) === ($ref)) {
$vname = $key;
break;
}
}
return $vname;
}
}
$abc= new Example;
$def= new Example;
echo $abc->someMethod();
echo $def->someMethod();
I can't find a good reason to do that.
Anyways, one way you can do (but again it has no use as far as i can imagine) this is by passing the instance name as a constructor's parameter, like this:
$my_instance = new test("my_instance");
Now, before you jump at how you shouldn't mix scopes: I realize this. However, this is a case where either scope mixing must occur or major code duplication must occur—nothing around it. And I'd prefer scope mixing.
That said, I'd like this code:
function a() {
$a = "a";
$b = "b";
$c = "c";
}
function b() {
a();
echo $a . $b . $c;
}
b(); // Output: abc
echo $a; // Should raise a notice that $a is undefined
to be able to work as commented. I know it's not possible in most languages—I was able to do it in Ruby, though; and wonder if you can do it with PHP.
The names of variables aren't known beforehand in the real situation.
Again, it's code duplication or this—absolutely no way around it.
Also, it'd be okay if a had to be something like a('b') or something.
In reality, the code is this:
static function renderError($what, $vararray) {
foreach($vararray as $key => $val) { /* this foreach is the code we want to decouple */
$key = 'e_'.$key;
$$key = htmlspecialchars($val);
}
ob_clean();
exit(eval('?>'.file_get_contents(ROOT."/templates/$what.php")));
}
With a call like E_Render::renderError('NotFound', array( 'requested_url' => '/notfound', 'misspelling' => '/reallynotfound' ));
Then, in templates/NotFound.php, you'd have something like:
<html>
<body>
<?php echo $e_requested_url; ?> could not be found. Did you mean <?php echo $e_misspelling: ?>?
</body>
</html>
We'd really rather not have our template authors do anything more than that...although $e['requested_url'] could be done if nothing better was available.
That's why we have OO:
class Foo {
function a() {
$this->a = "a";
$this->b = "b";
$this->c = "c";
}
function b() {
$this->a();
echo $this->a . $this->b . $this->c;
}
}
$f = new Foo;
$f->b(); // Output: abc
echo $a; // Should raise a notice that $a is undefined
Alternatively:
function a() {
$a = "a";
$b = "b";
$c = "c";
return compact('a', 'b', 'c');
}
function b() {
extract(a());
echo $a . $b . $c;
}
See: compact(), extract()
Otherwise I don't see a way of doing this without drastically changing the language.
PS: If you feel this feature is so important, why don't you just use Ruby?
There's no way to do what you're asking given the restrictions you are imposing. There's never going to be a good reason to do exactly what you are trying to do. There's plenty of better solutions.
Anyway, the closest you'll get is passing by reference:
<?php
function a(&$a, &$b, &$c)
{
$a = 1;
$b = 2;
$c = 3;
}
function b()
{
a($a, $b, $c);
}
?>
I just ran this code
-- var1.php
<?php
function a($vars) {
foreach ($vars as $var => $val) {
$$var = $val;
}
echo eval('?>' . file_get_contents('var2.php') . '<?php ');
};
a(array('a' => 'foo', 'b' => 'bar', 'c' => 'baz'));
-- var2.php
<html>
<body>
<div><?= '$a = "' . $a . '"' ?></div>
<div><?= '$b = "' . $b . '"' ?></div>
<div><?= '$c = "' . $c . '"' ?></div>
</body>
</html>
And it outputs :
$a = "foo"
$b = "bar"
$c = "baz"
The reason being that since eval() keeps the current scope, any variable declared locally inside the function will also be available locally inside the eval'ed string. Same thing with $this.
** UPDATE **
Since eval() is evil and should be avoided (as kindly suggested), here's a rewrite using simple templating. This way, your designer only has to know the variable name available (in the specs) :
-- var1.php
<?php
function showError($error, $vars) {
$template = file_get_contents("{$error}.php");
$keys = array();
$values = array();
foreach ($vars as $var => $val) {
$keys[] = '#{e_'.$var.'}';
$values[] = $val;
}
echo str_replace($keys, $values, $template);
};
showError('template1', array('value' => 300, 'message' => 'Something foo'));
-- template1.php
<html>
<body>
<div>Error <span style="font-weight: bold; color: red;">#{e_value}</span></div>
<div>The message was : <em>#{e_message}</em></div>
</body>
</html>
why can't you return $a from a()?
function a() {
$a = "a";
return $a;
}
function b() {
$a = a();
echo $a;
}
b(); // Output: a
echo $a; // Should raise a notice that $a is undefined
this does not break scope.
I do not understand why you cannot return them as an array. Besides the suggestion #NullUserException gave you, I would suggest the following approach (if you do not take the OOP route).
function a() {
$a = "a";
$b = "b";
$c = "c";
return array($a, $b, $c);
}
function b() {
list($a, $b, $c) = a();
echo $a . $b . $c;
}
I am in a situations where i need to instantiate a class with arguments from within an instance of another class.
Here is the prototype:
//test.php
class test
{
function __construct($a, $b, $c)
{
echo $a . '<br />';
echo $b . '<br />';
echo $c . '<br />';
}
}
Now, i need to instantiate above class using below class's cls function:
class myclass
{
function cls($file_name, $args = array())
{
include $file_name . ".php";
if (isset($args))
{
// this is where the problem might be, i need to pass as many arguments as test class has.
$class_instance = new $file_name($args);
}
else
{
$class_instance = new $file_name();
}
return $class_instance;
}
}
Now when i try to create an instance of test class while passing arguments to it:
$myclass = new myclass;
$test = $myclass->cls('test', array('a1', 'b2', 'c3'));
It gives error:
Missing argument 1 and 2; only first argument is passed.
This works fine if i instantiate a class which has no arguments in it's constructor function.
For experienced PHP developers, above should not be much of a problem. Please help.
Thanks
you need Reflection http://php.net/manual/en/class.reflectionclass.php
if(count($args) == 0)
$obj = new $className;
else {
$r = new ReflectionClass($className);
$obj = $r->newInstanceArgs($args);
}
You can:
1) Modify test class to accept an array, which contains the data you wish to pass.
//test.php
class test
{
function __construct($a)
{
echo $a[0] . '<br />';
echo $a[1] . '<br />';
echo $a[2] . '<br />';
}
}
2) initiate using a user method instead of the constructor and call it using the call_user_func_array() function.
//test.php
class test
{
function __construct()
{
}
public function init($a, $b, $c){
echo $a . '<br />';
echo $b . '<br />';
echo $c . '<br />';
}
}
In your main class:
class myclass
{
function cls($file_name, $args = array())
{
include $file_name . ".php";
if (isset($args))
{
// this is where the problem might be, i need to pass as many arguments as test class has.
$class_instance = new $file_name($args);
call_user_func_array(array($class_instance,'init'), $args);
}
else
{
$class_instance = new $file_name();
}
return $class_instance;
}
}
http://www.php.net/manual/en/function.call-user-func-array.php
Lastly, you can leave your constructor params blank and use func_get_args().
//test.php
class test
{
function __construct()
{
$a = func_get_args();
echo $a[0] . '<br />';
echo $a[1] . '<br />';
echo $a[2] . '<br />';
}
}
http://sg.php.net/manual/en/function.func-get-args.php
You could use call_user_func_array() I believe.
or you could leave the arguments list of the constructor, and then inside the constructor use this
$args = func_get_args();
class textProperty
{
public $start;
public $end;
function textProperty($start, $end)
{
$this->start = $start;
$this->end = $end;
}
}
$object = new textProperty($start, $end);
don't work?
The easiest way I have found:
if ($depCount === 0) {
$instance = new $clazz();
} elseif ($depCount === 1) {
$instance = new $clazz($depInstances[0]);
} elseif ($depCount === 2) {
$instance = new $clazz($depInstances[0], $depInstances[1]);
} elseif ($depCount === 3) {
$instance = new $clazz($depInstances[0], $depInstances[1], $depInstances[2]);
}
Sorry a bit raw, but you should understand the idea.
We're in 2019 now and we have php7 now... and we have the spread-operator (...) .
We can now simply call
<?php
class myclass
{
function cls($file_name, $args = array())
{
include $file_name . ".php";
if (isset($args))
{
$class_instance = new $file_name(...$args); // <-- notice the spread operator
}
else
{
$class_instance = new $file_name();
}
return $class_instance;
}
}