My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Monday, April 14, 2008

Script Type PHP :)

Update 2008/03/15
I have removed preg_replace and added DOM classes to parse and manage, in a better way, script nodes that contain php code.
Everything inside a simple PHP 5 compatible class.
Finally, please remember that this is a layer between <?php ?> and JavaScript, and only an experiment ;)

Here you can read another example, where difference between server, output, and client, should be more clear than precedent one.

<?php require 'PHPScriptHandler.php'; ?>
<html>
<head>
<title>Hello PHP World</title>
<script type="text/php" author="andr3a">

// here we are between the server and output, known as client
$hello = ucwords('hello php world');

// imagine that we would like to use a variable
// defined somewhere in the server
global $something;

// we could even include or require php files
// perform database operations and everything else
</script>
<script type="text/javascript">
onload = function(){
// here we are in the client, on window load event
alert($hello);
alert($something);
};
</script>
</head>
<body>
<?php
// here we are in the server side
// we could do what we do every day without problems
$something = '<div>Hello Body</div>';
echo $something;
?>
</body>
</html>


-------------------------------

This is a little experiment to emulate script tag with php.
The final result will be something like this one:

<html>
<head>
<title>Hello PHP World</title>
<script type="text/php">

// string
$hello = ucwords('hello php world');

// object
$o = new stdClass;
$o->test = 'hello again';

</script>
<script type="text/javascript">
onload = function(){
alert($hello);
alert($o.test);
};
</script>
</head>
<body>
</body>
</html>

How can it be possible?

<?php // 5 - PHP Script Handler Experiment - by Andrea Giammarchi
function php_script_handler($output){return stripos($output, 'type="text/php"') ? preg_replace_callback('#(?i)<script[[:space:]]+type="text/php"(.*?)>([^\a]+?)</script>#', 'php_script_parser', $output) : $output;}
function php_script_parser(){eval(end(func_get_arg(0)));return '<script type="text/javascript"'.next(func_get_arg(0)).'>'.PHP_EOL.php_script_vars(get_defined_vars()).PHP_EOL.'</script>';}
function php_script_vars($vars){foreach($vars as $key => $value)$vars[$key] = '$'.$key.'='.json_encode($value).';';return implode(PHP_EOL, $vars);}
ob_start('php_script_handler');
?>

Of course, we need to include this file before we write a single character in the layout (spaces included), so basically to obtain the expected result, just save above code in a file called, for example, php_script_handler.php, and put them before the layout

<?php require 'php_script_handler.php'; ?>
<html>
<head>
<title>Hello PHP World</title>
.... other stuff ....


The evil eval? Yes, absolutely ... but first of all, this is only a simple experiment, secondly, the page will not be sent before evaluation, so there's no way from the client side to inject malicious code.

The main problem is true interoperability between these two languages, JavaScript, and PHP, but did I say that this is only an experiment? :P

8 comments:

Unknown said...
This comment has been removed by the author.
Andrea Giammarchi said...

because JavaScript 3rd edition is the best scripting language I've ever used? :D

There is a lot of stuff that I would like to bring in PHP ... and basically that's what I am doing with my PHP framework, but it is still under construction :geek:

Anonymous said...

JavaScript Onload no i don't think that crazy programme

Anonymous said...

wow, that's insane. i'm going to have to take a closer look at this technique, i've never used the ob_start() callback parameter before.

Unknown said...
This comment has been removed by the author.
Andrea Giammarchi said...

>> But javascript is prototyping language otherwise php

I've implemented prototype behaviour in my framework too, just stay tuned, ok? ;)

Finally, I gree about strpos but in this case I absolutely know what I am doing and there's no way to have a false positive with that check.
The reason is simple, type="text" cannot be the first char, and if it is, the output is a non-sense.

Anyway, I removed preg_replace_callback (please read the update) because with DOM classes, there's no reason to prefere a proge with problems if some var inside contain, for example, a < /script> in a string.

Regards

Unknown said...
This comment has been removed by the author.
Andrea Giammarchi said...

ok for strpos ... anyway, the important thing is that false !== 0, so basically a check like if(indexOf($a, $b) < 0) is the same of if(indexOf($a, $b) === false), because these cannot be ambiguous.

In my old example, I used an improbable ambiguity because of my lazy nature :D

Finally, thank you to visit my blog.
Cheers