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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: bob at opsat dot net
New email:
PHP Version: OS:

 

 [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 15:01:29 2024 UTC