I am using Slim PHP as the underlaying framework for my app and composer autoload for the loading of my classes. In composer i have this psr-4 configuration:
"psr-4": {
"App\\": "app/classes/"
}
All my classes are in /app/classes/ folder.
In my classes folder i have all common classes but module specific classes i have in sub folders.
From my ../classes/connect.php file i am having this method under the corresponding namespace:
namespace App;
class connect
{
public function authenticate(){
office\AuthenticationManager::acquireAppToken(200);
}
}
In my subfolder ../classes/office/ i have a file called office.php with this method:
namespace App\office;
class AuthenticationManager
{
public function acquireAppToken($tid)
{
\App\APIManager\RequestManager::sendPostRequest();
}
}
The above method is calling another method which is located in ../classes/api.php
The namespace in that file is
namespace App\APIManager;
The problem is that when calling on this last method i get the following error:
"\App\APIManager\RequestManager" not found...
I already tried to solve this with composer dump-autoload, but it did not help. Why is this error happening?
If you want to have a class named RequestManager in App\APIManager namespace, then it must be located in APIManager/RequestManager.php file.
It also applies to the AuthenticationManager class, which should be moved to office/AuthenticationManager.php
Have a look at PSR-4 examples.
Related
I'm following a tutorial on how to create laravel packages.
I'm using Laravel v8.42.1 (PHP v7.4.3) and jetstream package.
I'm stuck on creating a controller for my package, I always get following error when trying to connect to my url via the laraval app (<base-url/playground):
Target class [TestVendor\TestPackage\Http\Controllers\PlaygroundController] does not exist.
The TestVendor\TestPackage\src\routes.php is recognized by the main application:
use TestVendor\TestPackage\Http\Controllers\PlaygroundController;
use Illuminate\Support\Facades\Route;
Route::get('/playground', [PlaygroundController::class, 'index']);
And is loaded from my ServiceProvider class:
$this->loadViewsFrom(__DIR__.'/resources/views', 'playground');
loadRoutesFrom(__DIR__.'/routes.php');
My namespacing is also normally correctly written in the composer.json of my package:
"autoload": {
"psr-4": {
"TestVendor\\TestPackage\\": "src/"
}
},
And I have my PlaygroundController in src/Http/Controllers/PlaygroundController.php:
namespace TestVendor\TestPackage\Http\Controllers;
use Illuminate\Routing\Controller;
class PlaygroundController extends Controller
{
public function index()
{
return view('playground::hello');
}
}
The view is also in the right package.
I'm using https://github.com/Jeroen-G/laravel-packager to scaffold my packages.
Did multiple composer auto-load and composer updates.
It seems my controller is not recognized in the main application, I think somewhere my name spacing is not correct?
I already had a look at:
Target class controller does not exist - Laravel 8
Solution did not work
Target class does not exist. problem in laravel 8
Solution did not work
You have namespaced your controller as:
namespace TestVendor\TestPackage\Http\Controllers;
In the line above though you say:
And I have my PlaygroundController in src/Http/PlaygroundController.php:
Unless that is a typo, you need to add a Controllers directory underneath Http and put your PlaygroundController in there:
src/Http/Controllers/PlaygroundController.php
For psr-4 autoloading, your folder structure and namespaces should mimic each other.
I'm running into trouble with namespace in PHP. For an example I have a file like this
namespace App\Models\Abstracts;
abstract class Country{}
and then another file like this
namespace App\Models;
use App\Models\Abstracts\Country;
class City extends Country{}
I always get the
Fatal error: Uncaught Error: Class ... not found in ...
Can anyone help me?
thanks a lot.
To do that, I advise you to use the PSR (psr-4).
First, let's create a files structure as bellow :
Now let's init the composer to configure the psr-4.
jump to the root of the project (in this example the root directory of src), and run :
you will be asked to fill some project information, just skip it
composer init
A file named composer.json will be created in the root directory, let's configure the psr-4 inside.
{
"name": "root/project",
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Learn more about psr-4
to hover, we are just telling the PSR to point the name App to the directory src and then the name of subfolder should be the surname in your namespace.
Example:
App => src directory
App\Models => src/Models directory
And so on
Next, you should generate the autoload by
composer dump-autoload
The final project file structure seems to be something like :
I create a file called index.php in the root directory to test my code, but first, you should require the autoload which has been generated by the configuration we just did.
<?php
use App\Models\City;
require __DIR__.'/vendor/autoload.php';
$city = new City();
var_dump($city);
Result:
/var/www/myfm/index.php:9:
class App\Models\City#3 (0) {
}
I hope this helps you.
In my default symfony4 structure I want to add lib folder, where I have additional classes. So something like this:
-bin
-config
-lib
- Importer.php
...(other files with classes)
-public
-src
- Controller
- TestController.php
- Entity
- Form
...
...
But I cannot figure out how to later use my files (i.e.: Importer.php).
Let's say Importer.php has a single class Importer() inside. If I try to use it from TestController.php I get:
Attempted to load class "Importer" from namespace "lib". Did you
forget a "use" statement for another namespace?
TestController.php has
use Importer;
specified on top (autodetected by PhpStorm). I also tried adding namespace in my Importer.php file, for example:
namespace lib;
and then in TestController:
use lib\Importer;
But it produces the same result.
Lastly after reading about services, I tried adding the file to config/services.yaml
lib\:
resource: '../lib/Importer.php'
Which gives the same result...
What to do, how to live?
First of all read about php namespaces.
Next read about the psr-4 standart.
Select a prefix for your folder, let's say Lib. Make sure that all files in the lib folder has a properly namespace. E.g. Importer class must be stored in the lib\Importer.php and must have the namespace Lib;, Items\Item class must be stored in the lib\Items\Item.php and must have the namespace Lib\Items\Item; and so on.
Your files are ready. Just need to inform Symfony about them.
Symfony uses composer's autoloader, so check composer's autoload section. Than add new folder for autoloading in composer.json:
"autoload": {
"psr-4": {
"App\\": "src/",
"Lib\\": "lib/"
}
},
It says that all classes in lib folder have their own separate files and Lib prefix in their namespace and other part of namespace is similar to directories structure.
Next you need to clear autoloader's cache. Run in console:
composer dump-autoload
And finally you can use your class:
use Lib\Importer;
$importer = new Importer;
Also you can add your files to autowire.
In my project I have a folder lib\custom which contains Web folder and functions.php file. In my functions.php I have some functions which I need to use in another classes and in this file on the first line I have a defined namespace look like this
<?php
namespace Custom;
function abc(){....}
And in Web folder I have some classes with namespace Custom\Web;
In my composer.json file I have defined namespace look like this
"Custom\\":"lib/custom/"
So , now I am using the abc() look like this
use Custom;
$abc = Custom\abc("abc")
but as a response I am getting
Call to undefined function Custom\abc()
How can I solve this problem?
PSR-4 describes a specification for autoloading classes from file paths. It doesn't cover loading functions from files.
Use the files autoloader to load a file with functions on each request automatically. This will make your function available as long as you included the autoloader:
{
"autoload": {
"files": ["lib/custom/functions.php"]
}
}
Since your functions are namespaced you'll need to import them with the use statement or use the fully qualified name.
If your Web folder contains PSR-4 compatible classes, load them as before with the PSR-4 autoloader (you can define multiple autoloaders in your composer.json).
I made a class in php with some helper methods that parse HTML files.
I'd like to use this class in my Laravel project, but I'm new to Laravel and it's not clear how to add a simple class to a Laravel 5 project.
Is this possible? Or do I need to go to all the trouble of creating a composer package for my class, hosting it somewhere, and then require it in my composer.json file. That seems like a lot of work for including a simple PHP class, and I'm hoping there's an easier way.
As it stands right now there's not a great/easy way to do this in Laravel 5 (possibly by design). The two approaches you can take are
Create a new class in the App namespace
By default Laravel 5.0 looks for App\ prefixed classes in the app/ folder, so something like this should work
#File: app/Helpers/Myclass.php
<?php
namespace App\Helpers;
class Myclass
{
}
and then create your class with
$object = new App\Helpers\Myclass;
This approach, however, relies on you creating classes in the App\ namespace, and there's some ambiguity around if the App\ namespace is owned by Laravel, or is owned by the developer of the application.
Create your own Namespace and Register as PSR-4 autoloader
A better, but more complicated, approach would be to create classes in your own namespace, and then tell Laravel about this namespace by registering a new PSR autoloader.
First, you'd create the class definition
#File: application-lib/Myclass.php
<?php
namespace Pulsestorm;
class Myclass
{
}
Notice we've created a new folder off the root folder to hold our classes named application-lib. You could name this folder anything you like, because in the next step, you're going to add a section to your composer.json file's autoloader section
#File: composer.json
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/",
"Pulsestorm\\": "application-lib/"
}
},
The section we've added is this
"Pulsestorm\\": "application-lib/"
The key to the object (Pulsestorm\) is your namespace. The value (application-lib) is the folder where composer should look for class definition files with the specified namespace.
Once you've added this to composer.json, you'll need to tell Composer to regenerate it's autoload cache files with the dumpautoload command
$ composer dumpautoload
Generating autoload files
After doing the above, you should be able to instantiate your class with
$object = new Pulsestorm\Myclass;
The "real" right way to do this would be to create a generic composer package for your helper class, and then require that composer package into your laravel project. That may, however, be more work than you care to take on for a simple library helper.
If your class is generic enough to use it in other projects, the best way is to release it as a package.
Here's how you create packages with Laravel 5: http://laravel.com/docs/5.0/packages