I cannot autoload my class using psr-4 - php

I am learning auto loading my calss using psr-4 but I have no luck,here is my folder structure
Here is the code inside my "Employee.php"
namespace app\Employee;
class Employee
{
public function __construct(){
echo "hello employee";
}
}
and in my index.php
use app\Employee;
$emp = new Employee;
Here is my composer.json
{
"autoload": {
"psr-4": {
"Employee\\":"app/Employee"
}
}
}

Your current autoloader, expects that the "Employee" namespace is mapped within the "app/Employee/" directory.
With your setup, you would need to add in index.php
use Employee\Employee;
$emp = new Employee();
And the actual namespace of Employee.php would be:
namespace Employee;
class Employee {}

Change
use app\Employee;
$emp = new Employee;
to:
use Employee\Employee;
$emp = new Employee();

From your code in Employee.php:
namespace app\Employee;
This is the namespace you have to use if you want to access the class.
PSR-4 in Composer works like this:
"autoload":{"psr-4": { "Namespace\Prefix":"a/path"}}
When loading a class "Namespace\Prefix\Class", Composer will see the PSR-4 entry and compare if the class being loaded starts with that Prefix. It does! Now it remove the detected prefix from the classname, and treats the rest as a path and file name relative to "a/path".
So the remainder of that class is "Class", and because there is no backslash left, this directly is the filename "Class.php" (note the uppercase filename). This file is searched in "a/path/Class.php".
For your situation, you almost did everything right - the only thing: Your namespace prefix in composer.json is not Employee\ - you gave the correct prefix in your code above.

Related

Symfony2.7, adding 3rd party lib to project

I'm stuck, i wanted to load external library to my symfony2 project but got error stating that class was not found my app/autoloader.php:
...
$loader->add('Tinify', __DIR__.'/../vendor/tinify/tinify/lib');
...
and my file where i want to use it looks like it:
<?php
namespace XYZ\NewsBundle\Controller;
...
use Tinify;
class NewsController extends Controller{
...
public function displayAction($slug)
{
$em = $this->getDoctrine()->getManager();
$external = new \Tinify();
}
error is as follow The autoloader expected class "Tinify" to be defined in file "xyz/app/../vendor/tinify/tinify/lib\Tinify.php". The file was found but the class was not in it, the class name or namespace probably has a typo.
but file under vendor\tinify\tinify\lib\Tinify.php
namespace Tinify;
const VERSION = "1.3.0";
class Tinify {
...
}
i checked if it really has typo but don't see one
Full qualified class name of Tinify is not Tinify but \Tinify\Tinify. Its namespace + classname.
In you NewsController class you should do:
use \Tinify\Tinify;
Also note the backslash at the beginning of the namespace.
Then in the code you should use just class name and not namespace so also change this:
$external = new \Tinify();
to this:
$external = new Tinify();
Why don't install Tinyfy throught Composer?
composer require tinify/tinify
In this way composer handles de autoload of the library, you don't need to load manually nothing, you only must to make an instance of the class and run
$tinify = new Tinify();

PHP class not found when using namespace

I am new with this namespace thing.
I have 2 classes(separate files) in my base directory, say class1.php and class2.php inside a directory src/.
class1.php
namespace \src\utility\Timer;
class Timer{
public static function somefunction(){
}
}
class2.php
namespace \src\utility\Verification;
use Timer;
class Verification{
Timer::somefunction();
}
When I execute class2.php, i get the Fatal error that
PHP Fatal error: Class 'Timer' not found in path/to/class2.php at
line ***
I read somewhere on SO, that I need to create Autoloaders for this. If so, how do I approach into creating one, and if not, then what else is the issue?
UPDATE
I created an Autoloader which will require all the required files on top of my php script.
So, now the class2.php would end up like this.
namespace \src\utility\Verification;
require '/path/to/class1.php'
use Timer;
//or use src\utility\Timer ... both doesn't work.
class Verification{
Timer::somefunction();
}
This also does not work, and it shows that class not found. But, if I remove all the namespaces, and use's. Everything works fine.
We can solve the namespace problem in two ways
1) We can just use namespace and require
2) We can use Composer and work with the autoloading!
The First Way (Namespace and require) way
Class1.php (Timer Class)
namespace Utility;
class Timer
{
public static function {}
}
Class2.php (Verification Class)
namespace Utility;
require "Class1.php";
//Some interesting points to note down!
//We are not using the keyword "use"
//We need to use the same namespace which is "Utility"
//Therefore, both Class1.php and Class2.php has "namespace Utility"
//Require is usually the file path!
//We do not mention the class name in the require " ";
//What if the Class1.php file is in another folder?
//Ex:"src/utility/Stopwatch/Class1.php"
//Then the require will be "Stopwatch/Class1.php"
//Your namespace would be still "namespace Utility;" for Class1.php
class Verification
{
Timer::somefunction();
}
The Second Way (Using Composer and the autoloading way)
Make composer.json file. According to your example "src/Utility"
We need to create a composer.json file before the src folder. Example: In a folder called myApp you will have composer.json file and a src folder.
{
"autoload": {
"psr-4": {
"Utility\\":"src/utility/"
}
}
}
Now go to that folder open your terminal in the folder location where there is composer.json file. Now type in the terminal!
composer dump-autoload
This will create a vendor folder. Therefore if you have a folder named "MyApp"
you will see vendor folder, src folder and a composer.json file
Timer.php(Timer Class)
namespace Utility;
class Timer
{
public static function somefunction(){}
}
Verification.php (Verification Class)
namespace Utility;
require "../../vendor/autoload.php";
use Utility\Timer;
class Verification
{
Timer::somefunction();
}
This method is more powerful when you have a complex folder structure!!
You are going to need to implement an autoloader, as you have already read about it in SO.
You could check the autoloading standard PSR-4 at http://www.php-fig.org/psr/psr-4/ and you can see a sample implementation of PSR-4 autoloading and an example class implementation to handle multiple namespaces here https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md.

Class auto loader Yii2

I created a new directory at root 'components'. Then I put a file 'ClassName.php' into this folder. Declare a namespace namespace components; and the class named ClassName Now I try to use it like
$c = new app\components\ClassName()
But there's an error. It says that Class 'components\ClassName' not found.
Where am I missing? I suppose that I should add folder components in include_path or something like that. Please help to understand.
I found the solution.
Just add
Yii::setAlias('components', dirname(dirname(\__DIR__)) . '/components');
In className.php:
namespace components;
Then usage:
$c = new components\ClassName();
This is how you can create custom components in Yii2 (basic application)
Create a folder named "components" in the root of your application.
Then create a class for your component with proper namespace and extend Component class:
namespace app\components;
use yii\base\Component;
class MyComponent extends Component {
public function testMethod() {
return 'test...';
}
}
Add component inside the config/web.php file:
'components' => [
// ...
'mycomponent' => [
'class' => 'app\components\MyComponent'
]
]
Now you can access your component like this:
Yii::$app->mycomponent->testMethod();
In ClassName.php:
namespace app\components;
Added
When you create new ClassName instance, don't forget the leading backward slash for namespace (AKA fully qualified namespace), if your current namespace is not global, because in that case namespace will be treated as relative (Like UNIX paths), use:
$c = new \app\components\ClassName(); //If your current namespace is app\controllers or app\models etc.
$c = new app\components\ClassName(); //If your current namespace is global namespace
You can read more about namespaces basics in PHP documentation
It should be late but I guest my solution may help some one later. I had the same issue and the resolved it the way bellow:
If you want to autoload (import) a customer class in your app, you to do:
create your class where ever you want e.g in my case, i created common/core/Utilities.php
then you have to create an alias (alias is a short cut name you give to your folder path). In my case in create an alias for my folder core (note i should also create an alias for my component folder) e.g
Yii::setAlias('core', dirname(DIR).'/core');
this snippet i put it in my common/config/boostrap.php file. because yii2 load this file at running time.
Now you are ready to use your customize class where ever you want. Just do
$utilities = new \core\Utilities();
Hopefully this may !!!!!!!

Using namespaces in Laravel 4

I'm new to Laravel and using PHP namespaces in general. I didn't run into any problems until I decided to make a model named File. How would I go about namespacing correctly so I can use my File model class?
The files are app/controllers/FilesController.php and app/models/File.php. I am trying to make a new File in FilesController.php.
Namespacing is pretty easy once you get that hang of it.
Take the following example:
app/models/File.php
namespace App\Models;
class File {
public function someMethodThatGetsFiles()
{
}
}
app/controllers/FileController.php
namespace App\Controllers;
use App\Models\File;
class FileController {
public function someMethod()
{
$file = new File();
}
}
Declare the Namespace:
namespace App\Controllers;
Remember, once you've put a class in a Namespace to access any of PHP's built in classes you need to call them from the Root Namespace. e.g: $stdClass = new stdClass(); will become $stdClass = new \stdClass(); (see the \)
"Import" other Namespaces:
use App\Models\File;
This Allows you to then use the File class without the Namespace prefix.
Alternatively you can just call:
$file = new App\Models\File();
But it's best practice to put it at the top in a use statement as you can then see all the file's dependencies without having to scan the code.
Once that's done you need to them run composer dump-autoload to update Composer's autoload function to take into account your newly added Classes.
Remember, if you want to access the FileController via a URL then you'll need to define a route and specify the full namespace like so:
Route::get('file', 'App\\Controllers\\FileController#someMethod');
Which will direct all GET /file requests to the controller's someMethod()
Take a look at the PHP documentation on Namespaces and Nettut's is always a good resource with this article
first, load your class with:
$ composer dump-autoload
then
$file = new File;
// your stuff like:
$file->name = 'thename';
$file->active = true;
$file->save();
Section: Insert, Update, Delete on Laravel 4 Eloquent's doc
To namespace your model, at the top of your model class right after the opening
Then when you call from controllers you will call new Whatever\Model;
You probably have to do a dump-autoload with composer the first time around.
have a look to it.. hopefully will clear your query....
<?php
namespace app\controllers;
use yii\web\Controller;
use app\models\users;
class UserController extends Controller{
public function actionIndex()
{
echo "working on .....";
}
}
Namespaces are defined at the top of PHP classes right after the opening php script tag like this:
<?php
namespace MyNameSpace;
When you then want to use the namespaced class in some other class, you define it like this:
new MyNameSpace\PhpClass;
or import it at the top of the file (after namespaces if present) like this:
<?php
//namespace
use MyNameSpace\MyPHPClass;
//then later on the code you can instantiate the class normally
$myphpclass = new MyPHPClass();
In Laravel namespaces can be defined anywhere composer can autoload them, I'd recommend defining namespaces within the app directory. So you can define a namespace like Utils for holding Utility classes by creating a Utils directory in the app directory, creating our utility classes and defining the namespace as we did above.
Afterwards you have run the command to ask composer to autoload classes:
$ composer dump-autoload

PHP Root namespace

I have got a single file in which I need specify classes in multiple namespaces, something like:
<?php
namespace library;
class ClassInLib {
...
}
namespace \; //Switch to root namespace
class ClassInRoot {
...
}
The above code has a syntax error at namespace \;. How can I switch from the library namespace to the root namespace?
Why do I need this: I need to mock a bunch of classes during unit testing and I don't think these very short mock classes justify being in separate files.
namespace
{
class RootClass
{
function whatever();
}
}
namespace Symfony\Component\DependencyInjection
{
interface ContainerAwareInterface
{
function setContainer(ContainerInterface $container = null);
}
}
http://www.php.net/manual/en/language.namespaces.definitionmultiple.php
Good chance you will decide to use separate files anyways.
I struggled with this for a while - I put the class files I wanted to be global namespaced ( e.g. I want to use them as \myClass ) into their own folder and I removed any namespace ... ; declared in the files.
Then in composer.json add in classmap to the directory I'd made:
"autoload": {
"classmap": [
"directoryWith/subDirIfNeeded"
]
...
}
Then don't forget to composer dumpautoload whenever you make a change to composer.json

Categories