What does mean if (\false) (yes, with backslash) in PHP? - php

This morning, I've been notified that a new Twig_Extensions release is available! Yay!
Before integrating it to twigfiddle, I wanted to see changes. This is mainly adding support to namespaces using class_alias function, and then add PSR-4 correspoding classes that just include the legacy one.
But each new (namespaced) classes are implemented like this:
<?php
namespace Twig\Extensions;
require __DIR__.'/../lib/Twig/Extensions/Extension/Text.php';
if (\false) {
class TextExtension extends \Twig_Extensions_Extension_Text
{
}
}
What does this notation mean?

It means it's using the false defined in the global namespace..
After a bit of research it turns out the rest of this answer is nonesense... I could swear you were able to do this in PHP at one point in time.
I think this is get around the situation where
<?php
namespace whywouldyoudothis;
false = true;
?>
I have never ever seen anyone code for this but that's what springs to mind.

From php manual
Prefixing a name with \ will specify that the name is required from
the global space even in the context of the namespace.

if (\false) {
class TextExtension extends \Twig_Extensions_Extension_Text
{
}
}
The code is still reachable by code sniffers and IDEs. However I think it should have deprecation note there. So that developers would be notified about using deprecated classes.
Here is an example from main Twig repository.
https://github.com/twigphp/Twig/blob/v2.10.0/lib/Twig/Token.php

This is a no sense code, simply this is a Unreachable code because \false is always false!

Related

Nested namespaces in PHP

So I'm targetting my compiler to PHP and I'm having some problems with namespaces.
They look something like this in my language:
package Foo
{
package Bar
{
class X { }
}
class Y { }
}
Of course, PHP doesn't handle nested namespaces. What's the best way to translate this code so it still works in PHP?
I should note that all files are compiled into a single PHP file in the end. One caveat of this is that I'll have to go back to the global namespace after I've closed a package, and I haven't found any documentation about how to do that. It seems to me that in PHP, once you declare a namespace, it applies to the whole file.
It's true that "Namespace declarations cannot be nested".Namespacing is used to avoid conflicting definitions and introduce more flexibility and organization in your code.The brackets surrounding the namespace code block are completely optional.If you want to translate your code to run able in php. You can write like:
namespace Foo\Bar;
class X{
// Your properties
}
class Y {
// Your properties
}
If you need more information you can see this link well written by Elias Zerrouq with example http://code.tutsplus.com/tutorials/namespacing-in-php--net-27203
Zotoaster it is quite possible to do what you desire; however, my solution would rely on the psr-4 autoloading solution. With this, by placing your files in the appropriate folders, you would be able to do the following at the start of the php file:
use Foo\Bar\X;
use Foo\Y;
Thereafter you can instantiate the classes accordingly:
$x = new X();
$y = new Y();
You can read more on how to use namespaces here: http://www.php-fig.org/psr/psr-4/
Furthermore, you could use composer to handle the "dirty work" for you, i.e. all the auto loading: https://getcomposer.org/doc/01-basic-usage.md#autoloading

Can I put PHP extension classes, functions, etc. in a namespace?

I am writing a PHP extension in C, and I would like to put the classes, functions, and variables I am creating in a namespace. I have not been able to find anything in the extension documentation regarding namespaces. To be clear, I want the equivalent of
namespace MyNamespace{
class MyClass{
}
}
but in a C extension. More specifically, I am looking for a function or macro in the Zend C API that allows me to assign a PHP namespace to a class or function I have written in C. Is this possible?
Putting a class in a namespace is very simple. Where normally you would initialize a class with
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "MyClass", my_class_methods);
instead write the second line as
INIT_CLASS_ENTRY(ce, "MyNamespace\\MyClass", my_class_methods);
The namespace does not need to be included in the method declarations or in the members of the my_class_methods array to properly match them with the class.
To use Namespaces in PHP extensions, you are basically just putting a prefix in front of the class or function name.
I'm not really a PHP internals developer, so the specifics are not entirely clear to me how this works, unfortunately there is very, very little information online that I could find about this as well (I really put Google through it's paces), and the article below is the best I could find.
However, it seems this article hints at the correct solution, which seems to be, that when you register the function with the Zend engine/PHP internals, you do so like "myNS\\MyFunc" and it should then be accessible from the myNS defined there. I would try out a few different variations with this, and see how far that gets you.
Your best option would be to ask in #php-internals on Freenode (if you can get an invitation) or on the PHP Mailing list.
If you manage to find a solution, the Internet seems to be in need of a good article on how one would accomplish this.
Source http://www.php-cpp.com/documentation/namespaces
A namespace is nothing else than a class or function prefix. If you want your classes or functions to appear in a specific namespace, you simply have to add a prefix to the class or function name....
Update: I've updated my answer to try to be more clear. I'm sorry it took so long, I originally replied from my Phone while I was traveling, with every intention of coming back and responding to your original comment, but I genuinely forgot about it until I got a notification from SO about comments. My apologies.

Am I required to use namespaces in Symfony2?

I've just begun learning Symfony2 (after using 1.x for the past 2 years) and am kind of put off by how much more typing is required. I know that sounds lazy, but I love the fact that I can quickly get something up and running in 1.x with much less typing. I'm wondering if it's possible to autoload classes without needing to use namespaces. All my attempts to do so (using the PEAR naming scheme) have failed.
If I'm missing something obvious and would be shooting myself in the foot by avoiding using namespaces, I'd appreciate any advice :)
In response to #KingCrunch:
I'd like to avoid the namespace and use declarations that seem to be used very frequently in Symfony2 simply to speed up my coding. To be honest, I haven't used namespaces in PHP before. I understand their benefit on paper (and I'm used to using packages in other languages) but I've never run into an issue by not using them in Symfony 1.x projects. This is why I made the "If I'm missing something..." statement above.
You have to realize that namespaces are not requiring you any more typing than PEAR-style names. Actually they can save up some characters.
See those two examples:
With PEAR-style:
class Foo_Bar_Baz extends Foo_Bar_Parent
{
public function __construct()
{
$obj = new Some_Long_Class_Name;
$obj2 = new Some_Long_Class_Name;
}
}
With namespaces/use:
namespace Foo\Bar;
use Some\Long\Class\Name;
class Baz extends Class
{
public function __construct()
{
$obj = new Name;
$obj2 = new Name;
}
}
With namespaces, but no use:
namespace Foo\Bar;
class Baz extends \Foo\Bar\Class
{
public function __construct()
{
$obj = new \Some\Long\Class\Name;
$obj2 = new \Some\Long\Class\Name;
}
}
As you see, if you use fully qualified class names every time (last example), you just have one more char per class name, the leading \. If you use the use statements and all, then it gets shorter the more you re-use the same class names in one file, or the more classes you use that are in the same namespace.
TL;DR: Anyway, if you're lazy, get an IDE like PhpStorm that will autocomplete all those and add the use statements for you.
Short answer: yes, namespaces are a must if you want to use Symfony2.
The reason behind this is that sf2 class autoloader is built on the namespace usage. In theory, you could write your own autoloader and wrap it around sf2, but I think this would be more hassle than using namespace and use ;)
At first I was also bummed by it and didn't really like the way it's used. But once I got used to it and started to see the benefits, it's the other way around. I use sf2 for my own projects and must use sf1.4 at work (not for long, hopefully) and every time I switch from sf2 to sf1.4 I get the "oh, not this again" feeling.
NS is so complex that you can even make a mistake when trying to explain the benefits to someone:
I know the point of the answer wasn't to get the code "perfect", but still...You forgot to include the use statement for the "Class" class:
namespace Foo\Bar;
use Some\Long\Class\Name;
use The\Extended\Class;
...
This is why namespaces are horrid - only takes forgetting 1 to throw an error; and, even if there is only 1 class named 'Class' in the entire project, PHP has no idea it's there.

How unique is PHP's __autoload()?

PHP's __autoload() (documentation) is pretty interesting to me. Here's how it works:
You try to use a class, like new Toast_Mitten()(footnote1)
The class hasn't been loaded into memory. PHP pulls back its fist to sock you with an error.
It pauses. "Wait," it says. "There's an __autoload() function defined." It runs it.
In that function, you have somehow mapped the string Toast_Mitten to classes/toast_mitten.php and told it to require that file. It does.
Now the class is in memory and your program keeps running.
Memory benefit: you only load the classes you need. Terseness benefit: you can stop including so many files everywhere and just include your autoloader.
Things get particularly interesting if
1) Your __autoload() has an automatic way of determining the file path and name from the class name. For instance, maybe all your classes are in classes/ and Toast_Mitten will be in classes/toast_mitten.php. Or maybe you name classes like Animal_Mammal_Weasel, which will be in classes/animal/mammal/animal_mammal_weasel.php.
2) You use a factory method to get instances of your class.
$Mitten = Mitten::factory('toast');
The Mitten::factory method can say to itself, "let's see, do I have a subclass called Toast_Mitten()? If so, I'll return that; if not, I'll just return a generic instance of myself - a standard mitten. Oh, look! __autoload() tells me there is a special class for toast. OK, here's an instance!"
Therefore, you can start out using a generic mitten throughout your code, and when the day comes that you need special behavior for toast, you just create that class and bam! - your code is using it.
My question is twofold:
(Fact) Do other languages have similar constructs? I see that Ruby has an autoload, but it seems that you have to specify in a given script which classes you expect to use it on.
(Opinion) Is this too magical? If your favorite language doesn't do this, do you think, "hey nifty, we should have that" or "man I'm glad Language X isn't that sloppy?"
1 My apologies to non-native English speakers. This is a small joke. There is no such thing as a "toast mitten," as far as I know. If there were, it would be a mitten for picking up hot toast. Perhaps you have toast mittens in your own country?
Both Ruby and PHP get it from AUTOLOAD in Perl.
http://perldoc.perl.org/perltoot.html#AUTOLOAD:-Proxy-Methods
http://perldoc.perl.org/AutoLoader.html
Note that the AutoLoader module is a set of helpers for common tasks using the AUTOLOAD functionality.
Do not use __autoload(). It's a global thing so, by definition, it's somewhat evil. Instead, use spl_autoload_register() to register yet another autoloader to your system. This allows you to use several autoloaders, what is pretty common practice.
Respect existing conventions. Every part of namespaced class name is a directory, so new MyProject\IO\FileReader(); should be in MyProject/IO/FileReader.php file.
Magic is evil!
The Mitten::factory method can say to itself, "let's see, do I have a subclass called Toast_Mitten()? If so, I'll return that; if not, I'll just return a generic instance of myself - a standard mitten. Oh, look! __autoload() tells me there is a special class for toast. OK, here's an instance!"
Rather such tricky code, use simple and verbose one:
try {
$mitten = new ToastMitten();
// or $mitten = Mitten::factory('toast');
} catch (ClassNotFoundException $cnfe) {
$mitten = new BaseMitten();
}
I think this feature comes in very handy, and I have not seen any features like it else where. Nor have I needed these features else where.
Java has something similar. It's called a ClassLoader. Probably other languages too, but they stick with some default implementation.
And, while we're at this. It would have been nice if __autoload loaded any type of symbols, not just classes: constants, functions and classes.
See Ruby's Module#const_missing
I just learned this: Ruby has a method on Module called const_missing that gets called if you call Foo::Bar and Bar isn't in memory yet (although I suppose that Foo has to be in memory).
This example in ruby-doc.org shows a way to use that to implement an autoloader for that module. This is in fact what Rails uses to load new ActiveRecord model classes, according to "Eloquent Ruby" by Russ Olsen (Chapter 21, "Use method_missing for flexible error handling", which also covers const_missing).
It's able to do this because of the "convention over configuration" mindset: if you reference a model called ToastMitten, if it exists, it will be in app/models/toast_mitten.rb. If you could put that model any place you wanted, Rails wouldn't know where to look for it. Even if you're not using Rails, this example, and point #1 in my question, shows how useful it can be to follow conventions, even if you create them yourself.

Strategy for developing namespaced and non-namespaced versions of same PHP code

I'm maintaining library written for PHP 5.2 and I'd like to create PHP 5.3-namespaced version of it. However, I'd also keep non-namespaced version up to date until PHP 5.3 becomes so old, that even Debian stable ships it ;)
I've got rather clean code, about 80 classes following Project_Directory_Filename naming scheme (I'd change them to \Project\Directory\Filename of course) and only few functions and constants (also prefixed with project name).
Question is: what's the best way to develop namespaced and non-namespaced versions in parallel?
Should I just create fork in repository and keep merging changes between branches? Are there cases where backslash-sprinkled code becomes hard to merge?
Should I write script that converts 5.2 version to 5.3 or vice-versa? Should I use PHP tokenizer? sed? C preprocessor?
Is there a better way to use namespaces where available and keep backwards compatibility with older PHP?
Update: Decided against use of namespaces after all.
I don't think preprocessing the 5.3 code this is a great idea. If your code is functionally identical in both PHP 5.2 and 5.3 with the exception of using namespaces, instead of underscore-separated prefixes, why use namespaces at all? In that case it sounds to me like you want to use namespaces, for the sake of using namespaces..
I do think you'll find that as you migrate to namespaces, you will start to 'think a bit differently' about organizing your code.
For this reason, I strongly agree with your first solution. Create a fork and do backports of features and bugfixes.
Good luck!
This is a followup to my previous answer:
The namespace simulation code got quite stable. I already can get symfony2 to work (some problems still, but basically). Though there is still some stuff missing like variable namespace resolution for all cases apart from new $class.
Now I wrote a script which will iterate recursively through a directory and process all files: http://github.com/nikic/prephp/blob/master/prephp/namespacePortR.php
Usage Instructions
Requirements for your code to work
Your classnames mustn't contain the _ character. If they do, classnames could get ambiguous while converting.
Your code mustn't redeclare any global functions or constants within a namespace. Thus it is ensured that all your code may be resolved at compile-time.
Basically these are the only restrictions to your code. Though I should note that in a default configuration the namespacePortR will not resolve things like $className = 'Some\\NS\\Class'; new $className, because it would require inserting additional code. It's better that this is patched up later (either manually or using an automated patching system.)
Configuration
As we have made the assumption that no global function or constant is redeclared in a namespace you must set the assumeGlobal class constant in the namespace listener. In the same file set the SEPARATOR constant to _.
In the namespacePortR change the configuration block to satisfy your needs.
PS: The script may be provided a ?skip=int option. This tells it to skip the first int files. You should not need it, if you have set the override mode to intelligent.
Here's what I've found:
Doing this with regular expressions is a nightmare. You can get most of it done with just a few simple expressions, but then edge cases are a killer. I've ended up with horrible, fragile mess that barely works with one codebase.
It's doable with built-in tokenizer and simple recursive descent parser that handles only simplified subset of the language.
I've ended up with rather ugly design (parser and transformer in one – mostly just changing or re-emitting tokens), because it seemed too much work to build useful syntax tree with whitespace maintained (I wanted resulting code to be human-readable).
I wanted to try phc for this, but couldn't convince its configure that I have built required version of Boost library.
I haven't tried ANTLR for this yet, but it's probably the best tool for that kind of tasks.
I am working on a project that emulates PHP 5.3 on PHP 5.2: prephp. It includes namespace support (not yet complete though.)
Now, out of the experience of writing this there is one ambiguity problem in namespace resolution: Unqualified function calls and constant lookups have a fallback to the global namespace. So you could convert your code automatically only if you either fully qualified or qualified all your function calls/constant lookups or if you didn't redefine any function or constant in a namespace with the same name as a PHP built in function.
If you strictly adhered to this practice (whichever of them you choose) it would be fairly easy to convert your code. It would be a subset of the code for emulating namespaces in prephp. If you need help with the implementation, fell free to ask me, I would be interested ;)
PS: The namespace emulation code of prephp isn't complete yet and may be buggy. But it may give you some insights.
Here's the best answer I think you're going to be able to find:
Step 1: Create a directory called 5.3 for every directory w/ php5.3 code in it and stick all 5.3-specific code in it.
Step 2: Take a class you want to put in a namespace and do this in 5.3/WebPage/Consolidator.inc.php:
namespace WebPage;
require_once 'WebPageConsolidator.inc.php';
class Consolidator extends \WebpageConsolidator
{
public function __constructor()
{
echo "PHP 5.3 constructor.\n";
parent::__constructor();
}
}
Step 3: Use a strategy function to use the new PHP 5.3 code. Place in non-PHP5.3 findclass.inc.php:
// Copyright 2010-08-10 Theodore R. Smith <phpexperts.pro>
// License: BSD License
function findProperClass($className)
{
$namespaces = array('WebPage');
$namespaceChar = '';
if (PHP_VERSION_ID >= 50300)
{
// Search with Namespaces
foreach ($namespaces as $namespace)
{
$className = "$namespace\\$className";
if (class_exists($className))
{
return $className;
}
}
$namespaceChar = "\\";
}
// It wasn't found in the namespaces (or we're using 5.2), let's search global namespace:
foreach ($namespaces as $namespace)
{
$className = "$namespaceChar$namespace$className";
if (class_exists($className))
{
return $className;
}
}
throw new RuntimeException("Could not load find a suitable class named $className.");
}
Step 4: Rewrite your code to look like this:
<?php
require 'findclass.inc.php';
$includePrefix = '';
if (PHP_VERSION_ID >= 50300)
{
$includePrefix = '5.3/';
}
require_once $includePrefix . 'WebPageConsolidator.inc.php';
$className = findProperClass('Consolidator');
$consolidator = new $className;
// PHP 5.2 output: PHP 5.2 constructor.
// PHP 5.3 output: PHP 5.3 constructor. PHP 5.2 constructor.
That will work for you. It is a cludge performance-wise, but just a little, and will be done away with when you decide to stop supporting 5.3.
What I did, with a large codebase that used the underscore naming convention (among others), and require_once a whole lot in lieu of an autoloader, was to define an autoloader, and add class_alias lines in the files defining aliases to a classes old name after changing their names to be nice with namespaces.
I then started removing require_once statements where execution was not dependent on inclusion order, since the autoloader would pick stuff up, and namespace stuff as I went along fixing bugs and so on.
It's worked quite well so far.
Well, I don't know if it is the "best" way, but in theory, you could use a script to take your 5.3 migrate code and backport it into 5.2 (potentially even using PHP).
On your namespace files you would want to do something convert:
namespace \Project\Directory\Filename;
class MyClass {
public $attribute;
public function typedFunction(MyClass $child) {
if ($child instanceof MyClass) {
print 'Is MyClass';
}
}
}
To something like:
class Project_Directory_Filename_MyClass {
public $attribute;
public function typedFunction(Project_Directory_Filename_MyClass $child) {
if ($child instanceof Project_Directory_Filename_MyClass) {
print 'Is MyClass';
}
}
}
And in your namespace code you would need to convert from:
$myobject = new Project\Directory\Filename\MyClass();
To:
$myobject = new Project_Directory_Filename_MyClass();
While all your includes and requires would stay the same, I think you would almost need to keep some sort of Cache of all your classes and namespace to do the complex conversion around the 'instanceof' and typed parameters if you use them. That is the trickiest thing I can see.
I haven't tested this on my own, but you may take a look on this php 5.2 -> php 5.3 conversion script.
It's is not the same as 5.3 -> 5.2, but maybe you will find some useful stuff there.
Our DMS Software Reengineering Toolkit can likely implement your solution pretty well. It is designed to carry out reliable source code transformations, by using AST to AST transforms coded in surface-syntax terms.
It has a PHP Front End which is a full, precise PHP parser, AST builder, and AST to PHP-code regenerator. DMS provides for AST prettyprinting, or fidelity printing ("preserve column numbers where possible").
This combination has been used to implement a variety of trustworthy PHP source code manipulation tools for PHP 4 and 5.
EDIT (in response to a somewhat disbelieving comment):
For the OP's solution, the following DMS transformation rule should do most of the work:
rule replace_underscored_identifier_with_namespace_path(namespace_path:N)
:namespace_path->namespace_path
"\N" -> "\complex_namespace_path\(\N\)"
if N=="NCLASS_OR_NAMESPACE_IDENTIFIER" && has_underscores(N);
This rule finds all "simple" identifiers that are used where namespace paths are allowed,
and replaces those simple identifiers with the corresponding namespace path constructed
by tearing the string for the identifier apart into consitutent elements separated by underscores. One has to code some procedural help
in DMS's implementation langauge, PARLANSE, to check that the identifier contains underscores ("has_underscores"), and to implement the tear apart logic by building the corresponding namespace path subtree ("complex_namespace_path").
The rule works by abstractly identifying trees that correspond to language nonterminals (in this case, "namespace_path", and replacing simple ones by more complex trees that represent the full name space path. The rule is written as text, but the rule itself is parsed by DMS to construct the trees it needs to match PHP trees.
DMS rule application logic can trivially apply this rule everywhere throughout the AST produced by the PHP parser.
This answer may seem overly simple in the face of all the complicated stuff that makes up the PHP langauge, but all that other complexity is hidden in the PHP langauge definition used by DMS; that definition is some 10,000 lines of lexical and grammar definitions, but is already tested and working. All the DMS machinery, and these 10K lines, are indications of why simple regexes can't do the job reliably. (It is surprising how much machinery it takes to get this right; I've been working on DMS since 1995).
If you want to see all the machinery that makes up how DMS defines/manipulates a language, you can see a nice simple example.

Categories