I use symfony 2.4.0. I want to use my custom class as discussed here: Autoloading a class in Symfony 2.1. I have created subfolder in src:
namespace Yur;
class MyClass {
public go() {
var_dump('hello!! 32');
}
}
In my controller, I made this:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Yur\MyClass;
class WelcomeController extends Controller
{
public function indexAction()
{
$my = new MyClass();
$my->go();
die();
...
but it makes an exception:
ClassNotFoundException: Attempted to load class "MyClass" from namespace "Yur" in /var/www/shop.loc/src/Acme/DemoBundle/Controller/WelcomeController.php line 12. Do you need to "use" it from another namespace?
After I have got this exception, I decided consciously to make syntax error exception in my class to see if it loaded. I changed class MyClass ... to class4 MyClass ..., but doesnt got asyntax error` exception. And I decided, that my class is not loaded.
Is anyone knows why? And what I must to do to resolve?
A few things. First, in your code sample above, you have
public go() {
var_dump('hello!! 32');
}
which should be
public function go() {
var_dump('hello!! 32');
}
The former raises a parser error in PHP. and probably isn't what you want.
Second, the error
ClassNotFoundException: Attempted to load class "MyClass" from namespace "Yur" in /var/www/shop.loc/src/Acme/DemoBundle/Controller/WelcomeController.php line 12. Do you need to "use" it from another namespace?
is the error Symfony uses when it attempt to autoload a class, but can't find the file. This usually means your file is named incorrectly, or in the wrong folder. I'd tripped check that you have a file in the directory you think you do.
$ ls src/Yur/MyClass.php
You can also add some debugging to the composer autoload code to see what path it's cooking up for your custom class
#File: vendor/composer/ClassLoader.php
public function findFile($class)
{
//...
$classPath .= strtr($className, '_', DIRECTORY_SEPARATOR) . '.php';
//start your debugging code
if($class == 'Yur\MyClass')
{
//dump the generated path
var_dump($classPath);
//dump the default include paths
var_dump($this->fallbackDirs);
}
//...
}
Related
I have a folder test. In this folder I have a two classes, TestHeader and TestHeaders.
This is TestHeader class
<?php
class TestHeader
{
public function send(): void
{
}
}
This is TestHeaders class
<?php
class TestHeaders
{
public function profile(int $userId): TestHeader
{
return new TestHeader();
}
}
And when I run tests, show me error Fatal error: Uncaught Error: Class "TestHeader" not found in C:\project\test\TestHeaders.php:7 I don't know why show this error. Someone could me explain why this error is and how I can fix it ?
if you'r not using a php framework that implement the autoload and if you not set up an autoload strategy you have to include all file you'r trying to use in another file.
add include("TestHeader.php"); at start of TestHeaders class, on the line immediately after the <?php tag
So, I'm converting some old code into a namespace, and trying to get autoload working. I've managed to follow the many good answers on this site about how to account for the namespace part of an autoloaded class (How do I use PHP namespaces with autoload?) - no problem.
Here's a different wrinkle, though. How do I autoload classes within the same namespace?
My autoload function (defined in a global include) is something like this:
function app_autoload($class)
{
$path = __DIR__.'/'.str_replace("\\", DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($path))
{
require_once($path);
}
}
spl_autoload_register('app_autoload');
If I have a class defined in the namespace app\nstest, I can autoload it just fine from most of my system:
namespace app\nstest;
class Test1
{
function hello()
{
echo "Hello world";
}
}
However, another class in the same namespace has issues:
namespace app\nstest;
class Test2
{
function callMe()
{
$test1 = new Test1();
}
}
If I explicitly include/require the Test1 file at the top of Test2, no problems, but the autoloader doesn't seem to be aware of the namespace, so it's loading "Test1.php" instead of "app/nstest/Test1.php".
I also tried checking the __NAMESPACE__ inside the autoloader, but it's empty.
Why doesn't this work?
web/index.php (Not web/src/App/App.php)
<?php
namespace App;
// web/index.php
require_once __DIR__ . '/../vendor/autoload.php';
$app = new App();
class App extends \Silex\Application {
public function __construct()
{
parent::__construct();
echo 'Worked!';
}
}
I also tried namespace App {...}, no change. It throws this exception:
Fatal error: Uncaught Error: Class 'App\App' not found in /path/to/web/index2.php:8
Stack trace:
#0 {main}
thrown in /path/to/web/index2.php on line 8
As long as I remove the extends ... and the parent call part, it works. I also noticed interface does the same thing (trying to use Serializable). Is this an issue with the autoloader being confused? Is there a way to do this without putting the App\App class into a file in src\App\App.php?
Note: this is an exercise to build a single-file application with Silex, so "just put it in a file" isn't an answer. I want to know why this doesn't work, which has an answer.
The problem in your code is,
In namespace, You are initiating class object before it being declared and loaded. In your above code you are doing same thing,
1. You are initiating App class object which lies in App namespace
2. You are initiating class object at the moment class when is not yet declared(As it is defined below in your code).
In your above code, not even your loader be called. It will be called if you initiate App\App class object after its declaration. and If your loader does not work fine then afterwards you will possibly get this error.
Fatal Error: Silex\Application class not found
Please checkout some examples and findings.
Example 1 Here loader is expected to be called but not called, because you have registered after initialization of class($app = new App();).
Example 2 Here, calling class will look for autoloading class because here initialization takes place after registration of loader and declaration of class, which is probably answers your question.
Change your code with this to get it fix:
<?php
namespace App;
require_once __DIR__ . '/../vendor/autoload.php';
class App extends \Silex\Application {
public function __construct()
{
parent::__construct();
echo 'Worked!';
}
}
$app = new App();
I created a class at Controller folder of Cake project like this:
<?php
class Hi
{
function __construct(){ }
public function hi()
{
echo "hi!";
exit;
}
}
Then in a controller, I tried to include it:
<?php
namespace App\Controller;
use App\Controller\AppController;
include_once "Hi.php";
class MyController extends AppController
{
public function sayHi()
{
$a = new Hi();
$a.hi();
}
}
Here is the error I'm having:
Fatal error: Cannot declare class Hi, because the name is already in use in path\api\src\Controller\Hi.php on line 2
What's going on?
MyController.php and Hi.php are in the same folder. I'm using PHP 7.
Including a file won't make the classes in that file part of the current namespace, as namespaces are a per-file functionality.
http://php.net/...namespaces.importing.php#language.namespaces.importing.scope
Your Hi class will be declared in the global namespace, and your new Hi() will cause PHP to look for it in the current namespace, ie it will look for App\Controller\Hi, which doesn't exist, hence the composer autoloader kicks in, and will map this via a PSR-4 namespace prefix match to src/Controller/Hi.php, which will include the file again, and that's when it happens.
http://www.php-fig.org/psr/psr-4/
Long story short, while using new \Hi() would fix this, you better not include class files manually, or declare them in paths where they do not belong. Instead declare your files and classes in a proper autoloading compatible fashion, that is for example with a proper namespace in a path that matches that namespace, like
namespace App\Utils;
class Hi {
// ...
}
in
src/Utils/Hi.php
I have an exception in application/core named prefix_Exceptions.php with the same class name. I try to throw this exception from a controller and I get:
Fatal error: Class 'prefix_Exceptions' not found in user_controller.php
In application/core/prefix_Exceptions.php:
<?php
class prefix_Exceptions extends CI_Exceptions {
public function __construct() {
parent::__construct();
}
public function test() {
echo "This is a test.";
}
}
And in application/controllers/user_controller.php:
<?php
class User_Controller extends CI_Controller {
public function view($id = '0') {
$this->load->model('user_model');
$u = $this->user_model->getUser($id);
if (!isset($u)) {
$this->exceptions->test(); // ???
}
echo "Test: $u";
}
}
Oh, and my prefix is set to prefix_:
$config['subclass_prefix'] = 'prefix_';
I've read about a dozen threads on this issue and none of them fix my exception so that it can be thrown by the controller.
The main reason your code is not working, is (as the error message suggests): your prefix_invalid_user.php is never loaded. CI does not know to load this file, as you are not following the required file naming scheme.
If you want to extend a built-in class, you have to use the same class name, except you change the prefix from CI_ to MY_ (or whatever prefix you set in your config).
To extend the class CI_Exceptions you would have to name it MY_Exceptions and save that php file in /application/core/MY_Exceptions.php. Then, and only then, will CI auto-load it for you.
However you should also know that CI's exceptions class isn't actually for throwing exceptions (the name is misleading, but CI_Exceptions handles error reporting). As you can see in the /system/core/Exceptions.php file, the CI_Exceptions class does not extend PHP's native Exceptions class, which is necessary to create custom, throwable exceptions.
If you want custom, throwable exceptions you have to create your own wrapper for them, and load/autoload it as a library.
Edit:
As per the OP's request, I'm adding the other half of the solution, which was to simply fetch the class object from CI's innards. For this, we can use the load_class function, which will return our class object if it has been instantiated, and if not, it will instantiate and return it.
$foo = load_class('Exceptions', 'core', $this->config->item('subclass_prefix'))
Then we can access the methods of our custom Exceptions class as so:
$foo->someMethodName();