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.
Related
A few years back Symfony introduced glob patterns for importing and loading configuration files. You can see an example of this in the stock kernel class
protected function configureRoutes(RouteCollectionBuilder $routes): void
{
$confDir = $this->getProjectDir() . '/config';
$routes->import($confDir . '/{routes}/*' . self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir . '/{routes}/' . $this->environment . '/**/*' . self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir . '/{routes}' . self::CONFIG_EXTS, '/', 'glob');
}
Those glob patterns expand to look like this
$routes->import("/path/to/symfony/config/{routes}/*.{php,xml,yaml,yml}", ...
$routes->import("/path/to/symfony/config/{routes}/dev/**/*.{php,xml,yaml,yml}", ...
$routes->import("/path/to/symfony/config/{routes}.{php,xml,yaml,yml}", ...
This brings a few questions to mind. First off -- what is the ** pattern? That's not a standard part of PHP's glob syntax. I presume by context it means "everything in this folder and all sub-folders", but I can't find official docs on Symfony's glob syntax to know for sure.
Other things about the patterns are odd -- like {routes}. Normally you put things in braces when you want to match a list -- but this uses braces with only one item in the list which makes me think I don't understand what's going on?
When I go spelunking in the source code the methods involved are big ones and not the most intuitive to follow.
Is Symfony's glob syntax an implementation of a standard glob syntax? Or is it its own thing, and if so, what extra features does it have beyond the standard wildcards? (regexes? more special things like **? does a single word in a brace mean anything?)
So far I have only worked with *, but, are there something like lookaheads, groups?
I would like to get all *.php except controller.php.
What I have to alter in this glob(dirname(__FILE__) . DIRECTORY_SEPARATOR . '*.php') call, to exclude controller.php?
Or should I avoid glob and work with something else instead?
php glob() uses the rules used by the libc glob() function, which is similar to the rules used by common shells. So the patterns that you are allowed to use are rather limited.
glob() returns an array of all the paths that match the given pattern. Filtering controller.php out the result array is one solution.
As per http://www.manpagez.com/man/3/glob/: (the backend behind php's glob()) The glob() function is a pathname generator that implements the rules for file name pattern matching used by the shell.
It is a single filter, no exceptions. If you want *.php, you'll get *.php.
Try this,
<?php
$availableFiles = glob("*.txt");
foreach ($availableFiles as $key => $filename) {
if($filename == "controller.php"){
unset($availableFiles[$key]);
}
}
echo "<pre>"; print_r($availableFiles);
?>
Is there a PHP internal function for path concatenation ? What possibilities do I have to merge several paths (absolute and relative).
//Example:
$path1="/usr/home/username/www";
$path2="domainname";
$path3="images/thumbnails";
$domain="exampledomain.com";
//As example: Now I want to create a new path (domain + path3) on the fly.
$result = $domain.DIRECTORY_SEPARATOR.$path3
Ok, there is an easy solution for this example, but what if there are different dictionary separators or some paths are a little bit more complicated?
Is there an existing solution for trim it like this: /home/uploads/../uploads/tmp => /home/uploads/tmp ....
And how would a platform-independent version of an path-concat-function look like?
should an relative path start with "./" as prefix or is "home/path/img/" the common way?
I ran into this problem myself, primarily regarding the normalization of paths.
Normalization is:
One separator (I've chosen to support, but never return a backwards slash \\)
Resolving indirection: /../
Removing duplicate separators: /home/www/uploads//file.ext
Always remove trailing separator.
I've written a function that achieves this. I don't have access to that code right now, but it's also not that hard to write it yourself.
Whether a path is absolute or not doesn't really matter for the implementation of this normalization function, just watch out for the leading separator and you're good.
I'm not too worried about OS dependence. Both Windows and Linux PHP understand / so for the sake of simplicity I'm just always using that - but I guess it doesn't really matter what separator you use.
To answer your question: path concatenation can be very easy if you just always use / and assume that a directory has no trailing separator. 'no trailing separator' seems like a good assumption because functions like dirname remove the trailing separator.
Then it's always safe to do: $dir . "/" . $file.
And even if the result path is /home/uploads/../uploads//my_uploads/myfile.ext it's still going to work fine.
Normalization becomes useful when you need to store the path somewhere. And because you have this normalization function you can make these assumptions.
An additional useful function is a function to make relative paths.
/files/uploads
/files/uploads/my_uploads/myfile.ext
It can be useful to derive from those two paths, what the relative path to the file is.
realpath
I've found realpath to be extremely performance heavy. It's not so bad if you're calling it once but if you're doing it in a loop somewhere you get a pretty big hit. Keep in mind that each realpath call is a call to the filesystem as well. Also, it will simply return false if you pass in something silly, I'd rather have it throw an Exception.
To me the realpath function is a good example of a BAD function because it does two things: 1. It normalizes the path and 2. it checks if the path exists. Both of these functions are useful of course but they must be separated. It also doesn't distinguish between files and directories. For windows this typically isn't a problem, but for Linux it can be.
And I think there is some quirky-ness when using realpath("") on Windows. I think it will return \\ - which can be profoundly unacceptable.
/**
* This function is a proper replacement for realpath
* It will _only_ normalize the path and resolve indirections (.. and .)
* Normalization includes:
* - directiory separator is always /
* - there is never a trailing directory separator
* #param $path
* #return String
*/
function normalize_path($path) {
$parts = preg_split(":[\\\/]:", $path); // split on known directory separators
// resolve relative paths
for ($i = 0; $i < count($parts); $i +=1) {
if ($parts[$i] === "..") { // resolve ..
if ($i === 0) {
throw new Exception("Cannot resolve path, path seems invalid: `" . $path . "`");
}
unset($parts[$i - 1]);
unset($parts[$i]);
$parts = array_values($parts);
$i -= 2;
} else if ($parts[$i] === ".") { // resolve .
unset($parts[$i]);
$parts = array_values($parts);
$i -= 1;
}
if ($i > 0 && $parts[$i] === "") { // remove empty parts
unset($parts[$i]);
$parts = array_values($parts);
}
}
return implode("/", $parts);
}
/**
* Removes base path from longer path. The resulting path will never contain a leading directory separator
* Base path must occur in longer path
* Paths will be normalized
* #throws Exception
* #param $base_path
* #param $longer_path
* #return string normalized relative path
*/
function make_relative_path($base_path, $longer_path) {
$base_path = normalize_path($base_path);
$longer_path = normalize_path($longer_path);
if (0 !== strpos($longer_path, $base_path)) {
throw new Exception("Can not make relative path, base path does not occur at 0 in longer path: `" . $base_path . "`, `" . $longer_path . "`");
}
return substr($longer_path, strlen($base_path) + 1);
}
If the path actually exists, you can use realpath to expand it.
echo realpath("/home/../home/dogbert")
/home/dogbert
Another problem with realpath is that it doesn't work with URLs, and yet the logic of concatenation is essentially the same (there should be exactly one slash between two joined components). Obviously the protocol portion at the beginning with two slashes is an exception to this rule. But still, a function that joined the pieces of a URL together would be really nice.
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);
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.