views:

195

answers:

5

Assume color = "orange";

Ruby:

puts("My favorite color is #{color.downcase() + 'ish'} -- at least for now.");

PHP:

print("My favorite color is {strtolower( $color ) + 'ish'} -- at least for now.");

The PHP version does not work like I would like it to. I'm not looking for any language wars, I just want to know if anyone knows of a way to get PHP to be more like Ruby in this specific regard.

Can anyone help a Ruby addict adjust to his routine visits to PHP-land? Is there an 'act-like-ruby' module somewhere out there? This is starting to hurt.

+5  A: 

You're close, you can embed variables in strings, but not function calls.

I use printf() (and sprintf()) for that, which is a thin wrapper around the C function of the same name:

printf('My favorite color is %sish -- at least for now.', strtolower( $color ));

See that %s in there? That's the placeholder for the string data type that you're passing in as the 2nd argument.

sprintf() works the same way, but it returns the formatted string instead of print'ing it.

The only other options are:

A. Performing the function calls first and assigning the end-result to the variable:

$color = strtolower( $color );
print("My favorite color is {$color}ish -- at least for now.");

B. Using concatenation, which is a little ugly IMO:

print('My favorite color is ' . strtolower( $color ) . 'ish -- at least for now.');

You may have noticed my use of single quotes (aka ticks), and double quotes.

In PHP, literals inside double quotes are parsed for variables, as you see in "A" above.

Literals inside single quotes are not parsed. Because of this, they're faster. You should, as a rule, only use double-quotes around literals when there's a variable to be parsed.

Encoderer
In your source it will always look cleaner and take less processing to do:$myVar = 'ValueBlah ' . strtolower($myArg) . ' End of my string'; This way you see the highlighted syntax of the entire line when working with the source.
Syntax
I know about sprintf but I was hoping PHP had something a bit more concise. Upvoted anyway though because it is a good answer.
dreftymac
@Syntax, I disagree about the "less processing" comment. String parsing made great leaps in efficiency between v4.0 and v5.0. And I'm not sure about yours, but Zend Studio for Eclipse does highlight syntax when I embed variables.
Encoderer
@Syntax: that's one way of looking at it. However, what happens for those who want to do myArg.tolowercase().reverse().stripspaces() and not have to nest all those parenthesis?
dreftymac
You use the nested parentheses, simple. It's PHP, not Ruby.
Mario
For those of us who don't use Eclipse or Zend Studio using concatenation makes the code much easier to understand/parse.
Simurr
@Syntax, Just for kicks, I tested it. I tried each method 1 Million times. Concatenating took 0.0000010620784759521 on average and embedding took 0.0000011020784759521. There used to be a bigger gap, but as you can see, their performance is equal.
Encoderer
http://blog.libssh2.org/index.php?/archives/28-How-long-is-a-piece-of-string.html
troelskn
I don't see how: puts("My favorite color is #{color.downcase() + 'ish'} -- at least for now."); is any more concise than: print('My favorite color is ' . strtolower( $color ) . 'ish -- at least for now.'); Not trolling and I don't know much about ruby but I honestly don't see the real diff.
gaoshan88
@Dreftymax - combine these into a single call encapsulated in a function? Also it seems that my timing issue is old news. i just know that when you have to search through a string to replace it rather than a simple combine that it's always a performance hit, minute or not.
Syntax
+3  A: 
'My favorite color is ' . strtolower( $color ) . 'ish-- at least for now.'

I dont think PHP supports full expressions interpolated into strings. Been a while since I did any PHP though.

Squeegy
it does not. double quoted strings are parsed for variables but not functions. single quoted strings are not parsed at all.
Syntax
A: 

Not possible. But if you really insist, you can always create a String class with a fluent interface... but that's crazy :)

Mario
+1  A: 

You can't call plain functions inside strings like that, but you can coax the parser into doing strange things:

<?php
print "{$a->b()}"; // Works

//Parse error: syntax error, unexpected '(' in Command line code on line 1
print "${time()}";

print "${$a=time()} $a"; // Also works: prints "1234380996"
?>

As long as it sees a valid variable at the start, it'll go ahead and interpolate an entire statement without complaining.

For those who were wondering, yes, this works too...

<?php
print "${$a or print shell_exec('ls')}";
?>
Ant P.
That's scary. Glad I never use double quotes.
Mario
@Mario, it's actually not so bad. PHP won't execute that code inside a variable, so it's not like you're open to code injection because of it. Try his example above. but assign it to a var: $x='$a->b()'; print({$x}); This is just going to print the literal PHP code.
Encoderer
It's not as bad as it looks. The only way you'll get code injection is if the users can control the hard-coded strings in the PHP code itself, and at that point you're probably screwed already.Being able to call functions like that is a little weird, though.
Ant P.
Ok, good, heh. I started having flashbacks for a second on my early PHP code.
Mario
+1  A: 

If this is anything goes....

class ColorIsh {
    var $color;

    function __constructor($color) { $this->color = $color; }
    function __get($prop) {
        if ($prop == 'ish') {
            // code here fixing suffix if needed
            return strtolower($this->color) . 'ish';
        }
        return '';
    }
    function __set($prop) {}
}

$color = new ColorIsh("orange");
$str = "My favorite color is $color->ish -- at least for now.";

And the hyper advanced version

class ColorIsh {
    private $color;

    function __constructor($color) {$this->color = $color; }
    function __get($prop) {
        if ($prop == 'color') 
            return $this->color;
        if ($prop == 'ish')
            return isset($this->ish) ? $this->ish : $this->color . 'ish';
        return false;
    }
    function __set($prop, $value) {
        if ($prop == 'color') { $this->color = $value; unset($this->ish); }
        if ($prop == 'ish') { $this->ish = $value; }
    }
}

$color = new ColorIsh('orange');
$color->ish = 'orangish';
print "The color is kinda $color->ish";
$color->color = 'green';
print "The color is kinda $color->ish";

output:
The color is kinda orangish.
The color is kinda greenish.
jmucchiello
+1! This is why I love PHP, the hidden treasures you can find sometimes in code...
Mario
Attention down-voter: Did you not notice that I said this answer was "out there"? In case it wasn't clear, I don't recommend anyone use the above code. I was merely showing that the "equivalent" to the ruby code was "possible".
jmucchiello