php: usage of define - php

in Yii they use this code:
defined('YII_DEBUG') or define('YII_DEBUG',true);
i've never seen anyone write like this before (or). is this real php code or some syntax of yii?

Basically if defined("YII_DEBUG") evaluates to false, it will then define it. Kinda like:
mysql_connect() or die("DIE!!!!!");
It is actual PHP syntax, just not commonly used. It allows you to not have to write:
if(!defined("YII_DEBUG"))
{
define("YII_DEBUG", true);
}
or even shorter
if(!defined("YII_DEBUG"))
define("YII_DEBUG", true);
I'm guessing they used it to get rid of the if statement altogether. The second if statement without brackets would be a hazard for editing, and the first one might have taken up too much room for the developer.
Personally, I'd stick clear of this just because it isn't a commonly known feature. By using commonly known syntaxes (the if statements), other programmers don't have to wonder what it does.
(Although, I might now that I look at it. Seems straightforward and gets rid of unnessecary if clauses)

It's due to short circuit evaluation.
If defined('YII_DEBUG') returns false, it will try to evaluate the second expression to make the sentence true, defining YII_DEBUG constant as true.
The final result is that, if the constant were not defined, then define it as being true. If it's already defined (the value doesn't matter), then do nothing (as the first expression is true, the second expression does not need to be evaluated for the expression to be true).

Pretty straightforward - the 'or' operator is efficient in that it will only evaluate the second part of the statement if it needs to. So if the first part evaluates to true (the constant is already defined), then the define() call isn't executed.

Related

What does "or" do in the context of errors?

Reading this question I want to copy #Your Common Sense's error checking when using mysqli
$query="INSERT INTO testtable VALUES (23,44,56)";
$stmt_test->prepare($query);
$stmt_test->execute() or trigger_error($stmt_test->error);
$stmt_test->close();
How does or work? Another example of it's use is
$fh = fopen($myFile, 'w') or die("can't open file");
How is it different than using an if statment and would should it be used instead?
If the first statement returns false, then the second one is executed. That's it.
This is often how boolean "or" expressions are evaluated in programming languages. If you have a statement involving functions thus:
if (a() or b()) { ... }
then PHP works out that, if a() returns true, there is no need to evaluate the second function, since the overall result will be true regardless of the outcome of the second part. We can use this trick as a simple if mechanism:
(operation_that_might_fail() or report_error());
Here, I've removed the if around the clause. This will be evaluated just as before - except the result of ORing the two is then thrown away, since we don't need to do anything with it.
For this to work, operation_that_might_fail() must return boolean true on success, and false otherwise. As it happens, many PHP functions do exactly that, so we can often use this approach.
Side note: whilst the statement or is arguably clearer, PHP programmers tend to prefer the operator ||. Similarly, and will do what it says, but && is more common.

Set variable in if statement expression

I ran across some interesting code today. I tried to find out if this is a feature of PHP or if I am missing something, but was unable to find anything on Google. Probably because I don't know the name of it.
Code
if($logo = \Repositories\Logo::getLogoData($id)){
$logo_href = $logo->link;
}
The variable $logo is not being set anywhere else. It seems like the expression in this if statement is checking to see if the that class method is returning anything and simultaneously setting the variable $logo to be used in the statement.
Is this true? If so, what in the world is this called!?!
You can make an assignment like that in a conditional. What happened logically is that the value is assigned to $logo and then $logo is evaluated as to whether it is truthy. If it is truthy, the code in the conditional executes.
You will oftentimes see this sort of assignment/evaluation in the case of looping through database result sets, but generally I would suggest that it should be avoided outside such a common use case for sake of clarity in reading g code.
Yes, this is a feature. It's like:
$a=$b=5;
But in this case, imagine the bool result of if as var $a.
However, IDE's are used to complain about solutions like this because of == vs. = as a very common possible bug source.

In PHP, why does "or die()" work, but "or return" doesn't?

In PHP, you can handle errors by calling or die to exit when you encounter certain errors, like this:
$handle = fopen($location, "r") or die("Couldn't get handle");
Using die() isn't a great way to handle errors. I'd rather return an error code so the parent function can decide what to do, instead of just ending the script ungracefully and displaying the error to the user.
However, PHP shows an error when I try to replace or die with or return, like this:
$handle = fopen($location, "r") or return 0;
Why does or die() work, but not or return 0?
I want to thank you for asking this question, since I had no idea that you couldn't perform an or return in PHP. I was as surprised as you when I tested it. This question gave me a good excuse to do some research and play around in PHP's internals, which was actually quite fun. However, I'm not an expert on PHP's internals, so the following is a layman's view of the PHP internals, although I think it's fairly accurate.
or return doesn't work because return isn't considered an "expression" by the language parser - simple as that.
The keyword or is defined in the PHP language as a token called T_LOGICAL_OR, and the only expression where it seems to be defined looks like this:
expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
Don't worry about the bits in the braces - that just defines how the actual "or" logic is handled. What you're left with is expr T_LOGICAL_OR expr, which just says that it's a valid expression to have an expression, followed by the T_LOGICAL_OR token, followed by another expression.
An expr is also defined by the parser, as you would expect. It can either be a r_variable, which just means that it's a variable that you're allowed to read, or an expr_without_variable, which is a fancy way of saying that an expression can be made of other expressions.
You can do or die() because the language construct die (not a function!) and its alias exit are both represented by the token T_EXIT, and T_EXIT is considered a valid expr_without_variable, whereas the return statement - token T_RETURN - is not.
Now, why is T_EXIT considered an expression but T_RETURN is not? Honestly, I have no clue. Maybe it was just a design choice made just to allow the or die() construct that you're asking about. The fact that it used to be so widely used - at least in things like tutorials, since I can't speak to a large volume of production code - seems to imply that this may have been an intentional choice. You would have to ask the language developers to know for sure.
With all of that said, this shouldn't matter. While the or die() construct seemed ubiquitous in tutorials (see above) a few years ago, it's not really recommended, since it's an example of "clever code". or die() isn't a construct of its own, but rather it's a trick which uses - some might say abuses - two side-effects of the or operator:
it is very low in the operator precedence list, which means practically every other expression will be evaluated before it is
it is a short-circuiting operator, which means that the second operand (the bit after the or) is not executed if the first operand returns TRUE, since if one operand is TRUE in an or expression, then they both are.
Some people consider this sort of trickery to be unfavourable, since it is harder for a programmer to read yet only saves a few characters of space in the source code. Since programmer time is expensive, and disk space is cheap, you can see why people don't like this.
Instead, you should be explicit with your intent by expanding your code into a full-fledged if statement:
$handle = fopen($location, "r");
if ($handle) {
// process the file
} else {
return 0;
}
You can even do the variable assignment right in the if statement. Some people still find this unreadable, but most people (myself included) disagree:
if ($handle = fopen($location, "r")) {
// process the file
} else {
return 0;
}
One last thing: it is convention that returning 0 as a status code indicates success, so you would probably want to return a different value to indicate that you couldn't open the file.
Return is fairly special - it cannot be anything like a function since it's a tool to exit functions. Imagine this:
if(1==1) return(); // say what??
If it was like this, return would have to be a function that does a "double exit", leaving not just its own scope but the caller's, too. Therefore return is nothing like an expression, it simply can't work that way.
Now in theory, return could be an expression that evaluates to (say) false and then quits the function; maybe a later php version will implement this.
The same thing applies to goto which would be a charm to work as a fallback; and yes, fallbacks are necessary and often make the code readable, so if someone complains about "clever code" (which certainly is a good point) maybe php should have some "official" way to do such a thing:
connectMyDB() fallback return false;
Something like try...catch, just more to the point. And personally, I'd be a lot happier with "or" doing this job since it's working well with English grammar: "connect or report failure".
TLDR: you're absolutely right: return, goto, break - none of them works. Easy to understand why but still annoying.
I've also stumbled upon that once. All I could find was this:
https://bugs.php.net/bug.php?id=40712
Look at the comment down below:
this is not a bug
I've searched in the documentation and I think it's due to the fact that return 0 is a statement whereas die() is essentially an expression. You can't run $handle = return 0; but $handle = fun(); is valid code.
Regarding error handling I would recommend custom codes or using custom handlers and triggers. The latter are described here for example.

Checking for undefined constants

I've seen a lot of people using
defined('XXX') or define('XXX', 'XXX');
instead of
if(!defined('XXX')){
define('XXX', 'XXX');
}
Does the first code do exactly the same thing? Why do people use it?
The feature is called short circuit evaluation and it's common to many languages. Boolean expressions are evaluated from left to right and evaluation stops when there's already a result. In this case, if the constant is defined the expression is TRUE no matter the other term, so define() does not run.
They do exactly the same thing. The first is just shorter to write. Similar to using
mysql_connect(...) or die('some error');
The right side of the logical OR is evaluated only if the left side is FALSE.
Does the exact same thing. Basically its (TRUE CONDITION) or FALSE ALTERNATIVE
It does exactly the same, relying on the fact that logical OR requires evaluation of the second operand if the first evaluates to FALSE.
I wouldn't use this method too broadly, as it tends to "short-circuit" conditionals (i.e. TRUE or f(); - f() will never be called)

if statement condition optimisation

I have an if statement with two conditions (separated by an OR operator), one of the conditions covers +70% of situations and takes far less time to process/execute than the second condition, so in the interests of speed I only want the second condition to be processed if the first condition evaluates to false.
if I order the conditions so that the first condition (the quicker one) appears in the if statement first - on the occasions where this condition is met and evaluates true is the second condition even processed?
if ( (condition1) | (condition2) ){
// do this
}
or would I need to nest two if statements to only check the second condition if the first evaluates to false?
if (condition1){
// do this
}else if (condition2){
// do this
}
I am working in PHP, however, I assume that this may be language-agnostic.
For C, C++, C#, Java and other .NET languages boolean expressions are optimised so that as soon as enough is known nothing else is evaluated.
An old trick for doing obfuscated code was to use this to create if statements, such as:
a || b();
if "a" is true, "b()" would never be evaluated, so we can rewrite it into:
if(!a)
b();
and similarly:
a && b();
would become
if(a)
b();
Please note that this is only valid for the || and && operator. The two operators | and & is bitwise or, and and, respectively, and are therefore not "optimised".
EDIT:
As mentioned by others, trying to optimise code using short circuit logic is very rarely well spent time.
First go for clarity, both because it is easier to read and understand. Also, if you try to be too clever a simple reordering of the terms could lead to wildly different behaviour without any apparent reason.
Second, go for optimisation, but only after timing and profiling. Way too many developer do premature optimisation without profiling. Most of the time it's completely useless.
Pretty much every language does a short circuit evaluation. Meaning the second condition is only evaluated if it's aboslutely necessary to. For this to work, most languages use the double pipe, ||, not the single one, |.
See http://en.wikipedia.org/wiki/Short-circuit_evaluation
In C, C++ and Java, the statement:
if (condition1 | condition2) {
...
}
will evaluate both conditions every time and only be true if the entire expression is true.
The statement:
if (condition1 || condition2) {
...
}
will evaluate condition2 only if condition1 is false. The difference is significant if condition2 is a function or another expression with a side-effect.
There is, however, no difference between the || case and the if/else case.
I've seen a lot of these types of questions lately--optimization to the nth degree.
I think it makes sense in certain circumstances:
Computing condition 2 is not a constant time operation
You are asking strictly for educational purposes--you want to know how the language works, not to save 3us.
In other cases, worrying about the "fastest" way to iterate or check a conditional is silly. Instead of writing tests which require millions of trials to see any recordable (but insignificant) difference, focus on clarity.
When someone else (could be you!) picks up this code in a month or a year, what's going to be most important is clarity.
In this case, your first example is shorter, clearer and doesn't require you to repeat yourself.
According to this article PHP does short circuit evaluation, which means that if the first condition is met the second is not even evaluated.
It's quite easy to test also (from the article):
<?php
/* ch06ex07 – shows no output because of short circuit evaluation */
if (true || $intVal = 5) // short circuits after true
{
echo $intVal; // will be empty because the assignment never took place
}
?>
The short-circuiting is not for optimization. It's main purpose is to avoid calling code that will not work, yet result in a readable test. Example:
if (i < array.size() && array[i]==foo) ...
Note that array[i] may very well get an access violation if i is out of range and crash the program. Thus this program is certainly depending on short-circuiting the evaluation!
I believe this is the reason for writing expressions this way far more often than optimization concerns.
While using short-circuiting for the purposes of optimization is often overkill, there are certainly other compelling reasons to use it. One such example (in C++) is the following:
if( pObj != NULL && *pObj == "username" ) {
// Do something...
}
Here, short-circuiting is being relied upon to ensure that pObj has been allocated prior to dereferencing it. This is far more concise than having nested if statements.
Since this is tagged language agnostic I'll chime in. For Perl at least, the first option is sufficient, I'm not familiar with PHP. It evaluates left to right and drops out as soon as the condition is met.
In most languages with decent optimization the former will work just fine.
The | is a bitwise operator in PHP. It does not mean $a OR $b, exactly. You'll want to use the double-pipe. And yes, as mentioned, PHP does short-circuit evaluation. In similar fashion, if the first condition of an && clause evaluates to false, PHP does not evaluate the rest of the clause, either.
VB.net has two wonderful expression called "OrElse" and "AndAlso"
OrElse will short circuit itself the first time it reaches a True evaluation and execute the code you desire.
If FirstName = "Luke" OrElse FirstName = "Darth" Then
Console.Writeline "Greetings Exalted One!"
End If
AndAlso will short circuit itself the first time it a False evaluation and not evaluate the code within the block.
If FirstName = "Luke" AndAlso LastName = "Skywalker" Then
Console.Writeline "You are the one and only."
End If
I find both of these helpful.

Categories