How can i fix my eval()'d code line: 1 issue - php

I keep getting
file: C:\xampp\htdocs\doit.php(45) : eval()'d code line: 1
I have searched the site and can not find a fix that works for me this is the code that I am using that is giving the issue
$ec = "\$sucrate=" . str_replace(array("LEVEL", "EXP", "WILL", "IQ"), array($player['level'], $player['exp'], $player['will'], $player['IQ']), $r['crimePERCFORM']) . ";";
eval($ec);

The string you are building would need quotes around the str_replace'd string (and possibly another string_replace pair also to prevent quote issues).
Example:
$ec = "\$sucrate='" . str_replace(array("LEVEL", "EXP", "WILL", "IQ"), array($player['level'], $player['exp'], $player['will'], $player['IQ']), $r['crimePERCFORM']) . "';";
However, while that should fix your issue, there is almost never a good case for using eval. It will certainly leave your code vulnerable to some sort of remote execution hack no matter what "protections" you put in place that would allow anyone to run any code on your server as if it was written by you.
This would do exactly that same thing, which is just setting the $sucrate variable with your replaced values.
$sucrate = str_replace(array("LEVEL", "EXP", "WILL", "IQ"), array($player['level'], $player['exp'], $player['will'], $player['IQ']), $r['crimePERCFORM']);

I got carried away and have thought about how to improve it this might not actually be an answer to your question but more of a food-for-thought. I see two solutions, and both are kind of invasive.
Of course both solutions only work in all the cases if your formula only use "variables" like in your example with ((WILL*0.8)/2.5)+(LEVEL/4). If you have more complex formulas you'd have do adapt my solutions.
Wrapping eval and don't inject all the inputs in the eval'd code
Assuming the formulas are under your control and not user-supplied you could improve your eval by not injecting all the inputs in your eval'd code but only the formula. This way you don't have to escape the inputs, you only have to make sure the formula is syntactically correct.
function calculateFormula($_vars, $_values, $_formula) {
// This transforms your formula into PHP code which looks
// like this: (($WILL*0.8)/2.5)+($LEVEL/4)
$_cleanFormula = str_replace(
$_vars,
array_map(function($v) { return '$' . $v; }, $_vars),
$_formula
);
// create the $WILL, $LEVEL, $IQ and $EXP variables in the local scope
extract(array_combine($_vars, $_values));
// execute the PHP-formula
return eval('return ' . $_cleanFormula . ';');
}
// Use it like this, instead of eval
$sucrate = calculateFormula(
array("LEVEL", "EXP", "WILL", "IQ"),
array($player['level'], $player['exp'], $player['will'], $player['IQ']),
$r['crimePERCFORM']);
This still uses eval, so security-wise this would be the worst solution. But this would be the closest to what you have now.
Using Symfony's Expression Language
The more secure option would be to use something like the symfony's expression language component. Now you don't need the whole symfony framework in your application, the expression language component can be used on it's own. This could be a big change, this depends on how your existing codebase looks. If you have not used composer or namespaces in your project, this change might be too big.
require_once __DIR__ . '/vendor/autoload.php';
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
$expressionLanguage = new ExpressionLanguage();
$sucrate = $expressionLanguage->evaluate(
$r['crimePERCFORM'],
array(
"LEVEL" => $player['level'],
"EXP" => $player['exp'],
"WILL" => $player['will'],
"IQ" => $player['IQ'],
)
);
As I've said this is maybe a huge change and you might have to get acquainted with composer if you don't know it already.

Related

php - Is it possible to use result of equation stored in a variable directly?

For example
$var = '10/2';
Is there a way for me to output the value 5 from that easily?
So something like this:
$foo = ($var) + 5;
I want $foo to have a value of 10?
Currently, the best way I know is to explode $var and then divide $var[0] by $var[1]. Is there a quicker way?
Another way of asking; Is there a way to tell the system to treat '10/2' as an equation instead of a string?
Could be you can use a solution like this
$foo = eval('return '.$var +5 .';');
print $foo;
eval require a line of code .. so you could build a valid code line
eval() to either assign in place or return:
eval("\$foo = ($var) + 5;");
$foo = eval("return ($var) + 5;");
First things first, EVAL IS HAZARDOUS AND SHOULD NEVER BE USED UNLESS YOU KNOW WHAT YOU'RE DOING! As an addendum to this, you don't know what you're doing. No matter how experienced you are as a programmer, when it comes to eval just assume you don't know what you're doing. Believe me, in the long run your sanity will thank you.
As for your problem, you're basically asking how to write an equation parser. Writing a full blown one that can handle all cases of valid input (and reliably identify invalid input) is a much bigger job than you might at first think, so if you really do need to parse string equations it may be better to look for a library that will do it for you because the chances are whoever wrote the library thought of a lot of stuff that you didn't, such as handling operator precedence and how parenthesis can modify it, how to pass strings in scientific notation, etc.
One of your comments suggests using PHP Math Parser. I've never personally used it, but I know the author by reputation well enough to believe it's a reliable library.
If your use case is always going to be as simple as your example then you can simply split the string and process the resulting fragments.
$parts = explode ("/", $var);
$foo = $parts[0] / $parts[1];

Short Solution for SQL Injection Attacks with MySQLI

I've gotten into the habit of writing the following sort of code:
$q = mysqli_query($mysqli,"SELECT * FROM table WHERE a='$a', b=$b;");
while ($row = mysqli_fetch_array($q)) {
// do something
}
Where $a is a string entered by the user (gotten through $_GET) and $b is a user-entered integer.
Obviously the code I have above is vulnerable to SQL injection attacks, so my habit is to rewrite it like this:
$q = mysqli_query($mysqli,"SELECT * FROM table WHERE a='".str_replace("'","",$a)."', b=".($b+0).";");
But this of course has problems if $a needs to have apostrophes (or quotation marks when quotation marks are used to mark the string).
Recently I learned about prepared statements in mysqli and started playing around with them. I wrote the following function to make it easier to make calls without having to change much of my code:
function safequery($a,$b,$c) {
global $mysqli;
$q = mysqli_prepare($mysqli,$a);
$e = "mysqli_stmt_bind_param(\$q,\$b";
$i = 0;
while ($i < count($c)) {
$e.=",";
$e.="\$c[$i]";
$i++;
}
$e.=");";
eval($e);
mysqli_stmt_execute($q);
return $q;
}
safequery("SELECT * FROM table WHERE a=? AND b=?;","si",array("unsafestring",37));
But what is returned from this function turns out not to be a mysqli_result and thus doesn't work with the first bit of code above. After some more research, I found an alternative, but it would require a complete rethink of how I write my code. Is this necessary or is it possible to protect against MySQL injection attacks with only small changes to the first bit of code (no new lines, same output style, etc.)?
I have looked around on StackOverflow and the rest of the web but I can't find a good simple solution; all of them require the edition of at least three more lines for every call and a different way of reading each row. I'd prefer to do this procedural-y...
Don't think half-measures are going to solve this problem. Commit to expunging all of the interpolation bugs from your code and be disciplined about using prepared statements. Your proposed fix only makes things worse, it gives you a false sense of security. It's also considerably more work than using prepared statements so I'm not sure why you'd even bother doing it this way.
One way to make this a lot easier to do is switch from using double quotes " to single quotes ' on your queries to disable interpolation. Any escaping errors become syntax problems, and if your editor highlights those you'll be able to spot them from across the room, and if something does by fluke work you'll be inserting harmless things like $a instead of actual data.
Another thing to consider is if you should be using an ORM like Doctrine or Propel given what you know about the sophistication of your application. These can make things considerably easier from an implementation perspective.
The code you have there is a ticking time bomb, get rid of it as soon as you can. Don't think replacing quotes is enough, that solves just one issue, there's actually a number of other methods your application can be vulnerable to injection bugs. Tools like SQLMap have an entire arsenal of things they can try to break your code and if you look at the list of things it can do if it finds a flaw you'll probably want to fix these problems right away.
One way you can find issues is using a tool like grep:
grep query `find -name '*.php'` | grep '\$'
That's not bulletproof, but it should probably turn up a lot of code you should fix right away.
Also as #ceejayoz suggests, purge that function with eval in it from your computer and never, ever do that again.
After talking with the commenters and looking at some of the other questions and things they linked to and suggested, I've rewritten the third code snippet to both solve the problem in question and fix the security holes that several commenters pointed out (if there are any remaining ones, please tell me).
First on my use of eval(). Though I can't see any immediate way it could cause problems (user strings are not executed as code in the eval()) it is certainly a round about and stupid way of solving my problem. #TadMan suggested call_user_func_array() which, once worked out, looks something like this:
function refValues($arr){
if (strnatcmp(phpversion(),'5.3') >= 0) //Reference is required for PHP 5.3+
{
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}
function safequery($a,$b,$c) {
global $mysqli;
$q = mysqli_prepare($mysqli,$a);
call_user_func_array("mysqli_stmt_bind_param",refValues(array_merge(array($q,$b),$c)));
mysqli_stmt_execute($q);
return $q;
}
safequery("SELECT * FROM table WHERE a=? AND b=?;","si",array("unsafestring",37));
It turns out that mysqli_stmt_bind_param() takes only references, thus the new refValues() function (run into and solved before on StackOverflow: https://stackoverflow.com/a/16120923/5931472).
While this removes eval() and makes my code easier to understand, it still doesn't solve the original problem of returning the query response in a way that mysqli_fetch_array() can use. It turns out that the proper function to do this is mysqli_stmt_get_result() so the last line of safequery() is rewritten from:
return $q;
To:
return mysqli_stmt_get_result($q);
The result of safequery() is then a mysqli_result which can be used by mysqli_fetch_array().

Using eval on mysql data, is my code vulnerable, if so what is a better alternative

I am using the information_schema.columns table to grab some information.
I just want to know if this is a bad idea and whether there is a better alternative.
if($column['DATA_TYPE'] === 'enem'){
$options = eval(str_replace('enem(', 'array(', $column['COLUMN_TYPE']));
}
I chose to use eval and a single str_replace as i thought it was the fastest method of creating the array.
Here is an example of what $column could look like
$column = array(
['COLUMN_NAME'] => 'status',
['COLUMN_TYPE'] => "enum('failed','success','pending','other')",
['DATA_TYPE'] => 'enum',
);
I think your second solution is much more clear and the difference in speed and memory performances will be minor. (You could also use RegExp)
Here is a link which can help you:
How can I get enum possible values in a MySQL database?
Here is one not eval alternative, probably not as quick as the eval but still fast
if($column['DATA_TYPE'] === 'enem'){
$enums = str_replace(array('enum(', ')'), '', $column['COLUMN_TYPE']);
$options = explode(',', $enums);
}
More checks might need to be done but it works for
enum('failed','success','pending','other')
The only real reason not to use eval() in this case is because you want your code to run on for example HHVM by Facebook, which does not support eval afaik. I see no security problems in your particular case, however.
However, if you simply change your code slightly, you could use json_decode:
$options = json_decode('['.substr($column['COLUMN_TYPE'], 5, -1).']);
It's hard to tell which is faster without doing a small benchmark. I suspect this is faster, because str_replace has to search the entire string.

What is the point of this line of code?

I found this line of code in the Virtuemart plugin for Joomla on line 2136 in administrator/components/com_virtuemart/classes/ps_product.php
eval ("\$text_including_tax = \"$text_including_tax\";");
Scrap my previous answer.
The reason this eval() is here is shown in the php eval docs
This is what's happening:
$text_including_tax = '$tax ...';
...
$tax = 10;
...
eval ("\$text_including_tax = \"$text_including_tax\";");
At the end of this $text_including_tax is equal to:
"10 ..."
The single quotes prevents $tax being included in the original definition of the string. By using eval() it forces it to re-evaluate the string and include the value for $tax in the string.
I'm not a fan of this particular method, but it is correct. An alternative could be to use sprintf()
This code seems to be a bad way of forcing $text_including_tax to be a string.
The reason it is bad is because if $text_including_tax can contain data entered by a user it is possible for them to execute arbitrary code.
For example if $text_include_tax was set to equal:
"\"; readfile('/etc/passwd'); $_dummy = \"";
The eval would become:
eval("$text_include_tax = \"\"; readfile('/etc/passwd'); $_dummy =\"\";");
Giving the malicious user a dump of the passwd file.
A more correct method for doing this would be to cast the variable to string:
$text_include_tax = (string) $text_include_tax;
or even just:
$text_include_tax = "$text_include_tax";
If the data $text_include_tax is only an internal variable or contains already validated content there isn't a security risk. But it's still a bad way to convert a variable to a string because there are more obvious and safer ways to do it.
I'm guessing that it's a funky way of forcing $text_including_tax to be a string and not a number.
Perhaps it's an attempt to cast the variable as a string? Just a guess.
You will need the eval to get the tax rate into the output. Just moved this to a new server and for some reason this line caused a server error. As a quick fix, I changed it to:
//eval ("\$text_including_tax = \"$text_including_tax\";");
$text_including_tax = str_replace('$tax', $tax, $text_including_tax);
It is evaluating the string as PHP code.
But it seems to be making a variable equal itself? Weird.
As others have pointed out, it's code written by someone who doesn't know what on earth they're doing.
I also had a quick browse of the code to find a total lack of text escaping when putting HTML/URIs/etc. together. There are probably many injection holes to be found here in addition to the eval issues, if you can be bothered to audit it properly.
I would not want this code running on my server.
I've looked through that codebase before. It's some of the worst PHP I have seen.
I imagine you'd do that kind of thing to cover up mistakes you made somewhere else.
No, it's doing this:
Say $text_including_tax = "flat". This code evaluates the line:
$flat = "flat";
It isn't necessarily good, but I did use a technique like this once to suck all the MySQL variables in an array like this:
while ($row = mysql_fetch_assoc($result)) {
$var = $row["Variable_name"];
$$var = $row["Value"];
}

Hidden Features of PHP? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I know this sounds like a point-whoring question but let me explain where I'm coming from.
Out of college I got a job at a PHP shop. I worked there for a year and a half and thought that I had learned all there was to learn about programming.
Then I got a job as a one-man internal development shop at a sizable corporation where all the work was in C#. In my commitment to the position I started reading a ton of blogs and books and quickly realized how wrong I was to think I knew everything. I learned about unit testing, dependency injection and decorator patterns, the design principle of loose coupling, the composition over inheritance debate, and so on and on and on - I am still very much absorbing it all. Needless to say my programming style has changed entirely in the last year.
Now I find myself picking up a php project doing some coding for a friend's start-up and I feel completely constrained as opposed to programming in C#. It really bothers me that all variables at a class scope have to be referred to by appending '$this->' . It annoys me that none of the IDEs that I've tried have very good intellisense and that my SimpleTest unit tests methods have to start with the word 'test'. It drives me crazy that dynamic typing keeps me from specifying implicitly which parameter type a method expects, and that you have to write a switch statement to do method overloads. I can't stand that you can't have nested namespaces and have to use the :: operator to call the base class's constructor.
Now I have no intention of starting a PHP vs C# debate, rather what I mean to say is that I'm sure there are some PHP features that I either don't know about or know about yet fail to use properly. I am set in my C# universe and having trouble seeing outside the glass bowl.
So I'm asking, what are your favorite features of PHP? What are things you can do in it that you can't or are more difficult in the .Net languages?
Documentation. The documentation gets my vote. I haven't encountered a more thorough online documentation for a programming language - everything else I have to piece together from various websites and man pages.
Arrays. Judging from the answers to this question I don't think people fully appreciate just how easy and useful Arrays in PHP are. PHP Arrays act as lists, maps, stacks and generic data structures all at the same time. Arrays are implemented in the language core and are used all over the place which results in good CPU cache locality. Perl and Python both use separate language constructs for lists and maps resulting in more copying and potentially confusing transformations.
Stream Handlers allow you to extend the "FileSystem" with logic that as far as I know is quite difficult to do in most other languages.
For example with the MS-Excel Stream handler you can create a MS Excel file in the following way:
$fp = fopen("xlsfile://tmp/test.xls", "wb");
if (!is_resource($fp)) {
die("Cannot open excel file");
}
$data= array(
array("Name" => "Bob Loblaw", "Age" => 50),
array("Name" => "Popo Jijo", "Age" => 75),
array("Name" => "Tiny Tim", "Age" => 90)
);
fwrite($fp, serialize($data));
fclose($fp);
Magic Methods are fall-through methods that get called whenever you invoke a method that doesn't exist or assign or read a property that doesn't exist, among other things.
interface AllMagicMethods {
// accessing undefined or invisible (e.g. private) properties
public function __get($fieldName);
public function __set($fieldName, $value);
public function __isset($fieldName);
public function __unset($fieldName);
// calling undefined or invisible (e.g. private) methods
public function __call($funcName, $args);
public static function __callStatic($funcName, $args); // as of PHP 5.3
// on serialize() / unserialize()
public function __sleep();
public function __wakeup();
// conversion to string (e.g. with (string) $obj, echo $obj, strlen($obj), ...)
public function __toString();
// calling the object like a function (e.g. $obj($arg, $arg2))
public function __invoke($arguments, $...);
// called on var_export()
public static function __set_state($array);
}
A C++ developer here might notice, that PHP allows overloading some operators, e.g. () or (string). Actually PHP allows overloading even more, for example the [] operator (ArrayAccess), the foreach language construct (Iterator and IteratorAggregate) and the count function (Countable).
The standard class is a neat container. I only learned about it recently.
Instead of using an array to hold serveral attributes
$person = array();
$person['name'] = 'bob';
$person['age'] = 5;
You can use a standard class
$person = new stdClass();
$person->name = 'bob';
$person->age = 5;
This is particularly helpful when accessing these variables in a string
$string = $person['name'] . ' is ' . $person['age'] . ' years old.';
// vs
$string = "$person->name is $person->age years old.";
Include files can have a return value you can assign to a variable.
// config.php
return array(
'db' => array(
'host' => 'example.org',
'user' => 'usr',
// ...
),
// ...
);
// index.php
$config = include 'config.php';
echo $config['db']['host']; // example.org
You can take advantage of the fact that the or operator has lower precedence than = to do this:
$page = (int) #$_GET['page']
or $page = 1;
If the value of the first assignment evaluates to true, the second assignment is ignored. Another example:
$record = get_record($id)
or throw new Exception("...");
__autoload() (class-) files aided by set_include_path().
In PHP5 it is now unnecessary to specify long lists of "include_once" statements when doing decent OOP.
Just define a small set of directory in which class-library files are sanely structured, and set the auto include path:
set_include_path(get_include_path() . PATH_SEPARATOR . '../libs/');`
Now the __autoload() routine:
function __autoload($classname) {
// every class is stored in a file "libs/classname.class.php"
// note: temporary alter error_reporting to prevent WARNINGS
// Do not suppress errors with a # - syntax errors will fail silently!
include_once($classname . '.class.php');
}
Now PHP will automagically include the needed files on-demand, conserving parsing time and memory.
Easiness. The greatest feature is how easy it is for new developers to sit down and write "working" scripts and understand the code.
The worst feature is how easy it is for new developers to sit down and write "working" scripts and think they understand the code.
The openness of the community surrounding PHP and the massive amounts of PHP projects available as open-source is a lot less intimidating for someone entering the development world and like you, can be a stepping stone into more mature languages.
I won't debate the technical things as many before me have but if you look at PHP as a community rather than a web language, a community that clearly embraced you when you started developing, the benefits really speak for themselves.
Variable variables and functions without a doubt!
$foo = 'bar';
$bar = 'foobar';
echo $$foo; //This outputs foobar
function bar() {
echo 'Hello world!';
}
function foobar() {
echo 'What a wonderful world!';
}
$foo(); //This outputs Hello world!
$$foo(); //This outputs What a wonderful world!
The same concept applies to object parameters ($some_object->$some_variable);
Very, very nice. Make's coding with loops and patterns very easy, and it's faster and more under control than eval (Thanx #Ross & #Joshi Spawnbrood!).t
You can use functions with a undefined number of arguments using the func_get_args().
<?php
function test() {
$args = func_get_args();
echo $args[2]; // will print 'd'
echo $args[1]; // will print 3
}
test(1,3,'d',4);
?>
I love remote files. For web development, this kind of feature is exceptionally useful.
Need to work with the contents of a web page? A simple
$fp = fopen('http://example.com');
and you've got a file handle ready to go, just like any other normal file.
Or how about reading a remote file or web page directly in to a string?
$str = file_get_contents('http://example.com/file');
The usefulness of this particular method is hard to overstate.
Want to analyze a remote image? How about doing it via FTP?
$imageInfo = getimagesize('ftp://user:password#ftp.example.com/image/name.jpg');
Almost any PHP function that works with files can work with a remote file. You can even include() or require() code files remotely this way.
strtr()
It's extremely fast, so much that you would be amazed. Internally it probably uses some crazy b-tree type structure to arrange your matches by their common prefixes. I use it with over 200 find and replace strings and it still goes through 1MB in less than 100ms. For all but trivially small strings strtr() is even significantly faster than strtolower() at doing the exact same thing, even taking character set into account. You could probably write an entire parser using successive strtr calls and it'd be faster than the usual regular expression match, figure out token type, output this or that, next regular expression kind of thing.
I was writing a text normaliser for splitting text into words, lowercasing, removing punctuation etc and strtr was my Swiss army knife, it beat the pants off regular expressions or even str_replace().
One not so well known feature of PHP is extract(), a function that unpacks an associative array into the local namespace. This probably exists for the autoglobal abormination but is very useful for templating:
function render_template($template_name, $context, $as_string=false)
{
extract($context);
if ($as_string)
ob_start();
include TEMPLATE_DIR . '/' . $template_name;
if ($as_string)
return ob_get_clean();
}
Now you can use render_template('index.html', array('foo' => 'bar')) and only $foo with the value "bar" appears in the template.
Range() isn't hidden per se, but I still see a lot of people iterating with:
for ($i=0; $i < $x; $i++) {
// code...
}
when they could be using:
foreach (range(0, 12) as $number) {
// ...
}
And you can do simple things like
foreach (range(date("Y"), date("Y")+20) as $i)
{
print "\t<option value=\"{$i}\">{$i}</option>\n";
}
PHP enabled webspace is usually less expensive than something with (asp).net.
You might call that a feature ;-)
The static keyword is useful outside of a OOP standpoint. You can quickly and easily implement 'memoization' or function caching with something as simple as:
<?php
function foo($arg1)
{
static $cache;
if( !isset($cache[md5($arg1)]) )
{
// Do the work here
$cache[md5($arg1)] = $results;
}
return $cache[md5($arg1)];
}
?>
The static keyword creates a variable that persists only within the scope of that function past the execution. This technique is great for functions that hit the database like get_all_books_by_id(...) or get_all_categories(...) that you would call more than once during a page load.
Caveat: Make sure you find out the best way to make a key for your hash, in just about every circumstance the md5(...) above is NOT a good decision (speed and output length issues), I used it for illustrative purposes. sprintf('%u', crc32(...)) or spl_object_hash(...) may be much better depending on the context.
One nice feature of PHP is the CLI. It's not so "promoted" in the documentation but if you need routine scripts / console apps, using cron + php cli is really fast to develop!
Then "and print" trick
<?php $flag and print "Blah" ?>
Will echo Blah if $flag is true. DOES NOT WORK WITH ECHO.
This is very handy in template and replace the ? : that are not really easy to read.
You can use minus character in variable names like this:
class style
{
....
function set_bg_colour($c)
{
$this->{'background-color'} = $c;
}
}
Why use it? No idea: maybe for a CSS model? Or some weird JSON you need to output. It's an odd feature :)
HEREDOC syntax is my favourite hidden feature. Always difficult to find as you can't Google for <<< but it stops you having to escape large chunks of HTML and still allows you to drop variables into the stream.
echo <<<EOM
<div id="someblock">
<img src="{$file}" />
</div>
EOM;
Probably not many know that it is possible to specify constant "variables" as default values for function parameters:
function myFunc($param1, $param2 = MY_CONST)
{
//code...
}
Strings can be used as if they were arrays:
$str = 'hell o World';
echo $str; //outputs: "hell o World"
$str[0] = 'H';
echo $str; //outputs: "Hell o World"
$str[4] = null;
echo $str; //outputs: "Hello World"
The single most useful thing about PHP code is that if I don't quite understand a function I see I can look it up by using a browser and typing:
http://php.net/function
Last month I saw the "range" function in some code. It's one of the hundreds of functions I'd managed to never use but turn out to be really useful:
http://php.net/range
That url is an alias for http://us2.php.net/manual/en/function.range.php. That simple idea, of mapping functions and keywords to urls, is awesome.
I wish other languages, frameworks, databases, operating systems has as simple a mechanism for looking up documentation.
Fast block comments
/*
die('You shall not pass!');
//*/
//*
die('You shall not pass!');
//*/
These comments allow you to toggle if a code block is commented with one character.
My list.. most of them fall more under the "hidden features" than the "favorite features" (I hope!), and not all are useful, but .. yeah.
// swap values. any number of vars works, obviously
list($a, $b) = array($b, $a);
// nested list() calls "fill" variables from multidim arrays:
$arr = array(
array('aaaa', 'bbb'),
array('cc', 'd')
);
list(list($a, $b), list($c, $d)) = $arr;
echo "$a $b $c $d"; // -> aaaa bbb cc d
// list() values to arrays
while (list($arr1[], $arr2[], $arr3[]) = mysql_fetch_row($res)) { .. }
// or get columns from a matrix
foreach($data as $row) list($col_1[], $col_2[], $col_3[]) = $row;
// abusing the ternary operator to set other variables as a side effect:
$foo = $condition ? 'Yes' . (($bar = 'right') && false) : 'No' . (($bar = 'left') && false);
// boolean False cast to string for concatenation becomes an empty string ''.
// you can also use list() but that's so boring ;-)
list($foo, $bar) = $condition ? array('Yes', 'right') : array('No', 'left');
You can nest ternary operators too, comes in handy sometimes.
// the strings' "Complex syntax" allows for *weird* stuff.
// given $i = 3, if $custom is true, set $foo to $P['size3'], else to $C['size3']:
$foo = ${$custom?'P':'C'}['size'.$i];
$foo = $custom?$P['size'.$i]:$C['size'.$i]; // does the same, but it's too long ;-)
// similarly, splitting an array $all_rows into two arrays $data0 and $data1 based
// on some field 'active' in the sub-arrays:
foreach ($all_rows as $row) ${'data'.($row['active']?1:0)}[] = $row;
// slight adaption from another answer here, I had to try out what else you could
// abuse as variable names.. turns out, way too much...
$string = 'f.> <!-? o+';
${$string} = 'asdfasf';
echo ${$string}; // -> 'asdfasf'
echo $GLOBALS['f.> <!-? o+']; // -> 'asdfasf'
// (don't do this. srsly.)
${''} = 456;
echo ${''}; // -> 456
echo $GLOBALS['']; // -> 456
// I have no idea.
Right, I'll stop for now :-)
Hmm, it's been a while..
// just discovered you can comment the hell out of php:
$q/* snarf */=/* quux */$_GET/* foo */[/* bar */'q'/* bazz */]/* yadda */;
So, just discovered you can pass any string as a method name IF you enclose it with curly brackets. You can't define any string as a method alas, but you can catch them with __call(), and process them further as needed. Hmmm....
class foo {
function __call($func, $args) {
eval ($func);
}
}
$x = new foo;
$x->{'foreach(range(1, 10) as $i) {echo $i."\n";}'}();
Found this little gem in Reddit comments:
$foo = 'abcde';
$strlen = 'strlen';
echo "$foo is {$strlen($foo)} characters long."; // "abcde is 5 characters long."
You can't call functions inside {} directly like this, but you can use variables-holding-the-function-name and call those! (*and* you can use variable variables on it, too)
Array manipulation.
Tons of tools for working with and manipulating arrays. It may not be unique to PHP, but I've never worked with a language that made it so easy.
I'm a bit like you, I've coded PHP for over 8 years. I had to take a .NET/C# course about a year ago and I really enjoyed the C# language (hated ASP.NET) but it made me a better PHP developer.
PHP as a language is pretty poor, but, I'm extremely quick with it and the LAMP stack is awesome. The end product far outweighs the sum of the parts.
That said, in answer to your question:
http://uk.php.net/SPL
I love the SPL, the collection class in C# was something that I liked as soon as I started with it. Now I can have my cake and eat it.
Andrew
I'm a little surprised no-one has mentioned it yet, but one of my favourite tricks with arrays is using the plus operator. It is a little bit like array_merge() but a little simpler. I've found it's usually what I want. In effect, it takes all the entries in the RHS and makes them appear in a copy of the LHS, overwriting as necessary (i.e. it's non-commutative). Very useful for starting with a "default" array and adding some real values all in one hit, whilst leaving default values in place for values not provided.
Code sample requested:
// Set the normal defaults.
$control_defaults = array( 'type' => 'text', 'size' => 30 );
// ... many lines later ...
$control_5 = $control_defaults + array( 'name' => 'surname', 'size' => 40 );
// This is the same as:
// $control_5 = array( 'type' => 'text', 'name' => 'surname', 'size' => 40 );
Here's one, I like how setting default values on function parameters that aren't supplied is much easier:
function MyMethod($VarICareAbout, $VarIDontCareAbout = 'yippie') { }
Quick and dirty is the default.
The language is filled with useful shortcuts, This makes PHP the perfect candidate for (small) projects that have a short time-to-market.
Not that clean PHP code is impossible, it just takes some extra effort and experience.
But I love PHP because it lets me express what I want without typing an essay.
PHP:
if (preg_match("/cat/","one cat")) {
// do something
}
JAVA:
import java.util.regex.*;
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat")
if (m.find()) {
// do something
}
And yes, that includes not typing Int.

Categories