How does PHP uses constants (defines) - php

Imagine I have this constant in PHP:
define('APP_PATH', str_replace('//', '/', str_replace('\\', '/', dirname(__FILE__) . '/')));
When I use APP_PATH in my application, does PHP execute the code (dirname, and the two str_replace on __FILE__) each time or PHP execute the code once and store the result in APP_PATH ? I hope I'm clear enough :)
This question applies to PHP 5.1.0+.

It should be done once, at the time it was defined.
UPDATED
For documentation: define() - constants
From the documentation:
A constant is an identifier (name) for a simple value. As the name suggests, that value cannot change during the execution of the script (except for magic constants, which aren't actually constants). A constant is case-sensitive by default. By convention, constant identifiers are always uppercase.
If you want more information on constants go ahead and read the documentation, it is explained pretty well there and probably has usage examples.

if you want a variable rather than a function you could make this an anonymous function
$APP_PATH=function(){ return str_replace('//', '/', str_replace('\\', '/', dirname(__FILE__) . '/') }
or
$APP_PATH=function($file){ return str_replace('//', '/', str_replace('\\', '/', dirname($file) . '/') }
which you could call with $APP_PATH [without variables] or $APP_PATH(FILE)
depends on what you wanna do

It executes it once and stores the result in APP_PATH. From that point on, APP_PATH is a scalar value. It's not like a handle to a computation/function or anything.

Tt is stored as the outcome in a single request, at the moment of the define. Hence 'constant'. The next request / script invocation will run the code again, so between requests it could be inconsistent.

Related

using . instead of / in laravel

I learn laravel and I see that when we extend a view we use '.' instead of '/'
example: #extends('layouts.nav')
my question is why do we use '.' instead of '/' and when I used '/' instead of '.' it did the same work
It's better to use dot notation instead of '/'. It's not written in the documents but '/' is used for path separator and in some cases it might return some kind of an error. You can check the laravel docs here.

Is it possible to evaluate an expression before being used as a function name?

I've run into a problem which has a simple solution...
$this->controller = new "controllers\\" . $namespace . $controller($this->relativePath);
I would like to do something like the above, but it doesn't work because it seems the value of the concatenated string is evaluated after $controller($this->relativePath) is evaluated.
The solution is something like this...
$x = "controllers\\" . $namespace . $controller
$this->controller = new $x($this->relativePath);
But it kills me to have a single-use variable. Is there an alternative?
You can tell the PHP engine to evaluate a string and execute it using eval()...most interpreted languages have such a function. I must warn you though, this can be very dangerous if your code is not absolutely correct because the PHP engine cannot be sure that what you are evaluating is proper PHP code. Thus, you will lose some safety that the engine offers when you use that. But if you know what you are doing, this should not deter you from using it; it was meant for this very purpose.
$this->controller = eval("new controllers\\" . $namespace . $controller($this->relativePath));
If the evaluation order is wrong...use parenthesis to convey your intentions; they have the highest precedence.
Eval Documentation
My Personal Recommendation
Use the Strategy Design Pattern
if you definitely don't want to use a second variable, you could instead use reflections:
<?php
function createObject($name, $params = null) {
if($params == null) {
return (new ReflectionClass($name))->newInstance();
} else {
return (new ReflectionClass($name))->newInstanceArgs($params);
}
}
$instance = createObject("your"."classname", ["parameters"]);
one could test how it holds up against eval performance-wise, but since this can only instanciate objects (in contrast to eval, which can arbitrarily execute code), this could provide a security benefit.
you could also expand the function to limit it to certain namespaces etc.

How to separate filename from path? basename() versus preg_split() with array_pop()

Why use basename() in PHP scripts if what this function is actually doing may be written in 2 lines:
$subFolders = preg_split("!\\\|\\/!ui", $path); // explode on `\` or `/`
$name = array_pop($subFolder); // extract last element's value (filename)
Am I missing something?
However I guess this code above may not work correctly if file name has some \ or / in it. But that's not possible, right?
PHP may run on many different systems with many different filesystems and naming conventions. Using a function like basename() guarantees (or at least, is supposed to guarantee) a correct result regardless of the platform. This increases the code's portability.
Also, compare a simple basename() call to your code - which is more readable, and more obvious to other programmers in regards to what it is supposed to do?

Is it possible to disjunct two require_once statements with OR operator to use the latter as fallback?

Is there a way to perform double require_once statement where the second one as a fallback if the first one fails?
For example: I can do this
mysql_query() or die("Boo");
Could I do:
require_once('filename') or require_once('../filename');
If one fails it reverts to the other?
You can't do this because of a weird little quirk in PHP. require_once() is a language construct, not a function. It will interpret the whole line as the argument:
(('filename') or require_once('../filename'))
(added braces for clarity) the result of this operation is 1.
Use is_readable() instead.
if (is_readable($filename))
require_once($filename);
else require_once("../$filename");
or a shorter version that should work:
require_once(is_readable($filename) ? $filename : "../$filename");
#Pekka is correct. I'd add something else though, that might get rid of the issue entirely. If you have files in several different places, you can edit the include paths so that require() and include() look in a variety of places. See set_include_path()
The example in the manual adds a new path to the existing include path:
$path = '/usr/lib/pear';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);

Is there any difference between __DIR__ and dirname(__FILE__) in PHP?

It looks the same for me,but I'm not sure,
because there are many projects that uses dirname(__FILE__).
Their result is exactly the same ; so, no difference on that.
For example, the two following lines :
var_dump(dirname(__FILE__));
var_dump(__DIR__);
Will both give the same output :
string '/home/squale/developpement/tests/temp' (length=37)
But, there are at least two differences :
__DIR__ only exists with PHP >= 5.3
which is why dirname(__FILE__) is more widely used
__DIR__ is evaluated at compile-time, while dirname(__FILE__) means a function-call and is evaluated at execution-time
so, __DIR__ is (or, should be) faster.
As, as a reference, see the Magic constants section of the manual (quoting) :
__DIR__ : The directory of the file.
If used inside an include, the
directory of the included file is
returned. This is equivalent to
dirname(__FILE__). This
directory name does not have a
trailing slash unless it is the root
directory. (Added in PHP 5.3.0.)

Categories