PHP - Class 'My\Engine\Control' not found - php

The following code is included by another file. My\Engine\Control is defined much earlier and extended all throughout my site with no issues. However in this one file I get the the error:
Fatal error: Class 'My\Engine\Control' not found in
/mnt/web/~/classes.php on line 6
<?php
namespace My\Engine;
// class Control {}
class RequiresAccount extends Control {
public function permissions() {
}
}
Yet when I try to put a dummy Control class in (uncomment the commented part) I get a different error.
Fatal error: Cannot declare class My\Engine\Control, because the name
is already in use in /mnt/web/~/Control.class.php on line 47
It seems impossible and I just can't figure it out. I write code like this all the time and just this one time...
All other files that require extending \My\Engine\Control function perfectly.

It seems that your using some custom autoload logic and some kind of optimizer which puts all the classes together into one file.
I would suggest sticking with PSR-4 standard & Composer library to support and maintain it.
This way your files will be organized and composer will take care of properly handling loading the files and optimizing the loading process for production. All you need to do is to include ./vendor/autoload.php file into your project and define the auto-loading strategy in composer.json file.

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.

Fatal error: Cannot redeclare class convertThis [duplicate]

i have fetal error message say :
Fatal error: Cannot redeclare class Database in C:\wamp\www\pets_new\lib\database.php on line 3
require_once("lib/message.php");
require_once("lib/user.php");
and all connect to database class
Class message
<?php
require('database.php');
class Message{
Class user :
<?php
require('database.php');
class User{
You include 2 files in a single "run". Think of it like this: All the included files are put together by PHP to create one big script. Every include or require fetches a file, and pastes its content in that one big script.
The two files you are including, both require the same file, which declares the Database class. This means that the big script that PHP generates looks like this:
class Message
{}
class Database
{}//required by message.php
class User
{}
class Database
{}//required by user.php
As you can see class Database is declared twice, hence the error.
For now, a quick fix can be replacing the require('database.php'); statements with:
require_once 'database.php';
Which checks if that particular file hasn't been included/required before. If it has been included/required before, PHP won't require it again.
A more definitive and, IMHO, better solution would be to register an autoloader function/class method, and let that code take care of business.
More on how to register an autoloader can be found in the docs. If you go down this route, you'd probably want to take a look at the coding standards concerning class names and namespaces here. If you conform to those standards, you don't have to write your own autoloader, and can simply use the universal class loader from Symfony2, or any other framework that subscribes to the PHP-FIG standards (like CodeIgnitor, Zend, Cake... you name it)
Try like this , while declaring class
if( !class_exists('database') ) {
require('database.php');
}
This means that you've already declared the class Database, the second time it's loaded (where ever the copy is), it's causing the error. We cannot see your content of the two files you've quoted. However, I'm sure if you look in both of them you'll find at least two creations of the class Database. One needs to be removed.

What's the best way to include files in my classes? What I'm doing breaks frequently

So I'm having some trouble with classes not finding the subclasses or parents sometimes.
For instance, I have a very simple class with a subclass that gives me a lot of trouble.
The main class is called Activities and the subclass is called DirectMessage.
Here's the activity class layout.
namespace activities;
require_once(INCLUDES . '/classes/activities/DirectMessage.php');
class activities extends \BaseController {
}
And here's the one for DirectMessage.
namespace DirectMessage;
use activities\activities;
class DirectMessage extends activities
{
}
I use activities all the time, but when I started including DirectMessage, it started giving me errors like this: Fatal error: Class 'activities\activities' not found in /includes/classes/activities/DirectMessage.php on line 13
Unfortunately, it doesn't ALWAYS give me this error, so it's got something to do with where it's being called from I guess.
Is there a better way to require my subclasses?
I'd recommend using Composer's PSR-4 autoloading for this, even if you're not loading in any dependencies with Composer. It's the easiest way I've found get basic autoloading working.
In short, PSR-4 autoloading will allow you to map namespaces to folder structures. Composer will generate an autoload file (vendor/autoload.php) - and this will be the one and only file you should have to require() in your entire project.

how does phunit process several files regarding requires/includes?

I'm calling phpunit with the argument being a directory (bonus questions: why can't it accept a list of files?) and it's now complaining about a class being declared more than once because of a file included in the previous test!
If i run phpunit firstTest.php; phpunit secondTest.php everything works
But phpunit ./ fails with PHP Fatal error: Cannot redeclare class X
my tests are basically:
include 'class_to_be_tested.php'
class class1Test extends...
and nothing else. And i'm using the option --process-isolation. I could add require_once on my classes, but that's not what i want to be able to test them individually.
shouldn't phpunit follow best testing practices and run one test, clear whatever garbage it have, run another test on a clean state? or am i doing something wrong?
Since you have include rather than include_once and there is no other code shown in your question, the cannot redeclare error could also be that you are including the file again somewhere in the code under test.
Assuming that is not the case, there some behind the scenes things that happen with --process-isolation that can keep the global class declarations. This blog post gives more detail: http://matthewturland.com/2010/08/19/process-isolation-in-phpunit/
Basically, you will want to create your own base TestCase and override the run() method to set the preserveGlobalState to false. This should properly allow all your tests to run together.
The base class would look similar to this (taken from the blog post I referred to):
class MyTestCase extends PHPUnit_Framework_TestCase
{
public function run(PHPUnit_Framework_TestResult $result = NULL)
{
$this->setPreserveGlobalState(false);
return parent::run($result);
}
}
The way phpUnit works means that all your tests are run in the context of a single php program. phpUnit aims to isolate the tests from each other, but they are all run within the same program execution.
PHP's include statement will include the requested file regardless of whether it has been included before. This means that if you include a given class twice, you will get an error the second time. This is happening in your tests because each test is including the same file, but without any consideration to whether it's already been included by one of the other tests.
Solutions:
Wrap your include calls with a if(class_exists('classname')) so that you don't include the file if the class has already been defined.
Include the files in a phpUnit bootstrap file instead of in the tests.
Use include_once (or even require_once) instead of include.
Stop including files arbitrarily, and start using an autoloader.
Change:
include 'class_to_be_tested.php';
class class1Test extends...
to be:
include_once 'class_to_be_tested.php';
class class1Test extends...
In PHP you need to have a Really Good Reason to use the former.
Regarding why can't it accept a list of files?, I think the design decision is that you generally don't need to. However you can do it by creating a test suite in the phpunit.xml.dist file, see
http://www.phpunit.de/manual/current/en/organizing-tests.html#organizing-tests.xml-configuration

Codeigniter extending exception class

I am trying to load a custom exception class that I created according to the instructions here:
http://codeigniter.com/user_guide/general/core_classes.html
MY_Exceptions.php is stored at application/core/
Somehow, when I try loading it, I keep getting this error:
Fatal error: Class 'MY_Exceptions' not found in C:\xampp\htdocs\xampp\facebook\application\models\campaign_model.php on line 29
Based on the instructions, it doesn't say I have to autoload the class or anything. What am I doing wrong?
MY_Exception.php is stored at application/core/
Name the class and file MY_Exceptions with an s
You do not need to autoload or manually load anything in the core directory, nor should you. They are required classes for CI to run that are automatically loaded.
For creating core classes, use this documentation instead: http://codeigniter.com/user_guide/general/core_classes.html
Keep in mind that when calling the class you will use the original class name. Let's say you have created MY_Input. Example:
$this->input->post(); // Do this
$this->my_input->post(); // Don't do this
To understand the why and how, see system/core/Common.php function load_class.
Looking at the docs now, I agree that this should probably be highlighted.
It's trying to find MY_ExceptionS.php, not MY_Exception.php.

Categories