PHP : Only use a class if it exists - php

Is there a way to make sure that the file exists before using the classes name in a file
This is to avoid errors incase it doesn't exist? I have researched this but nobody tells you how to do it. Maybe thats because there isn't a way or its only a way that secret php coders knew so please dont dislike this question because of the amount of information given about it.
I tried
if (class_exists("Authentication"))
{
use go\Authentication;
}
But I get this error
Parse error: syntax error, unexpected 'use' (T_USE) in C:\xampp\htdocs\index.php on line 29
I also tried this method
if (file_exists("/go/authentication.php") { use go\Authentication; }
And it gave me the same error as the previouse method

Besides of your original intention, in the documentation you can read:
The use keyword must be declared in the outermost scope of a file (the global scope) or inside namespace declarations. This is because the importing is done at compile time and not runtime, so it cannot be block scoped. The following example will show an illegal use of the use keyword:
Which means that it should be used in the top of the file or, at least, in the outermost scope. While your case might be the outermost scope, it is bound to a conditional, which makes your rule illegal, similarly to the example provided in the documentation:
<?php
namespace Languages;
class Greenlandic
{
use Languages\Danish;
...
}
?>
About your problem, you could simply do:
if (class_exists("Authentication"))
$Auth = new Authentication();
However, have a look into autoloading, since that seems more likely what you are looking for.

You are using use wrong!!
The 'use' keyword must be declared in the outermost scope of a file
(the global scope) or inside namespace declarations. This is because
the importing is done at compile time and not runtime, so it cannot be
block
scoped.
As far as loading the class on the fly is concerned. You can use autoloading as suggested in the comments
On a side note. If your class is found inside a namespace such as
namespace foo\bar;
class tar{
}
then the right way to check it exists is not
class_exists('tar')
but rather:
class_exists('\foo\bar\tar')
or
use foo\bar;
class_exists('tar');

Related

PHP conditionally require/use library class [duplicate]

I've never seen this structure anywhere, so I wonder if there's something wrong with an expression like this:
if (condition) {
use Symfony\Component\HttpFoundation\Response;
}
The only thing use does is to alias a class name. That's it. Nothing more.
Instead of having to repeatedly write the fully qualified classname in your script:
$q = new \Foo\Bar\Baz\Quux;
if ($q instanceof \Foo\Bar\Baz\Quux) ...
You can shorten that to:
use Foo\Bar\Baz\Quux;
$q = new Quux;
if ($q instanceof Quux) ...
As such, it makes absolutely no sense to want to use use conditionally. It's just a syntactic helper; if it could be used conditionally your script syntax would become ambiguous, which is something nobody wants.
It doesn't reduce code loading, because code is only loaded explicitly by require/include calls or via autoloading. The latter one is greatly preferred, since it already lazily springs into action only when needed.
This will throw a syntax error. From TFM:
The use keyword must be declared in the outermost scope of a file
(the global scope) or inside namespace declarations. This is because
the importing is done at compile time and not runtime, so it cannot be
block scoped.

Can magic constants be imported in PHP

I cannot find any hint about the fact I cannot import any magic constant.
Trying to like ...
<?php declare( strict_types = 1 );
namespace CodeKandis\MyVendor;
use function dirname;
use const __DIR__;
require_once dirname( __DIR__ ) . '/vendor/autoload.php';
... leads to
Parse error: syntax error, unexpected '__DIR__' (T_DIR), expecting identifier (T_STRING) or \\ (T_NS_SEPARATOR) in /public/index.php on line 5
This question is important while PHPStorm tends to auto import magic constants. And if it's not possible this needs to be reported and fixed.
Edit (2019-07-25)
After I opened an issue this will be fixed in PHPStorm 2019.3.
In PHP only OOP stuff (classes, interfaces, exceptions, errors...) must be fully named-qualified. If you do not specify full name or do not import class into another namespace, PHP will not fallback to global namespace to look for it.
You can also use fully-specified functions or constants. Functions can belong to a namespace, and in fact all core functions belong to global namespace i.e. \. PHP will first look for the function in the current namespace and it will fall back to global functions or constants if a namespaced function or constant does not exist. You can perform micro-optimization if you specify the global namespace explicitly, because PHP will look in the global namespace directly.
namespace A {
function phpinfo(){
echo 'I am bogus';
}
phpinfo(); // vs. \phpinfo()
}
Magic constants are not really constants at all. They change value based on the context. They are more like magic variables. The following code is invalid, because these constants do not belong to any namespace, not even the global one.
namespace A {
echo \__LINE__;
}
At compile time PHP will substitute them with the actual values. They can't be imported either for exactly the same reason, they are not defined anywhere, they are simply an instruction for the compiler.
There are also other things which can't be imported or namespaced, see: List of Keywords.
You cannot use any of the following words as constants, class names, function or method names.
namespace A {
\echo 'hi'; // <-- this line is invalid code
\die(1); // neither is this, even if it looks and behaves like a function
}
Some people confusingly put parentheses after echo or print, treating them like functions, but in reality they are not. The ones listed with parentheses behave like functions accepting parameters, but you can't import them either.

'use' directive while using ReflectionClass in symfony app

I have a class in my symfony 3 app with a method that should instantiate a Model class dynamically using the name that's passed in to the function, i.e.:
static function getInstance($modelName){
use $modelName;
$r = new \ReflectionClass($modelName);
return $r->newInstanceArgs();
}
But there's a syntax error on the use directive.
I've tried adding specific use statements for every class at the top of the file; and I've also tried using require with a fully qualified path to the corresponding PHP file - but neither approach has worked.
Please advise how to correctly do this.
What about this? use qualified class name
static function getInstance($modelName){
$r = new \ReflectionClass('AppBundle\Entity\\' . $modelName);
return $r->newInstanceArgs();
}
Also, per PHP USE Documentation:
Scoping rules for importing
The use keyword must be declared in the outermost scope of a file (the global scope) or inside namespace declarations. This is because the importing is done at compile time and not runtime, so it cannot be block scoped. The following example will show an illegal use of the use keyword:
Example #5 Illegal importing rule
namespace Languages;
function toGreenlandic() {
use Languages\Danish;
}

Import class conditionally with the keyword 'use'

I've never seen this structure anywhere, so I wonder if there's something wrong with an expression like this:
if (condition) {
use Symfony\Component\HttpFoundation\Response;
}
The only thing use does is to alias a class name. That's it. Nothing more.
Instead of having to repeatedly write the fully qualified classname in your script:
$q = new \Foo\Bar\Baz\Quux;
if ($q instanceof \Foo\Bar\Baz\Quux) ...
You can shorten that to:
use Foo\Bar\Baz\Quux;
$q = new Quux;
if ($q instanceof Quux) ...
As such, it makes absolutely no sense to want to use use conditionally. It's just a syntactic helper; if it could be used conditionally your script syntax would become ambiguous, which is something nobody wants.
It doesn't reduce code loading, because code is only loaded explicitly by require/include calls or via autoloading. The latter one is greatly preferred, since it already lazily springs into action only when needed.
This will throw a syntax error. From TFM:
The use keyword must be declared in the outermost scope of a file
(the global scope) or inside namespace declarations. This is because
the importing is done at compile time and not runtime, so it cannot be
block scoped.

Resetting a namespace in PHP?

How can I "reset" a namespace to the global one? Given the following code:
namespace foo;
include 'myfile.php';
myfile.php will now try to load all of its classes in the foo namespace, even though its classes are in the global namespace. Now it wouldn't be a big deal to swap the order of those lines, but how would I deal with myfile.php having an autoloader? It will try to load the classes in namespace foo.
Namespaces work on a per-file basis. If myfile.php doesn't declare any namespace then everything in it will belong to the global namespace, regardless of the namespace in which include was used.
Long story short, namespace declarations only apply to their own file, not includes.
myfile.php should declare the namespace that it wants to be in. If you want to ensure that myfile.php loads in the global namespace, I believe you can put
namespace // empty namespace means global
{
}
around the body of myfile.php. Make sure that you use the braces, or else you'll redefine the rest of the file in which myfile.php is included to also be in the global namespace.
Maybe I didn't understand your question well ; in that case, could you provide an example of what you get, and what you'd expect ?
Are you sure it will try to load the functions from myfile.php in the foo namespace ?
Considering I have one file (temp-2.php) that looks like this :
<?php
namespace foo;
function my_function_this_file() {
var_dump(__FUNCTION__);
}
my_function_this_file();
include 'my_other_file.php';
my_function_the_other_file();
And another one (my_other_file.php) that looks like this :
<?php
function my_function_the_other_file() {
var_dump(__FUNCTION__);
}
When I call the first one from my browser, I get this output :
string 'foo\my_function_this_file' (length=25)
string 'my_function_the_other_file' (length=26)
This seems to indicate the second function is not inside any namespace, except the global one -- which corresponds to the fact that it's not declared in any namespace.
If I remember correctly, the "namespace" instruction is only valid for the file it is used in, and not for included files.
The Import names cannot conflict with classes defined in the same file page from the namespaces FAQ seems to indicate that too.
Hope this helps, and I understood the question correctly...
EDIT : btw, swapping the order of the to lines, like this :
<?php
include 'my_other_file.php';
namespace foo;
Wouldn't work : the "namespace" instruction must be the first one of the file : you'll get a Fatal Error, if you do that :
Fatal error: Namespace declaration statement has to be the very first statement in the script
I'd just like to chime in on this with my findings. Since PHP cannot handle exceptions in __toString methods, the solution is to do it yourself: something along the lines of
public function __toString()
{
try {
return $this->draw();
} catch ( \Exception $e ) {
die( \error::_getExceptionPage( $e ) );
}
}
However what becomes really weird, the namespace of the call to error::_getExceptionPage($e) becomes the same as the class in which __toString was defined - and I wasn't able to find a way around that except prefixing everything in my exception handling code with \, i.e. every call to any class in getExceptionPage must become \someClass::staticMethod().
Same goes for included files, everything - all code since the thrown exception becomes embedded in the namespace of the faulty class. Tested with PHP 5.3.17

Categories