php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #60996 Slash agnostic basename()
Submitted: 2012-02-06 21:48 UTC Modified: 2012-02-07 02:49 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: bob at opsat dot net Assigned:
Status: Wont fix Package: *General Issues
PHP Version: 5.3.10 OS: Any
Private report: No CVE-ID: None
 [2012-02-06 21:48 UTC] bob at opsat dot net
Description:
------------
On Windows, basename() works with \ or /. On Unix platforms it only works with /.  
Since / is technically wrong on Windows, it should let you be technically wrong on  
Unix using \. Why? I noticed this while working on a custom autoloader. I was 
trying to basename('namespace\class') and was getting back 'namespace\class' on 
Unix but only getting 'class' on Windows, and 'class' was the expected output.

Since namespaces use a pseudo-filesystem structure I believe basename() (and 
probably dirname()) should be allowed to work properly on them regardless of the 
OS.

"But you are't dealing with files so this is dumb" - when it comes to autoloading, 
namespaces and classes are dealing with files... so.

Test script:
---------------
<?php

// on unix vs on windows

spl_autoload_register(function($name){
	var_dump(basename($name));
	die();
});

new bob\ftw;

?>

Expected result:
----------------
'ftw'

Actual result:
--------------
'bob\ftw' on unix.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-02-07 02:49 UTC] aharvey@php.net
-Status: Open +Status: Wont fix
 [2012-02-07 02:49 UTC] aharvey@php.net
Windows also allows / as a directory separator, which is why basename() supports 
both separators on that platform. Given that it's easy enough to write a function 
in PHP that calls explode() using \ as a delimiter and accesses the last value in 
the array, and namespaces _aren't_ the filesystem, extending basename() doesn't 
make much sense.
 [2014-06-22 16:54 UTC] sun at unleashedmind dot com
This has been requested in bug 32349 in 2005 already, but was rejected with:

> On unix "\name\containing\slashes" is a perfectly valid directory or file name

That is unfortunate, but indeed true.

The behavior on Windows allows to quickly retrieve the shortname of a fully-qualified class name (FQCN).

That is useful when one needs to retrieve the info from arbitrary class names, without having to instantiate a memory-intensive \ReflectionClass (triggering autoloading) and without having to invent (slow) custom helper functions.

cf. https://gist.github.com/sun/7c15ac1e6c68b1334f49

PHP introduced namespaces in 5.3, but PHP core does not provide native utility functions to retrieve

1. The shortname of a fully-qualified class name.
2. The namespace of a fully-qualified class name.

Wondering whether it would be worth to re-open this bug or create a new one to discuss the addition of two simple utility functions to http://php.net/manual/en/ref.classobj.php ?

1. string       class_shortname( string $fqcn )
2. string|false class_namespace( string $fqcn )


Expected result:
----------------
Platform: Any

FQCN                 class_namespace()  class_shortname()
-------------------- ------------------ -----------------
Name\Spaced\Class    'Name\Spaced'      'Class'
\Name\Spaced\Class   'Name\Spaced'      'Class'
Class                FALSE              'Class'
\Class               FALSE              'Class'


Not familiar with hacking C, but these two helper functions sound trivial to implement to me; possibly even backportable as minor feature additions to 5.4+ ?

Thoughts?

---

For completeness, like the OP, I originally wanted to ask whether we can move basename()'s platform-specific behavior on Windows into the regular code so that backslashes work as delimiters on all platforms...

Test script:
------------
<?php
$classes = array(
  'Name\Spaced\Class',
  '\Name\Spaced\Class',
  'Class',
  '\Class',
);
echo 'Platform: ', PHP_OS, "\n\n";
printf("%-20s %-15s %s\n", 'FQCN', 'dirname()', 'basename()');
printf("%-20s %-15s %s\n", str_repeat('-', 20), str_repeat('-', 15), str_repeat('-', 10));
while ($class = array_shift($classes)) {
  printf("%-20s %-15s %s\n", $class, dirname($class), basename($class));
}

Expected result:
----------------
Platform: - All -

FQCN                 dirname()       basename()
-------------------- --------------- ----------
Name\Spaced\Class    Name\Spaced     Class
\Name\Spaced\Class   \Name\Spaced    Class
Class                .               Class
\Class               \               Class

Actual result:
--------------
Platform: WINNT

FQCN                 dirname()       basename()
-------------------- --------------- ----------
Name\Spaced\Class    Name\Spaced     Class
\Name\Spaced\Class   \Name\Spaced    Class
Class                .               Class
\Class               \               Class

Platform: Linux

FQCN                 dirname()       basename()
-------------------- --------------- ----------
Name\Spaced\Class    .               Name\Spaced\Class
\Name\Spaced\Class   .               \Name\Spaced\Class
Class                .               Class
\Class               .               \Class
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 11:01:30 2024 UTC