a quick (maybe stupid) question.
I'm using a namespace for my controllers, like so:
namespace Members;
use DB;
use Input;
use PerformanceReport;
use Redirect;
class AdminController extends MembersController {
And as expected, I have to provide use statements for the Laravel classes I wish to use.
From what I've understood, the composer autoloader prevents this from being necessary if used correctly.
So my question being, is it possible to configure the autoloader to suit my needs, and if so, how would I go by doing this?
Your question is connected with the way PHP namespaces work, not with composer's autoloader.
If your class is in namespace Controllers; and you'd write Redirect::to('/') php would assume that the class you're referring to is in the current declared namespace (in that case Controllers/Redirect). You can either write \Redirect::to('/') or put a use Redirect statement on top like you did.
Composer's autoload just maps namespaces to their file directory (see vendor/composer/autoload_classmap.php for how it maps it).
If you want to dive more into composer's autoloading, i'd recommend read up on PSR-0 and PSR-4.
Related
I can't make interfaces work in my php/laravel project. I have a series of Controllers, which I want to implement an interface. And PhpStorm seems happy with my syntax. But I get a runtime error that the interface is not found, when I make a check if the current object indeed has the interface:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use iTeamEntryController;
class TeamController extends Controller implements iTeamEntryController {...}
and then the Interface:
<?php
use Illuminate\Http\Request;
interface iTeamEntryController
{
public function saveTeam(Request $request);
}
Here I get an error on the line defining the class, saying that interface 'iTeamEntryController' is not found. Both the class and the interface exists in the same folder.
I've been trying to find an example online, but everyone either has both the interface and the class declaration in the same file, or uses 'include_once' or 'require_once', which to me seems to be referring to files, and not OOP. So what am I doing wrong here? Why can't my interface be found?
Remember that the use clause wants you to specify an absolute class/interface/trait name, not relative to your current namespace.
The below is wrong, unless your controller is in a global namespace (which I'm sure isn't the case):
use iTeamEntryController; // wrong
And this - below - is correct:
use App\Http\Controllers\iTeamEntryController;
If you keep your interface in app/Http/Controllers directory, don't forget to specify a namespace:
namespace App\Http\Controllers;
If you want, on the other hand, your interface to be in a root directory, make sure it is there. Then, the namespace is not needed and your use clause is correct. Except, I'm pretty sure you don't want your interfaces in the root directory of your Laravel app.
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 new to Laravel 5 and I would like someone to explain to me how exactly Laravel's namespacing works.
So I had a class named Variant in app/models/Variant.php my code looks like this
namespace App;
use Illuminate\Database\Eloquent\Model;
class Variant extends Model{
/*Some code*/
}
in my route.php I have:
use App\Variant;
/*calls Variant::all() some where in code*/
Then I get an error saying Variant is not defined. However, if I change my namespace in Variant.php from namespace App to namespace App\Models and in route.php from use App\Variant to use App\Models\Variant everything magically works.
Why is that? Does it have to do with php namespace or the classmap property in composer.json? I am very confused.
Your classes are probably loaded by composer. What's the content of it - autoloading section in particular?
I guess it's loaded by PSR-4 standard, which respects director-name\file-name pattern.
Meaning:
App\Variant is sought in app/Variant.php
App\Models\Variant is sought in app/models/Variant.php
Therefore, when you change your namespace to the one corresponding with your directory path, it works.
What I want to do is to use different namespaces in a controller. I have a tree scheme like this:
app/
app/controllers/
app/modules/
app/modules/modulename/
app/modules/modulename/controllers/
app/modules/modulename/controllers/modulecontroller.php
app/modules/modulename/models/
app/modules/modulename/models/modulemodel.php
What I want to do is to call a model from a controller in app/controllers/ folder. Therefore I am supposed to add namespace as follows:
use App\Modules\Facebook\Controllers\Facebook;
The problem is that when I add a namespace and use App::() function at the sametime, I get the following error:
Class 'App\Modules\Modulename\Controllers\App' not found
I think it is looking the App::() function in module folder. How can I solve this problem?
if you use App inside your App\Modules\Facebook\Controllers namespace, it will be interpreted as App\Modules\Facebook\Controllers\Facebook\App class.
since you don't want to have the previous namespace, you use a \ before App like:
\App::()
or put a use statement of top the class like use App;
You probably are creating an unusual namspace scheme. It appears you are namespacing every class from your module differently. You should namespace your code within your module only, like so:
// Adding Onur to the namespace prevents any future namespace collisions.
<?php namespace Onur\Facebook;
After creating your namespace you should add all classes that are outside of your namespace that you want to use as followed.
use Eloquent, Input, Validate, Etc;
This prevents you from adding a \ in front of every class instance, making your code hard maintain and prone to errors. It also gives you a good overview on all the classes you are using in the current class.
if you say
use App\Modules\Facebook\Controllers\Facebook;
then you are supposed to use Facebook instead of App... Or donĀ“t I understand your problem correctly?
if you say
use App\Modules\Facebook\Controllers\Facebook as FacebookController;
the you can use FacebookController in your file
if you need Access to the root App, you need to to root it using a leading \
\App::make()
How would I go about autoloading a class after having used the use keyword?
e.g.
use Code\Store\Core\Store;
$_STORE = Factory::Get( "Store" );
My autoloader goes looking for Store.php when I want it to go looking for /Code/Store/Core/Store.php
Is there a way to expand a namespace after having used use? Or autoload it during the use definition? Or is my only option to use the full namespace when getting a class from the factory?