Understanding reflection classes - php

I am trying to understand how reflection classes work, I am unable to find a good explanation of one and examples, but also a little help with my own issue!
So, first off my issue:
When making a new reflectionClass I cannot seem to get it to work and use the class.
Here is my code:
$class = new ReflectionClass("Feature\\CollectionTesting\\CollectionTest");
And from what I read from the documentation you are meant to pass it a class name (but mines not in the same directory or in the same file).
This is obviously wrong as it throws me an error:
Uncaught ReflectionException: Class Feature\CollectionTesting\CollectionTest does not exist in (my current file)
With this I was also told I would need to load the classes into the file to be able to use them so I have done like so:
spl_autoload_register(function ($finalPath) {
include $finalPath;
});
Where $finalPath is the path to the file itself. For example it would be something like:
Feature\\CollectionTesting\\CollectionTest.class.php
Is someone able to explain to me how they work and provide examples, plus help me with my issue or help me understand what the issue is so I can get this working?

Related

Php 7.4.3 Class not found

This is my project path configuration
./create.php
/Install/Install.php
create.php
<?php
use Install\Install;
echo "Starting";
$install = new Install();
This gives me the error
PHP Fatal error: Uncaught Error: Class 'Install\Install' not found in /project/create.php:6
Install.php
<?php
namespace Install;
class Install
{
//whatever
}
Can someone explain me what is happening there ?
Obviously I guess that using a require_once line with my filename would probably fix the issue...but I thought using namespace and use import could prevent me from doing that like we do in classic framework like symfony / magento ?
I've seen some post speaking about autoloading, but i'm a little bit lost. Haven't been able to find a clear explanation on the other stack topic neither.
PHP compiles code one file at a time. It doesn't have any native concept of a "project" or a "full program".
There are three concepts involved here, which complement rather than replacing each other:
Namespaces are just a way of naming things. They allow you to have two classes called Install and still tell the difference between them. The use statement just tells the compiler (within one file) which of those classes you want when you write Install. The PHP manual has a chapter on namespaces which goes into more detail on all of this.
Require and include are the only mechanisms that allow code in one file to reference code in another. At some point, you need to tell the compiler to load "Install.php".
Autoloading is a way for PHP to ask your code which file it should load, when you mention a class it hasn't seen the definition for yet. The first time a class name is encountered, any function registered with spl_autoload_register will be called with that class name, and then has a chance to run include/require to load the definition. There is a fairly brief overview of autoloading in the PHP manual.
So, in your example:
use Install\Install; just means "when I write Install, I really mean Install\Install"
new Install() is translated by the compiler to new Install\Install()
the class Install\Install hasn't been defined; if an autoload function has been registered, it will be called, with the string "Install\Install" as input
that autoload function can then look at that class name, and run require_once __DIR__ . '/some/path/Install.php';
You can write the autoload function yourself, or you can use an "off-the-shelf" implementation where you just have to configure the directory where your classes are, and then follow a convention for how to name them.
If you want to Use class from another file, you must include or require the file.
Use require('Install.php'); before use Install\Install;.
If you are planning to do a big project I would recommend to use PHP frameworks rather than coding from scratch.

spl autoloading: Class is not found – namespace issue?

I am just getting my feet wet with PHP autoloading. I actually think I got the basics down, but somehow it still won't work.
I got the following directory structure:
myLib
-bootstrap.php
-sven
-project
project.php
bootstrap.php is the file that will be included to use the lib. In this file, I simply have the following code:
spl_autoload_extensions('.php');
spl_autoload_register();
$var = new \sven\project\project();
$var->init();
And in project.php:
namespace sven\project;
class project {
public function init() {
echo 'It works!';
}
}
The way the autoloader is used, to my understanding, the core PHP autoloader should translate the namespace into directories and then look for a php containing the class.
Instead of displaying 'It works!', a fatal error is thrown. Unfortunately, I can't exactly tell what that error is because the CMS only informs me that there was a fatal error.
But with such a simple structure, I am sure the error is pretty basic and easy to find for someone who knows how it works.
Where am I going wrong with this example – did I correctly describe how the autoloader should work in this setup or is there a misunderstanding?
EDIT: Finally got the error log running:
Fatal error: Class undefined: sven\\project\\project\\project\\project in /xxx/bootstrap.php on line 36
That obviously looks wrong, but how to change that? Why are there two backslashes?
spl_autoload_extensions('.php');
spl_autoload_register();
This code works only with PHP 5.3 and above.
Sven,
I just answered another question about spl_autoload, try my example click here
I hope it helps!
PS:
Also don't just autoload all .php files on your path , that can be dangerous !

Class 'XMLParser' not found

I've created a class called XMLParser which is being inlcuded using an auto include like all the other classes I'm working with.
When I try to instantiate an object using this class, I get the fatal error in the title.
The auto-include function works. Changing the class name makes it work, I'm also quite positive this had been working when I set it up, otherwise the unit tests depending on this class would never have passed.
Is there a built in XMLParser class that could be conflicting with this?
Surely, even if there was that would not be a problem as I'd get a declaration error or the object would just be instantiated anyway?
Any light on the matter would really help. It's frustrating to say the least.
There is a PEAR file called XMLParser.php
This file appears in the PHP include path before my class directories.
When the autoload function requires_once XMLParser.php it finds this file, which rightfully, does not have the XMLParser class defined within.
That's the source of the fatal error.
To avoid this, one should probably namespace their classes.
Shame on me, thanks for all your feedback.

In PHP, is there a way to get all declared classes in a specific namespace?

I'd like to get the names of all classes within a specific namespace in PHP. Currently, I'm attempting to do some magic via reflection on a specific list of named classes, but I'd like to do it without knowing the names ahead of time.
I've tried calling get_declared_classes(), but for whatever reason, classes that I do have available are not showing up. I can call get_declared_classes(), not see Event in the list, then immediately call $x = new Event() without a problem. Something like the following, which I would think should cause a problem...
if (! in_array('Event', get_declared_classes())) { $x = new Event(); }
...works fine. I'm wondering if namespacing these classes and retrieving that way would help alleviate the problem. Is this possible?
EDIT: For clarification, let me add that I am not currently using namespaces, and I am not specifically trying to achieve something from the above listed code. What I want is to get the names of all classes I have declared. Despite the fact the class declarations for all of them are being hit before I call get_declared_classes(), they are not all appearing in the list. I was hoping that namespacing might help solve the problem.
EDIT2: Several people have pointed out that the classes may be autoloaded. I tested this by doing the following. echo(class_exists('Event')) returned a value of 1. echo(class_exists('Event', FALSE)) returned a value of 0. The second, optional parameter to class_exists is whether or not to autoload. So, apparently the class is being autoloaded. That answers that.
So, next question - how do I prevent this? I'm using a framework that really doesn't give me much low-level control. Is there a way to force autoloading, THEN call get_declared_classes, or for get_declared_classes to fire an autoload first?
You do not need to hard code it in the code, you can use variable name:
$class_name = 'Event';
if (!in_array($class_name, get_declared_classes())) {
$x = new $class_name();
};
See similar code in action here: codepad.org/hCLE4ToA.
Also some classes may not appear in get_declared_classes()'s result, because they may not be loaded at the time this function is called. It may be the case if they are autoloaded after you try to instantiate them. See more on autoloading classes here: php.net/autoload.
Does it answer some of your questions? Did it help?

PHP __autoload Cannot redeclare

I started to use the PHP __autoload function and now I'm getting those weird Fatal error: Cannot redeclare class xxx errors.
It's weird since these errors occur on classes I don't even load with the autoload function. And I also use require_once to include the files.
I'm really puzzled about this. Anyone knows anything about this kind of errors when using autoload?
require_once/include_once only looks at the file name when they're trying to include a file, not a class name. So you can have class Foo in both Foo.php and B.php, and then you'll get that error.
I'm not sure how __autoload would cause you any problems, unless __autoload requires Foo.php because it needs class Foo, and you require B.php manually which redefines class Foo.
By the way, use spl_autoload_register instead of __autoload.
i had same situation .. all i changed was and its working for me
include('xxx.php');
to
require_once('xxx.php');
I am not pretend on the best answer. Just my thoughts.
__autoload() is deprecated in PHP 7.2 and will be possiblly deleted.
I found this way to upload/include files
//initialize a function which will upload files
function upload(){//you can call the function as you like
//your path to files goes here
}
spl_autoload_register('upload')//specify the function, where you include your files(in this case it's upload function
I've had this before, not sure what caused it though. Make sure you're using require_once/include_once rather than the normal versions for starters. I think the problem was related to using class_exists without telling it to skip autoloading (class_exists($name, false)) - are you doing this?
I found the problem. Apparently when it wanted to include Bank class, it took the "bank.php" file from the current directory ^^. Which is just the bank page, it should have include "src/model/Bank.php". I removed the current directory from the search list and it has been fixed.
So always make sure the autoload function is including the correct files. Good practice is too name your files more straightforward like class.Bank.php or class.User.php instead of Bank.php or User.php.
Thanks for your help and quick response anyway!

Categories