Everyone knows in PHP you can do this:
$m = "my string is {$string}";
But is taht possibile with function too? Like:
$m = "my string is {getStringValue()}";
The string expansion in {$..} goes a bit beyond just being able to execute functions. I for example used gettext with that. But you can also use tricks like that:
$html = "htmlentities"; // any callback function
// or just: $html = function($s){ return $s; }
print "even allows expressions {$html(2+3*5+rand(2,17))} here";
That's possible because PHP allows any variable expression there in order to support the simple object notation case:
print "this isn't just a {$obj->prop} string variable";
And for example I'm utilizing an object which implements ArrayAccess, where even this is a method invocation:
print "Makes some things {$_GET->ascii->html['input']} simpler";
We had a few such topics on SO, but for the life of me I can't find a good reference ...
This is not possible (and it wouldn't be very readable too, especially if the function had parameters).
You could use sprintf:
$m = sprintf("my string is %s", getStringValue());
Only variable names are expanded
http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.double
With concatenation, If I understand well what you're trying to do:
$m = "my string is {".getStringValue()."}";
Related
I have an object and need to access an attribute from a string like this:
$string = 'items[0]->sellers[0]->commertialOffer->Price';
I've tried something like this but it doesn't work:
$myObject->{$string};
Any idea?
$items = '{"items":[{"sellers":[{"commertialOffer":{"Price":33}}]}]}';
$myObject = json_decode($items);
$string = 'items[0]->sellers[0]->commertialOffer->Price';
echo ($myObject->{'items'}[0]->{'sellers'}[0]->{'commertialOffer'}->{'Price'});
echo ($myObject->items[0]->sellers[0]->commertialOffer->Price);
As $myObject->items is an array you can`t access it like
$string = 'items[0]';
echo $myObject->{$string};
You can access that by using
$string = 'items';
echo $myObject->{$string}[0];
Are you passing the string between two functions ? If yes , then take 4 values and create the string like :-
$string = $value1.'|'.$value2.'|'.$value3.'|'.$value4 ;
Then explode the string and get back the 4 values .
You probably want to revise your problem because interpreting raw code from a string is often a bad idea. You could potentially use the eval function: see. Again, this is probably not a good idea: when is eval evil?
I write some class to work with string like in C#.
Here it is:
class String {
private $origin_string = null;
private $result_string = null;
function __construct($string)
{
$this->origin_string = $string;
$this->result_string = $this->origin_string;
}
public function Trim()
{
$this->result_string = Trim($this->result_string);
return $this->result_string;
}
public function StartWith($string)
{
return (substr($this->result_string, 0, strlen($string)) === $string);
}
public function EndWith($string)
{
$endlen = strlen($string);
$strlen = strlen($this->result_string);
return (substr($this->result_string, $strlen - $endlen, $endlen) === $string);
}
public function Contains($string) {
return (strpos($this->result_string, $string) !== false);
}
public function Replace($search, $string) {
$this->result_string = str_replace($search, $string, $this->result_string);
return $this->result_string;
}
public function __invoke($string) {
$this->origin_string = $string;
$this->result_string = $this->origin_string;
return $this;
}
public function __toString()
{
return $this->result_string;
}
public static function Override($string)
{
return new self($string);
}
}
In use:
$s = new String("My custom string");
if ($s->StartWith("My"))
$s->Replace("custom", "super");
print $s; // "My super string"
To correct print my text from object i use magic method __toString().
Question:
Is there a method, the inverse __toString?
That is so we can write:
$s = "new text";
And the line is assigned to variables within the object.
($s - an existing object "String" in the example above.)
An analogue of the method __set, only in relation to the object, not the variable inside it.
While using the __invoke, but it's not quite what I want.
No.
$s = "new text"; assigns the (native PHP) string "new text" to the variable $s. It overwrites whatever $s was before. It does not call any methods on $s if $s is an object.
You'd have to alter the core behavior of PHP to achieve something like that. You'll always have to explicitly call a method on your String object.
The short answer to your direct question is "No, there isn't any way to do that in PHP".
Strings are a primitive data type in PHP, and it doesn't do operator overloading or any other other features you'd need to enable this kind of thing.
But also, because they're a primitive data type, there's no real need to encapsulate them in an object structure like this. PHP's OO capabilities have come a long way in recent versions, but at its heart it still isn't a fully OO language.
In fact, I'd say that what you're doing is counter productive. You're wrapping the concept of a string up into a class that has significantly less functionality than basic PHP. You're writing a whole stack of code in order to do stuff in one line of code that can already be done in one line of code, and you're limiting the ability to do a whole lot more.
For example, you've got Contains() and StartsWith() methods, but they don't deal with regular expressions in any way.
And how are you going to deal with concatenation? And what about embedding variables into strings?
PHP has a lot of string handling functionality (in fact, string handling it's one of its strengths), which your class isn't going to be able to replicate.
I recommend working with the language you've been given, not trying to force it to conform to your syntax ideals.
No, you can't assign directly a value to your object. PHP does not allow operator overloading and this style assignment. You must use the contructor, the invoke or any setter method to assign a new value to your string.
You can write something like this:
$s = 'myclass';
$o = new $s();
or, if you want to 'compile' the new keyword you could do:
$s = '$x = new myclass();';
eval($s);
hope this helps.
The title may be a little confusing. This is my problem:
I know you can hold a variable name in another variable and then read the content of the first variable. This is what I mean:
$variable = "hello"
$variableholder = 'variable'
echo $$variableholder;
That would print: "hello". Now, I've got a problem with this:
$somearray = array("name"=>"hello");
$variableholder = "somearray['name']"; //or $variableholder = 'somearray[\'name\']';
echo $$variableholder;
That gives me a PHP error (it says $somearray['name'] is an undefined variable). Can you tell me if this is possible and I'm doing something wrong; or this if this is plain impossible, can you give me another solution to do something similar?
Thanks in advance.
For the moment, I could only think of something like this:
<?php
// literal are simple
$literal = "Hello";
$vv = "literal";
echo $$vv . "\n";
// prints "Hello"
// for containers it's not so simple anymore
$container = array("Hello" => "World");
$vv = "container";
$reniatnoc = $$vv;
echo $reniatnoc["Hello"] . "\n";
// prints "World"
?>
The problem here is that (quoting from php: access array value on the fly):
the Grammar of the PHP language only allows subscript notation on the end of variable expressions and not expressions in general, which is how it works in most other languages.
Would PHP allow the subscript notation anywhere, one could write this more dense as
echo $$vv["Hello"]
Side note: I guess using variable variables isn't that sane to use in production.
How about this? (NOTE: variable variables are as bad as goto)
$variablename = 'array';
$key = 'index';
echo $$variablename[$key];
Say I have a function called set_session_variable that looks like:
function set_session_variable($name, $value) {
// ...write value to the specified path
}
How would I write this function (without using an eval) so that I can do something like:
set_session_variable('foo', 'bar'); // Would set $_SESSION['foo'] = 'bar';
set_session_variable('foo[bar][baz]', 'blah'); // Would set $_SESSION['foo']['bar']['baz'] = 'blah';
I highly suggest, that you won't use
set_session_variable('foo[bar][baz]', 'blah');
but instead
set_session_variable('foo', array('bar'=>array('baz' => 'blah')));
Additionally, you don't need a function call for that at all:
$_SESSION['foo']['bar']['baz'] = 'blah';
You can change the implementation of $_SESSION with the session save handler.
If you're only concerned how you could parse a string like 'foo[bar][baz]', this has been asked before, for example use strings to access (potentially large) multidimensional arrays.
A more relevant question is why you need a function at all. Function calls have a cost, and the function doesn't appear to do useful work.
Example assignments:
$_SESSION['foo'] = 'bar';
$_SESSION['foo']['bar']['baz'] = 'blah';
$foo['bar']['baz'] = 'blah';
$_SESSION['foo'] = $foo;
In direct answer to your question: You could parse the value of $name within set_session_variable() using the PCRE module and a regular expression.
Even simpler and faster would be parsing it with sscanf() provided you are able and willing to impose a convention on the naming of array keys.
A cleaner alternative function:
$array['bar']['baz'] = 'blah';
set_session_variable('foo', $array);
function set_session_variable($key, $val) {
$_SESSION[$key] = $val;
}
One way to solve this is to mimic function overloading, example in this post -> PHP function overloading
Another way is to add one string argument to your function, with your array indices delimited.
For example: set_session_variable('foo', 'bar', 'baz;key');
Which saves the value 'bar' into foo['baz']['key'].
All you have to do is tear the 3rd argument apart (i use ; as delimiter here).
I know this is not exactly reflection, but kind of.
I want to make a debug function that gets a variable and prints a var_dump and the variable name.
Of course, when the programmer writes a call to the function, they already know the variable's name, so they could write something like:
debug( $myvar, 'myvar' );
But I want it to be quick and easy to write, just the function name, the variable, and voilĂ !
debug( $myvar ); // quicker and easier :)
You can do it by converting the variable to a key/value set before passing it to the function.
function varName($theVar) {
$variableName = key($theVar);
$variableValue = $theVar[$variableName];
echo ('The name of the variable used in the function call was '.$variableName.'<br />');
echo ('The value of the variable used in the function call was '.$variableValue.'<br />');
}
$myVar = 'abc';
varName(compact('myVar'));
Though I don't recommend creating a reference to a nameless variable, function varName(&$theVar) works too.
Since compact() takes the variable name as a string rather than the actual variable, iterating over a list of variable names should be easy.
As to why you would want to do this -- don't ask me but it seems like a lot of people ask the question so here's my solution.
I know I'm answering a 4 year old question but what the hell...
compact() might help you is your friend here!
I made a similar function to quickly dump out info on a few chosen variables into a log for debugging errors and it goes something like this:
function vlog() {
$args = func_get_args();
foreach ($args as $arg) {
global ${$arg};
}
return json_encode(compact($args));
}
I found JSON to be the cleanest and most readable form for these dumps for my logs but you could also use something like print_r() or var_export().
This is how I use it:
$foo = 'Elvis';
$bar = 42;
$obj = new SomeFancyObject();
log('Something went wrong! vars='.vlog('foo', 'bar', 'obj'));
And this would print out like this to the logs:
Something went wrong! vars={"foo":"Elvis","bar":42,"obj":{"nestedProperty1":1, "nestedProperty2":"etc."}}
Word of warning though: This will only work for variables declared in the global scope (so not inside functions or classes. In there you need to evoke compact() directly so it has access to that scope, but that's not really that big of a deal since this vlog() is basically just a shortcut for json_encode(compact('foo', 'bar', 'obj')), saving me 16 keystrokes each time I need it.
Nope, not possible. Sorry.
Not elegantly... BUT YOU COULD FAKE IT!
1) Drink enough to convince yourself this is a good idea (it'll take a lot)
2) Replace all your variables with variable variables:
$a = 10
//becomes
$a = '0a';
$$a = 10;
3) Reference $$a in all your code.
4) When you need to print the variable, print $a and strip out the leading 0.
Addendum: Only do this if you are
Never showing this code to anyone
Never need to change or maintain this code
Are crazy
Not doing this for a job
Look, just never do this, it is a joke
I know this is very very late, but i did it in a different way.
It might honestly be a bit bad for performance, but since it's for debugging it shouldn't be a problem.
I read the file where the function is called, on the line it was called and I cut out the variable name.
function dump($str){
// Get the caller with debug backtrace
$bt = debug_backtrace();
$caller = array_shift($bt);
// Put the file where the function was called in an array, split by lines
$readFileStr = file($caller['file']);
// Read the specific line where the function was called
$lineStr = $readFileStr[$caller['line'] -1];
// Get the variable name (including $) by taking the string between '(' and ')'
$regularOutput = preg_match('/\((.*?)\)/', $lineStr, $output);
$variableName = $output[1];
// echo the var name and in which file and line it was called
echo "var: " . $variableName . " dumped in file: " . $caller['file'] . ' on line: ' . $caller['line'] . '<br>';
// dump the given variable
echo '<pre>' . var_export($str, true) . '</pre>';
}
i've had the same thought before, but if you really think about it, you'll see why this is impossible... presumably your debug function will defined like this: function debug($someVar) { } and there's no way for it to know the original variable was called $myvar.
The absolute best you could do would be to look at something like get_defined_vars() or $_GLOBALS (if it were a global for some reason) and loop through that to find something which matches the value of your variable. This is a very hacky and not very reliable method though. Your original method is the most efficient way.
No, the closer you will get is with get_defined_vars().
EDIT: I was wrong, after reading the user comments on get_defined_vars() it's possible with a little hack:
function ev($variable){
foreach($GLOBALS as $key => $value){
if($variable===$value){
echo '<p>$'.$key.' - '.$value.'</p>';
}
}
}
$lol = 123;
ev($lol); // $lol - 123
Only works for unique variable contents though.
Bit late to the game here, but Mach 13 has an interesting solution: How to get a variable name as a string in PHP
You could use eval:
function debug($variablename)
{
echo ($variablename . ":<br/>");
eval("global $". $variablename . ";");
eval("var_dump($" . $variablename . ");");
}
Usage: debug("myvar") not debug($myvar)
This is late post but I think it is possible now using compact method
so the code would be
$a=1;
$b=2;
$c=3
var_dump(compact('a','b','c'));
the output would be
array (size=3)
'a' => int 1
'b' => int 2
'c' => int 3
where variable name a, b and c are the key
Hope this helps
I believe Alix and nickf are suggesting this:
function debug($variablename)
{
echo ($variablename . ":<br/>");
global $$variablename; // enable scope
var_dump($$variablename);
}
I have tested it and it seems to work just as well as Wagger's code (Thanks Wagger: I have tried so many times to write this and the global variable declaration was my stumbling block)