PHP class not found but it's included - php

I'm including a PHP class with
require_once($ENGINE."/classUser.php");
but when the code is executed i receive this error:
Fatal error: Class 'User' not found in
C:\xampp\htdocs\WebName\resources\engine\ajax\signup.php on line 12
I still can't figure out what's the problem. I'm 99% sure it's correct.
The "$ENGINE" is correct, and the class is correct too (Netbeans suggests me class methods and variables).
signup.php:
<?php
/* Created on: 13/12/2011
* Author:
*
* Description: User signup procedure.
*/
require_once("../settings.php");
require_once($ENGINE."/classUser.php");
$user = new User();
$user->createUser($_POST["username"], $_POST["email"], $_POST["password"]);
?>
classUser.php:
<?php
/* Created on: 13/12/2011
* Author:
*
* Description: This class manages users.
*/
require_once("settings.php");
require_once($LIBRARY."/cassandraphp/cassandra.php");
class User {
public function createUser($username, $email, $password){
$cassandra = Cassandra::createInstance($CASSANDRASERVER);
$cassandra->set(
"user.".$username,
array(
'ID' => uniqid(),
'Username' => $username,
'Email' => $email,
'Password' => $password
)
);
}
}
?>

Check to make sure your environment isn't being picky about your opening tags. My configuration requires:
<?php
If I try to use:
<?
Then I get the same error as you.
Short tags can be enabled through the INI setting short_open_tag.

if ( ! class_exists('User'))
die('There is no hope!');

I had this problem and the solution was namespaces. The included file was included in its own namespace. Obvious thing, easy to overlook.

It may also be, that you by mistake commented out such a line like require_once __DIR__.'/../vendor/autoload.php'; --- your namespaces are not loaded.
Or you forget to add a classmap to the composer, thus classes are not autoloaded and are not available. For example,
"autoload": {
"psr-4": {
"": "src/"
},
"classmap": [
"dir/YourClass.php",
]
},
"require": {
"php": ">=5.3.9",
"symfony/symfony": "2.8.*",

First of all check if $ENGINE."/classUser.php" is a valid name of existing file.
Try this:
var_dump(file_exists($ENGINE."/classUser.php"));

The problem went away when I did
sudo service apache2 restart

My fail might be useful to someone, so I thought I would post as I finally figured out what the issue was. I was autoloading classes like this:
define("PROJECT_PATH", __DIR__);
// Autoload class definitions
function my_autoload($class) {
if(preg_match('/\A\w+\Z/', $class)) {
include(PROJECT_PATH . '/classes/' . $class . '.class.php');
}
}
spl_autoload_register('my_autoload');
In my /classes folder I had 4 classes:
dbobject.class.php
meeting.class.php
session.class.php
user.class.php
When I later created a new class called:
cscmeeting.class.php
I started getting the can't load DbObject class. I simply could not figure out what was wrong. As soon as I deleted cscmeeting.class.php from the directory, it worked again.
I finally realized that it was looping through the directory alphabetically and prior to cscmeeting.class.php the first class that got loaded was cscmeeting.class.php since it started with D. But when I add the new class, which starts with C it would load that first and it extended the DbObject class. So it chocked every time.
I ended up naming my DbObject class to _dbobject.class.php and it always loads that first.
I realize my naming conventions are probably not great and that's why I was having issues. But I'm new to OOP so doing my best.

As a more systematic and structured solution you could define folders where your classes are stored and create an autoloader (__autoload()) which will search the class files in defined places:
require_once("../settings.php");
define('DIR_CLASSES', '/path/to/the/classes/folder/'); // this can be inside your settings.php
$user = new User();
$user->createUser($_POST["username"], $_POST["email"], $_POST["password"]);
function __autoload($classname) {
if(file_exists(DIR_CLASSES . 'class' . $classname . '.php')) {
include_once(DIR_CLASSES . 'class' . $classname . '.php'); // looking for the class in the project's classes folder
} else {
include_once($classname . '.php'); // looking for the class in include_path
}
}

It 'happened to me!
The problem is that somehow you include a file with the same file name of the class thus invalidating the same class!
Check the path of inclusion and these checks files with the same name!

Check your file permissions for the correct linux user for classUser.php

Check File Permissions
Check File size.
Sometimes an inaccessible or corrupted file would be the problem, as was in my case

you should declare namespace in the ClassUser.php, something like this:
<?php
namespace app; // where 'app' is a folder declared as a root for the project
class ClassUser{
public function test(){
//log something here
}
}
?>
Then you can add the class in your other php files like this:
<?php
use app\ClassUser;
$classUserLcl = new ClassUser();
$classUserLcl->test();
?>
and you are done.
Otherwize it will abuse:
You Oh! its a Fatal error : Uncaught Error: Class 'app\ClassUser' not found in ...

When namespace declaration is part of your php class file "this kind of weird errors tends to appear".
Solution: Use namespace with {, your code shows like this:
<?php
namespace path_to\lib {
require_once "folder/php_class_file_where_namespace_declaration_is_part_of_it.php";
**YOUR CODE HERE**
<?php } ?>

Double check your autoloader's requirements & namespaces.
For example, does your autoloader require your namespace to match the
folder structure of where the file is located? If so, make sure they
match.
Another example, does your autoloader require your filenames to
follow a certain pattern/is it case sensitive? If so, make sure the
filename follows the correct pattern.
And of course if the class is in a namespace make sure to include it
properly with a fully qualified class name (/Path/ClassName) or with a use statement at the top of your file.

Maybe it is how you use new User().
Set path something like
$user = new \resources\engine\ajax\User();

If you've included the file correctly and file exists and still getting error:
Then make sure:
Your included file contains the class and is not defined within any namespace.
If the class is in a namespace then:
instead of new YourClass() you've to do new YourNamespace\YourClass()

Yes this happen in cases when use a trait or extend a class, you should be aware to instantiate the class after the class declaration for example:
This example will trigger class not found error:
$class = new A();
class A {
use SomeTrait;
}
To make it to work move the initialization step in the bottom like so:
class A {
use SomeTrait;
}
$class = new A();

I found I had to use the use keyword, as well as the include statement. Tested it with either missing, and it doesn't work.
namespace foo;
use src\config\object;
include('config/object.php');

Related

Calling a method from outside class with dependencies PHP

Problem:
I have an index.php file which has several composer dependencies.
Inside the index.php file i'm trying to call the static method from the outside class in a different php (let's say auth.php) file like this:
/*creating a class instance*/
$var = new AuthClass();
/*accessing an outside class method*/
$var = AuthClass::checkTime($tokenCode);
The issue is the checkTime method inside the class requires a composer dependency as well, which isn't inherited, although the file is located in the same folder as index.php and index.php is included.
PHP Fatal error: Uncaught Error: Class 'Token' not found
I've tried everything - from adding require_once/include 'index.php' to copying the composer autoload to auth.php outside and inside the AuthClass code, but nothing works, i'm still getting the same error.
Additional code:
index.php
require __DIR__ . '/src/vendor/autoload.php';
$argument1 = $_GET['argument1'];
$tokenCode = $_GET['tokenCode'];
include 'config/database.php';
include 'objects/program1.php';
include 'auth.php';
use ReallySimpleJWT\Token;
use Carbon\Carbon;
$secret = "somesecret";
if (($_SERVER['REQUEST_METHOD']) == "GET") {
if ($_GET['url'] == "bankquery") {
if($tokenCode===NULL){
echo "no correct token provided";
print($results);
} else {
$results = Token::validate($tokenCode, $secret);
if ($results = 1){
$var = new AuthClass();
$var = AuthClass::checkTime($tokenCode);
} else {
echo "no correct token provided";
}
}
} else {
echo "some GET other query";
}
?>
auth.php
// loading composer
require __DIR__ . '/src/vendor/autoload.php';
//loading my index.php file
include 'index.php';
//using composer dependencies
use ReallySimpleJWT\Token;
use Carbon\Carbon;
class AuthClass{
public static function checkTime($tokenCode){
// getting payload from token code by accessing the composer dependency method in a class Token
$received = Token::getPayload($tokenCode);
return $received;
}
}
?>
Need help, guys.
You're using AuthClass before it was defined - try move include 'index.php'; line at the end of the file.
You should also include vendor/autoload.php only once - you don't need to repeat this in every file, just make sure that it is included at the top of the entry file which handles request.
But this is more like a result of design problem. You should define AuthClass in separate file and avoid any additional side effects in it - file should only define class. This is part of PSR-1 rules:
Files SHOULD either declare symbols (classes, functions, constants, etc.)
or cause side-effects (e.g. generate output, change .ini settings, etc.)
but SHOULD NOT do both.
Since you're already using autoloader from Composer it should be relatively easy to register your own autoloading rules, so Composer's autoloader will take care about classes autoloading.
If at this point you're still getting Class 'X' not found, you probably did not installed some dependency or your autoloading rules are incorrect.
The simplest solution would be to include your own code in the composer autoloading.
The composer website tells you how to do it.
You don't need to require the composer files yourself and composer handles everything for you.
The PSR-4 tells you how to namespace your code to use Namespacing.

Autoload namespaces based on directory structure

According to the top comment on the PHP page spl_autoload_register( ) :
Good news for PHP 5.3 users with namespaced classes:
When you create a subfolder structure matching the namespaces of the >containing classes, you will never even have to define an autoloader.
<?php
spl_autoload_extensions(".php"); // comma-separated list
spl_autoload_register();
?>
However, when I have the following structure:
* classes/someclass.php
* index.php
Where someclass.php contains the following:
<?php
class someclass {
function __construct( ) {
echo 'It works!';
}
}
?>
and index.php contains:
<?php
spl_autoload_extensions(".php");
spl_autoload_register();
new classes\someclass;
?>
Then I get the following error:
Fatal error: spl_autoload(): Class classes\someclass could not be
loaded
Am I getting this wrong? How can I make this work?
From the comments
This doesn't work either for the class:
<?php
namespace classes;
class someclass {
function __construct( ) {
echo 'It works!';
}
}
?>
In your someclass.php file you must define the namespace at the begginning.
<?php
namespace classes;
TLDR; It works, but:
namespace classes; is missing in classes/someclass.php
set_include_path(__DIR__); is missing in index.php
(spl_autoload_extensions(".php") is not necessary)
Include Path
The SPL autoload implementation is include path based. Using a dot as include path is relative to the working directory (!) which is independent from script file location. __DIR__ names the exact directory that is needed if the classes folder lies next to the index.php file as in the scenario.
Directory Separator mapping
Next the autoloader implementation does map the class namespace separator properly on Unix systems. In case that got lost in the o/p, the PHP source code clearly has this.
Case Sensitivity of File Names
What the source code also shows is that file-names to load are made lowercase. That is, if your file system is case sensitive, the file and directory names must be in lower case.
Refernces:
https://lxr.room11.org/xref/php-src%407.1/ext/spl/php_spl.c#spl_autoload
https://lxr.room11.org/xref/php-src%407.1/ext/spl/php_spl.c#307
PHP - most lightweight psr-0 compliant autoloader
The user, SedaSoft, who had posted the Good news comment you which you refer, had subsequently posted another comment, due to a revision of ideas:
What I said here previously is only true on Windows. The built-in
default autoloader that is registered when you call
spl_autoload_register() without any arguments simply adds the
qualified class name plus the registered file extension (.php) to each
of the include paths and tries to include that file.
Example (on Windows):
include paths:
- "."
- "d:/projects/phplib"
qualified class name to load:
network\http\rest\Resource
Here's what happens:
PHP tries to load
'.\\network\\http\\rest\\Resource.php'
-> file not found
PHP tries to load
'd:/projects/phplib\\network\\http\\rest\\Resource.php'
-> file found and included
Note the slashes and backslashes in the file path. On Windows this
works perfectly, but on a Linux machine, the backslashes won't work
and additionally the file names are case-sensitive.
That's why on Linux the quick-and-easy way would be to convert these
qualified class names to slashes and to lowercase and pass them to the
built-in autoloader like so:
<?php
spl_autoload_register(
function ($pClassName) {
spl_autoload(strtolower(str_replace("\\", "/", $pClassName)));
}
);
?>
But this means, you have to save all your classes with lowercase file
names. Otherwise, if you omit the strtolower call, you have to use the
class names exactly as specified by the file name, which can be
annoying for class names that are defined with non-straightforward
case like e. g. XMLHttpRequest.
I prefer the lowercase approach, because it is easier to use and the
file name conversion can be done automatically on deploying.
Note that this commenter had actually posted an answer here on SO today, containing the above links (along with a short explantation), but it was subsequently deleted, whilst in the review queue - presumably due to its brevity. I have reinstated the commenter's answer, along with the content of the link. Their answer was as follows:
I wrote that comment on php.net some time ago when I was working on a
Windows system. Later, I had to partially revoke what I wrote in that
comment on the very same page in another comment, which also contains
a possible solution to the problem that is the easiest I could think
of (apart from using Composer).
Here is a screenshot of the original answer:
Do not roll your own autoloading, but use composer instead.
Create a composer.json in the root of your project:
{
"autoload": {
"psr-4": {
"classes\\": "classes/"
}
}
}
Install composer, then run
composer dump-autoload
In your index.php, require the autoloader:
require __DIR__ . '/vendor/autoload.php';
For reference, see
https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx
https://getcomposer.org/doc/01-basic-usage.md#autoloading
http://www.php-fig.org/psr/psr-0/
http://www.php-fig.org/psr/psr-4/
Do not use the spl_autoload_extensions () function if the files to load only have the php extension.
In my case, I create a class called autoload .. something similar to this:
<?php
class Autoload
{
private static $_extensions = array(
0 => '.inc',
1 => '.lib.php',
2 => '.class.php',
);
public function __construct()
{
self::set_include_path();
spl_autoload_extensions(implode(',', self::$_extensions));
spl_autoload_register(__CLASS__, 'load_class');
}
public static function set_include_paths()
{
set_include_path(implode(PATH_SEPARATOR, array(
realpath('classes');
realpath('system');
...
get_include_path();,
)));
}
public function load_class($class)
{
if (!empty($class)) {
spl_autoload($class);
}
return false;
}
}
The use of ?> At the end of the file is not necessary.

spl_autoload_register tries to load a class with dependicies

How smart is spl_autoload_register? Does it know to "look ahead" for the class definition in other files before trying to include?
When I run my index.php page I'm seeing
Fatal error: Class 'input\input' not found in /var/www/php/classes/input/date.php on line 4
index.php runs the following (after this block it creates an object from one of the classes, if I uncomment the one line everything works perfectly)
function my_autoloader() {
//include_once "/var/www/php/classes/input/input.php"; //if this is uncommented, it fixes the problem, but I'm not sure why
foreach (glob("/var/www/php/classes/*/*.php") as $filename)
{
require_once $filename;
}
}
spl_autoload_register('my_autoloader');
is my syntax wrong? is spl_autoload_register supposed to function this way? many other files in these folders depend on eachother and the autoloader seems to "figure it out". I'm not sure why it is suddenly hung up on the "input" class in particular
You're using the autoloader in a wrong way. It is only supposed to load the classes you need for a specific request, not the whole folder.
Read more about autoloading classes properly with some good examples: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
You are using it wrongly.
The autoload is used for autoloading only the given class name on the 1st argument of callback, not for loading all classes like you're doing.
For example:
spl_autoload_register(function ($class) {
// ...
$class = stream_resolve_include_path(sprintf("%s.php", $class));
if ($class !== false) {
require $class
}
});
$class will contains the class to load it, so, you can use it to find the file containing this class at your filesystem.

How to use a PHP class from another file?

Let's say I've got two files class.php and page.php
class.php
<?php
class IUarts {
function __construct() {
$this->data = get_data('mydata');
}
}
?>
That's a very rudamentary example, but let's say I want to use:
$vars = new IUarts();
print($vars->data);
in my page.php file; how do I go about doing that? If I do include(LIB.'/class.php'); it yells at me and gives me Fatal error: Cannot redeclare class IUarts in /dir/class.php on line 4
You can use include/include_once or require/require_once
require_once('class.php');
Alternatively, use autoloading
by adding to page.php
<?php
function my_autoloader($class) {
include 'classes/' . $class . '.class.php';
}
spl_autoload_register('my_autoloader');
$vars = new IUarts();
print($vars->data);
?>
It also works adding that __autoload function in a lib that you include on every file like utils.php.
There is also this post that has a nice and different approach.
Efficient PHP auto-loading and naming strategies
In this case, it appears that you've already included the file somewhere. But for class files, you should really "include" them using require_once to avoid that sort of thing; it won't include the file if it already has been. (And you should usually use require[_once], not include[_once], the difference being that require will cause a fatal error if the file doesn't exist, instead of just issuing a warning.)
Use include_once instead.
This error means that you have already included this file.
include_once(LIB.'/class.php');
use
require_once(__DIR__.'/_path/_of/_filename.php');
This will also help in importing files in from different folders.
Try extends method to inherit the classes in that file and reuse the functions
Use include("class.classname.php");
And class should use <?php //code ?> not <? //code ?>

PHP namespaces not working

I'm trying to use PHP namespaces for the first time and can't even get a very basic example working with 2 files. Here's my directory setup:
/Framework/
/Framework/index.php
/Framework/Models/TestModel.php
And here's the code behind the two files.
index.php:
namespace Framework;
use \Framework\Models\TestModel;
$model = new TestModel();
$model->test();
TestModel.php:
namespace Framework\Models;
class TestModel
{
public function test()
{
print("test");
}
}
The error is simply that it cannot find the TestModel class:
Fatal error: Class 'Framework\Models\TestModel' not found in C:\xampp\htdocs\Framework\index.php on line 7
I'm running the PHP via a web browser at localhost/Framework/index.php. It must be something really simple I'm not seeing, can anyone point it out for me?
The Namespace on the File itself "distinguishes" from other classes and functions, however PHP/Server does not know where the physical file is simply based on a Namespace.
So including the file directly, as people has mentioned, lets PHP know exactly what you mean.
When PHP can't find the file, it will call the function spl_autoload_register() and in that method people will usually put a little function to match namespace to directory structure and then load files according.
Another option is to include Composer in your project and use the PSR-4 autoload
{
"require": {
},
"autoload": {
"psr-4": {
"App\\": "app_directoy/",
"Framework\\": "framework_directory/",
}
}
}
When including the composer autoload it will look for everything Framework/* within your framework_directory as you defined.
You should remove 'namespace Framework' and include TestModel.php instead in your index.php - Something like this:
require_once('Models/TestModel.php');
use \Framework\Models\TestModel;
$model = new TestModel();
$model->test();

Categories