简体   繁体   中英

Class found in PhpStorm but not when running

I'm using PhpStorm to develop an iCal Manager.

I have a class User defined in the namespace Engine used for all the website, and a class User defined in the namespace iCal used for iCal process only, extended from \\Engine\\User .

When coding, PhpStorm can locate \\Engine\\User in order to define \\iCal\\User , but when executing I got a "Fatal Error: Class \\Engine\\User not found".

I'm using PhpStorm 2019.1 with PHP 7.2.4 on WampServer.

I tried to make an alias, didn't work. I tried to require all my files in one then to add it in 'Engine', didn't work either.

\\Engine\\User:

<?php
declare(strict_types=1);
//Created for IGPD by leroy the 27/07/2019

namespace Engine;
use PDO;
use Exception;
use PDOStatement;

/**
 * Class User
 * @property bool attendee
 * @package Engine
 */
class User
{
public function __construct(array $user)
    {
        $this->email = $user['email'];
        $this->name = $user['name'];
        $this->surname = $user['surname'];
        $this->language = $user['language'];
    }
}

\\iCal\\User:

<?php
declare(strict_types=1);
//Created for IGPD by leroy the 27/07/2019

namespace iCal;
use Engine\User as UserAlias;

/**
 * Class User
 * @package iCal
 */
class User extends UserAlias
{
public function __construct(array $user, string $cutype, string $role, bool $rsvp, string $partstat, string $sentby, string $dir, string $type)
    {
        $this->calAddress = "mailto:" . $user['email'];
        $this->cutype = in_array($cutype, ['INDIVIDUAL', 'GROUP', 'RESOURCE', 'ROOM', 'UNKNOWN']) ? $cutype : 'UNKNOWN';
        $this->role = in_array($role, ['CHAIR', 'REQ-PARTICIPANT', 'OPT-PARTICIPANT', 'NON-PARTICIPANT']) ? $role : 'OPT-PARTICIPANT';
        $this->rsvp = $rsvp ? 'TRUE' : 'FALSE';
        $this->cn = $user['name'] . " " . $user['surname'];
        $this->language = in_array($user['language'], ['EN', 'FR']) ? $user['language'] : 'EN';
        $this->partstat = in_array($partstat, ['NEEDS-ACTION', 'ACCEPTED', 'DECLINED', 'TENTATIVE', 'DELEGATED']) ? $partstat : 'NEEDS-ACTION';
        $this->sentby = $sentby;
        $this->dir = $dir;
        $this->type = $type;
        UserAlias::__construct($user);
    }}

I just run the class file to check for errors, so I should not get anything. The actual output is:

Fatal error: Class 'Engine\\User' not found in D:\\wamp\\www\\IGPD\\iCal\\User.php on line 12

Here is iCal.php , the file that require all the files in the directory:

\\iCal\\iCal.php:

<?php
declare(strict_types=1);
namespace iCal;
//Created for IGPD by leroy the 02/08/2019

require_once 'Alarm.php';
require_once 'Calendar.php';
require_once 'Event.php';
require_once 'FreeBusy.php';
require_once 'Journal.php';
require_once 'Todo.php';
require_once 'User.php';

Then I used this in my main page but it's not the one I want to load so I shouldn't need it:

\\Engine\\Engine.php:

<?php
declare(strict_types = 1);
namespace Engine;
session_start();

require_once "collections.php";
require_once "..\iCal\iCal.php";

I do not use autoload.

I've explored the autoload solution mentioned by @ÁlvaroGonzález, and so far it's the only working solution. As a result, I came up with this code, in the index.php at the root of my directory.

\\index.php:

<?php
declare(strict_types=1);
namespace iCal;

spl_autoload_register(function ($class){
require_once    ucfirst($class) . '.php';
});

$e = new Calendar("e", "e", "e", "r", "e");
$f = new User(['email' => "", 'name'=>"", 'surname'=>"", 'language'=>""], "e", "e", true, "e", "e", "e", "e");

I'm glad to say it worked, but I'm afraid that is not the best solution, mainly because this code don't work if the class is defined in another directory.

When you run php foo.php the PHP interpreter loads that single file and no other, unless you explicitly instruct it to do otherwise. On the other side, your IDE does not need to run your code. It just scans your project's directory, compiles all classes, functions, constants, etc. and assumes they're available when you ask about them.

Any complex program calls for splitting code in several files, thus you need to address it. Almost all solutions available involve include et al. in some way, but the details can differ vastly. It's also important to note that namespaces do not play any role in class or file loading—it's just a mechanism to have more short names available as codebases grow and third-party libraries thrive.

Your are using direct calls to require_once to load files. That's roughly equivalent to copying and pasting the included files's code in the exact location of the require_once construct, but there's a caveat: PHP parses each file independently and if you're loading a file with a class definition that depends on another class, you need to have that other classed parsed earlier. Look at this example:

<?php // Animal.php
class Animal
{
}
<?php // Cat.php
class Cat extends Animal
{
}

This script runs flawlessly:

<?php
require_once 'Animal.php';
require_once 'Cat.php';

This one triggers Fatal error: Uncaught Error: Class 'Animal' not found in C:\\tmp\\Cat.php:2 :

<?php
require_once 'Cat.php';
require_once 'Animal.php';

So this is your exact problem: you aren't loading your files in the correct order.

This can be tricky in relatively small projects and it doesn't scale well so that's why class auto-loading was implemented. PHP provides a hook function you can customise and calls that function whenever it finds code that needs a yet unknown class. Your custom function gets the class name as argument and does whatever it sees fit (typically involving an include call).

Some guys wrote a spec on how an autoloader could work and called it PSR-4 . The well-known Composer package manager wrote an auto-loader implementing that spec. So, if you use Composer in your projects, you can benefit from that auto-loader without the need of writing any code. All you need to do is to follow a specific naming convention and directory structure and define where your classes root directory is. So, if you want a class called \\Engine\\User you define it in a file located at /Blah/Blah/Engine/User.php and the class is loaded automatically when it's used in your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM