I have the following folder setup
/common
/classes
-sharedClass.php
/project
/classes
-coreClass.php
index.php
bootstrap.php
In my bootstrap.php I'm setting up a namespace
$autoloader = new ClassLoader('CommonFiles', dirname(__DIR__) . '/common/classes/');
$autoloader->register();
In index.php:
require_once 'classes/coreClass.php'
$core = new CoreClass();
in coreClass():
use CommonFiles\SharedClass;
//Other code
I'm getting an error that sharedClass.php can't be found, and the actual namespace is being appended to the file path being checked so that it's:
c:/web/common/classes/CommonFiles/sharedClass.php
So... how do I stop the autoloader from including the namespace as part of the path root it's looking for?
So after some closer review apparently this is just how autoloading works. I reviewed some of the baked in Doctrine samples and it looks like the namespace is appended automatically to all your use statements. This wasn't just a fluke but a design decision and accounting for it meant an easy fix.
Related
I am currently doing something like this:
$loader->addPsr4('Application\\Config\\', __DIR__ . '/../config/test');
This means I can do any file in the directory test with namespace Application\Config\.
Is it possible to a similar setup/trick to do this for the global namespace?
You can do:
$loader->addClassMap(['src\\']);
and this will get you all the files in directory src (no matter what namespace there will be).
I am trying to use Azure storage for php, the setup steps are to include the namespace, include composer autoload and then use the azure classes, so I have the following. However further down I use the class Microgrid and it's not found because of the namespace, it is in a different directory. How can I use other classes that aren't part of that namespace? Also, what's the correct way to specify your namespace path? It's in a different directory relative to the page this is for and the one I am using is not at the root, should I start at the root?
namespace MicrosoftAzure\Storage;
use \MicrosoftAzure\Storage\Common\ServicesBuilder;
use \MicrosoftAzure\Storage\Blob\Models\CreateContainerOptions;
use \MicrosoftAzure\Storage\Blob\Models\PublicAccessType;
use \MicrosoftAzure\Storage\Common\ServiceException;
require_once '/var/www/html/vendor/autoload.php';
$action = MicroGrid::GetParameter('action');
ClassNames are considered relative to the current namespace unless they start with a \
This means that inside the MicrosoftAzure\Storage namespace you can use the relative namespace for class.
If you want to call a class from a different namespace you should call fully-qualified name for it like
$action = \MicrosoftAzure\WhereEver\MicroGrid::GetParameter('action');
or use the name space or unique class with fully-qualified name
use \MicrosoftAzure\WhereEver;
or
use \MicrosoftAzure\WhereEver\MicroGrid;
then:
$action = MicroGrid::GetParameter('action');
Edited to make it clear
namespaces allow us to avoid naming collisions and to alias long
names caused by avoiding naming collisions.
it depends to your autoloader for a simple example I create a new project and make this autoloader in the index.php located at root directory
function __autoload($className){
//if it's a full name with windows style slashes correct the path
$file_name = str_replace('\\', '/', $className);
require_once("vender/src/".$file_name.".php");
}
when I call $date = new \App\Utility\Date(); autoloader will require this file:
verdor/src/App/Utility/Date.php
and in Date.php I used this name space namespace App\Utility;
PHP does not provides a class autoloader out of the box.
There are many autoloaders for PHP, and the most common autoloader standard is the PSR-4, used by many frameworks and applications.
If you are not using an autoloader, you should require every class file (and recursive dependencies) before using it.
Azure uses Composer Autoloader and PSR-4.
You should use Composer Autoloader on your project, then import your class from the right namespace (you are not importing it on your example code)
A namespace basically groups your classes together. You can use something outside your namespace by explicitly using it e.g.
namespace App;
use Illuminate\Database\Eloquent\Model;
In this case I'm 'grouping' this and other classes in a namespace called 'App' but I want to use 'Model' provided by Eloquent (the Eloquent class having a namespace of 'Illuminate\Database\Eloquent') in this class.
If 'Microgrid' is not part of your current namespace, you'll need to explicitly add its namespace in your 'use' statements.
I am trying to access CustomersController class from index.php page that is inside webroot folder in cakephp 3.When I use below code, it says it cannot find the class.
require dirname(__DIR__) . '/src/Controller/CustomersController.php';
$customers = new CustomersController;
Am I doing something wrong?
Here is the error I get from cakephp index.php page: "Error: Class 'CustomersController' not found "
You have to understand that CakePHP 3 uses PSR4 autoloading (check also composer) and also namespaces. If you go and remove the namespace from from the controller you will see that it works. But this will probably break other stuff.
The title speaks itself. So here is my project structure:
|src
|Database
|Core
|MySQL.php
|Support
start.php
|vendor
composer.json
index.php
MySQL.php file:
<?php
namespace Database\Core;
//Some methods here
index.php and start.php files:
//start.php file
<?php
require __DIR__ . '/../vendor/autoload.php';
?>
//index.php file
<?php
use Database\Core;
require __DIR__ . '/src/start.php';
$mysql = new MySQL(); // Gets exception Class 'MySQL' cannot found etc.
?>
And finally my composer.json autoload part:
"autoload": {
"psr-4": "Database\\": "src/" // Also tried "src/Database" too
}
Where is the problem? I'm really tired of trying to cope with this situation. Please help guys! Thanks.
You need to include namespace when you are initializing a class:
$mysql = new Database\Core\MySQL();
or
use Database\Core\MySQL;
$mysql = new MySQL();
See Using namespaces: Aliasing/Importing
Aside from not using the right use statement as already mentioned, PSR-4 does not work like that. It is more of an alias. You are essentially saying that src equals Database. So to have a directory named Database in there would imply that the fully qualified namespace + class equals 'Database\Database\Core\MySQL`. You want to use PSR-0 in this case, or adjust your PSR-4 definition.
I am trying to use namespaces in fatfree framework, but somehow its not able to find the class following is my setup
routes.ini
[routes]
GET /=Src\Controllers\Index->index
index.php
namespace Src\Controllers;
class Index {
function index($f3) {
$f3->set('name','world');
echo View::instance()->render('template.htm');
}
}
Global index.php
// Retrieve instance of the framework
$f3=require('lib/base.php');
// Initialize CMS
$f3->config('config/config.ini');
// Define routes
$f3->config('config/routes.ini');
// Execute application
$f3->run();
UPDATE:
Error:
Not Found
HTTP 404 (GET /)
• index.php:13 Base->run()
UPDATE 2:
config.ini
[globals]
; Where the framework autoloader will look for app files
AUTOLOAD=src/controllers/
; Remove next line (if you ever plan to put this app in production)
DEBUG=3
; Where errors are logged
LOGS=tmp/
; Our custom error handler, so we also get a pretty page for our users
;ONERROR=""
; Where the framework will look for templates and related HTML-support files
UI=views/
; Where uploads will be saved
UPLOADS=assets/
I'm not sure what's going wrong.
Thanks In advance.
The autoloader of the Fat-Free Framework is very basic. It expects you to define one or more autoloading folders, each of them will map to the root namespace.
So let's say you define $f3->set('AUTOLOAD','app/;inc/') and your file structure is:
- app
- inc
- lib
|- base.php
- index.php
Then a class named MyClass belonging to the Foo\Bar namespace (full path: Foo\Bar\MyClass) should be stored in either app/foo/bar/myclass.php or inc/foo/bar/myclass.php (remember: we specified two autoloading folders).
NB: don't forget to specify namespace Foo\Bar at the beginning of myclass.php (the autoloader won't do it for you).
--
So to answer your specific problem, having the following file structure:
- lib
|- base.php
- src
|- controllers
|- index.php
- index.php
three configurations are possible:
Config 1
$f3->set('AUTOLOAD','src/controllers/')
Then all the files under src/controllers/ will be autoloaded, but remember : src/controllers/ maps to the root namespace, so that means the Index class should belong to the root namespace (full path: \Index).
Config 2
$f3->set('AUTOLOAD','src/')
Then all the files under src/ will be autoloaded, which means the Index class should belong to the Controllers namespace (full path: \Controllers\Index).
Config 3
$f3->set('AUTOLOAD','./')
Then all the files under ./ will be autoloaded, which means the Index class should belong to the Src\Controllers namespace (full path: \Src\Controllers\Index).
Fat-Free is always the root namespace "\". (the following might be wrong) Since F3 loads your classes through the autoloader, you always have to add the root namespace to your own namespaces. In this case you have to change it to
namespace \Src\Controllers;
And of course you have to change it in your routes.ini too.
GET /=\Src\Controllers\Index->index
To help you finding those issues in the future you can higher the DEBUG value with
$f3->set('DEBUG', 2); // 0-3; 0=off, 3=way too much information
Try this config - Your class:
namespace Creo\Controllers;
Framework routes
GET|POST / = \Creo\Controllers\IndexController->indexAction
folder location
_your_app_dir/app/Creo/Controllers
Your bootstrap file (in this case in _your_app_dir/app/)
spl_autoload_register(function ($className) {
$filename = __DIR__ . '/' . str_replace('\\', '/', $className) . ".php";
if (file_exists($filename)) {
include($filename);
if (class_exists($className)) {
return true;
}
}
return false;
});
Hope this will help.