I have autoload setup via PSR-4 which works perfectly fine. However I want to be able to add a specific class on top of that, that I can access from anywhere in the application.
This is what I have currently:
"autoload": {
"psr-4": {
"App\\": "app"
}
}
However I want to add a class called 'Redis' which is located in app/Lib/Redis.php so that from any Controller I can call Redis::method(); without having to add 'use App\Lib\Redis;' to the top of each file.
Is this possible?
This can't be done directly.
You could create a global function redis() and register than with composer:
"autoload": {
"psr-4": {
"App\\": "app"
},
"files"" {
"app/functions.php",
}
}
If this redis() function returned an instance of your Redis class, then I think that you could then do:
redis()->method();
Whether you should do this or not is another matter - unit testing becomes highly problematic. Personally, I would have a use statement and inject an instance of the Redis object into the constructors of the classes that need it.
Related
I try to create a Custom Plugin for CakePHP 4. But everytime i become a error that the plugin cant find the classes of the plugin.
I load the plugin in the Application.php
use Wirecore\CakePHP_JWT\Plugin as CakePHPJwt;
$plugin = new CakePHPJwt();
$this->addPlugin($plugin);
In the composer.json file of cake its also loaded:
"autoload": {
"psr-4": {
"App\\": "src/",
"Wirecore\\CakePHP_JWT\\": "./plugins/CakePHP-JWT-Plugin/src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Test\\": "tests/",
"Cake\\Test\\": "vendor/cakephp/cakephp/tests/",
"Wirecore\\CakePHP_JWT\\Test\\": "./plugins/CakePHP-JWT-Plugin/tests/"
}
}
and i create a file in /plugins/CakePHP-JWT-Plugin/src/Middleware/JwtMiddleware.php with example code of the documentation Middleware. I changed the namespace of the example code to
namespace Wirecore\CakePHP_JWT\Middleware;
after this i try to load the middle in the middleware function of the plugin but everytime i become this error:
Class 'Wirecore\CakePHP_JWT\Middleware\TrackingCookieMiddleware' not found
here the code of the middleware function:
use Wirecore\CakePHP_JWT\Middleware\TrackingCookieMiddleware;
$middlewareQueue->add(new TrackingCookieMiddleware());
return $middlewareQueue;
i have tried to change the namespace but it does not work, and i try it with composer dumpautoload but again it changed nothing. Any ideas ?
The autoload section in the composer file is what tells PHP how to find your namespaces on disk. Your namespace prefix for the class, Wirecore\CakePHP_JWT, is not the namespace you listed in the autoload section, you listed Wirecore\CakePHP-JWT-Plugin. Either fix the namespace declaration to match autoload, like so:
use Wirecore\CakePHP-JWT-Plugin\ .. etc
.. or change fix the autoload section to match the name listed in your namespace declaration:
"autoload": {
"psr-4": {
"Wirecore\\CakePHP_JWT\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Wirecore\\CakePHP_JWT\\Test\\": "tests/",
"Cake\\Test\\": "vendor/cakephp/cakephp/tests/"
}
}
Also, I'm not positive what standards your following here, but they potentially don't look right.
Is this a standalone plugin? If so, I'd mirror the structure from another standalone plugin like https://github.com/dereuromark/cakephp-geo/
If this isn't a standalone plugin (which is what seems more probable), but just a custom plugin being put directly into an existing CakePHP app, you're classes should be stuck in /plugins not /src, per the docs https://book.cakephp.org/4/en/plugins.html#creating-your-own-plugins
You might want to just use the Bake utility as a starting point (that'll solve your autoload issues too!) and copy your code into the classes it creates instead.
So I've been trying to create a custom class file for all my custom classes and append them in there, I'm using namespaces in order to accomplish using them in my controller however the controller is not recognizing the class
Ok:
Here is my custom class file placed in my project as app/Library/robloxClasses.php
namespace App\Library;
class RobloxMaths{
public function sortArrayOfArray(&$array, $subfield)
{
$sortarray = array();
foreach ($array as $key => $row)
{
$sortarray[$key] = $row[$subfield];
}
array_multisort($sortarray, SORT_DESC, $array);
}
}
Library is a folder i made to store all my custom class files in there
Here is how my controller ApiController uses the file using it's namespace
<?php
namespace App\Http\Controllers;
use App\Library\RobloxMaths;
use Illuminate\Http\Request;
class ApiController extends Controller
{
protected $RobloxClass;
public function __construct(){
$this->$RobloxClass= new RobloxMaths;
}
}
?>
The problem is, it keeps returning:
Class 'App\Library\RobloxMaths' not found
And I honestly do not know what's wrong, please help!
NOTE: I have tried composer update, and it fixes it temporarily but after a day or two or after me installing new dependencies it notifies me that the Class 'App\Library\RobloxMaths' not found thing happened
help please
Ensure that you have correctly setup the psr-4 autoload root in your composer.json file and that your file/directory names match perfectly including capitalisation, then run composer dump-autoload.
Example:
"autoload": {
"psr-4": {
"App\\": "app/"
}
}
This will assign the root namespace App to the app folder.
If you are using an IDE, there is a large chance that your use and namespace statements where auto-generated with the lowercase app to match the directory name. As all the names tie up correctly in the IDE there are no errors, but when it comes to running the PHP script the autoloader is not doing require|require_once on your files and therefore your classes are not available.
Option 1 (Do this)
Ensure that your namespaces have consistent capitalisation that matches the composer.json entry.
Option 2 (Written for completion)
Ensure that you add a new entry for this root namespace to your composer.json file. For the example above this would be:
"autoload": {
"psr-4": {
"App\\": "app/",
"app\\": "app/"
}
}
It's an old question, but I had the same problem with laravel 9,
The problem is that I've used php short tag <? instead of <?php at the custom class file.
it's silly but this was the solution for me.
I am creating a project with some additional functionality provided in form of a .php file API which contains some functions and some classes(out of which some class names are conflicting with Laravel built in class names) so, my question how should I include this file in my Laravel Controller to call functions in the file which using the classes of the file without referring Laravel classes and with less or no modification in .php API file?
Note* I am using Laravel-5.1
If you have a custom file containing some classes/functions that need to be loaded for every request, you need to make sure it's added to the autoloader.
In your composer.json add the following in your autoload section:
"autoload": {
"files": [
"path/to/your/File.php"
]
}
This will make sure the file is loaded. Now what you need is a way to use those classes without conflicting with existing Laravel classes.
First, make sure you have a namespace declaration at the top of your included file - say namespace Your\Namespace. In order to avoid conflicts, you need to explicitly tell PHP which class you mean when you reference it in the code. You mentioned your file contains a Response class that also exists in Laravel. In order to be able to use both, you need to alias one of them:
use Illuminate\Http\Response as LaravelResponse;
use Your\Namespace\Response;
Now in your code you can refer to Laravel's Response class as LaravelResponse, and to your response by simply Response.
Location of the file is irrelevant, as long as it's in a folder accessible to Laravel and its patch is added to composer.json.
Keep in mind that storing multiple classes per file is discouraged as a bad practice. I strongly suggest that you split your fine into separate file per class + one additional file with global functions.
Make an alias
Ex.
use App\Http\Requests\Request as DifferentRequest;
DifferentRequest->doStuff();
Aliasing/Importing
make an alias as #user2504370 proposed,
add to the composer:
"autoload": {
"classmap": [
"database",
"place_with_your_file",
],
"psr-4": {
"App\\": "app/",
"your_namespace": "your path",
}
},
and run
composer dump-autoload
EDIT:
there was a typo in classmap. I wanted to tell you you can put your file whenever you want, for example, you can create a new folder 'place_with_your_file', which is not necessarily inside Laravel's folder.
I'm using it with my external libraries.
For PSR-4: if you are using namespaces, then here you will register the base namespace and the folder where can be found:
for example: "Utilities\\": "../utilities/app"
or whichever your path is.
and for classmap, you need to include path to this folder:
"../utilities/app"
and your autoload will look something like this:
"autoload": {
"classmap": [
"database",
"../utilities/app",
],
"psr-4": {
"App\\": "app/",
"Utilities\\": "../utilities/app"`
}
},
Thank you all for taking efforts in trying to solve my problem but none of the solution worked for me so, here is what I tried for my problem
Below is the structure of my php file that I wanted to includes/integrate
<?php
class Misc {
const SUCCESS = 1;
const FAILURE = 0;
public static function get_hash ( $key )
{
...
...
...
}
public static function show_reponse ( $result )
{
...
}
}
function check($keyhash)
{
...
...
...
}
function function2()
{
...
...
...
}
class Response {
public function __construct ( $key )
{
...
}
public function __destruct ()
{
unset( $this->key );
unset( $this->params );
}
public function __set ( $key)
{
...
}
public function __get ( $key )
{
return $this->params[$key];
}
private function check_now ()
{
...
}
}
The main problem I was facing is the class name Response which was conflicting with Laravel Response class so I just removed all classes from the file and moved to their individual files in a new folder in Laravel\App folder and added namespaces to all classes.
Then I moved all functions in a PHP file in laravel\App directory
and used classnames along with the namespace defined and since I moved all functions in a different PHP file I could easily call the functions
so here is my final folder structure of Laravel
Laravel
-App
-Console
-Events
-Exceptions
-...
-Libraries(Folder Containing Individual PHP files of classes from original file)
-Providers
-helpers.php(File containing all functions from original file)
-User.php
-bootstrap
-...
-...
I want to add Accessors and Mutators to a model. In Laravel 4 it worked all fine, but with Laravel 5 I have some trouble.
I have a "lib" folder in my App directory which contains the "db_transformers.php" file. This file holds classes like "dbDate" with a set and get function to transform dates stored in the database to a user-friendly format.
The "db_transformers.php" file is namespaced:
<?php namespace App\lib;
I also rerfer to the folder in my model:
use App\lib;
But my methodes still throw errors:
public function getDateTimeAttribute($value)
{
return dbDate::get($value);
}
This will return a "Class 'App\dbDate' not found" error.
What could be my problem?
You're confusing autoloading (PHP including/requiring a class definition file) with namespaces (a system that allows hierarchical naming of PHP classes/functions to help prevent code conflicts).
It's an easy thing to do. Covering the changes to autoloading in Laravel 5 is beyond the scope of a Stack Overflow question, but if you're interested I've written a multiple article series on how autoloading works with composer/Laravel 4/Laravel 5.
To your specific question, you say you've defined a class named dbDate in a file named db_transformers.php, and db_transformers.php has a namespace of App\lib.
#File: lib/db_transformers.php
namespace App\lib;
//other code
class dbDate
{
//other code
}
//other code
This mean your class's full name is App\lib\dbDate. The entire thing is the class's name. That's probably the biggest thing to get used to with namespaces in PHP.
This means if you wanted to use the class in other code, you'd need to refer to the full class name, including a leading backslash.
return \App\lib\DbDate::get($value);
You could also import the class using the use keyword
use App\lib\DbDate;
//other code
public function getDateTimeAttribute($value)
{
//since we imported the class with `use`, we don't need to type the full name
return DbDate::get($value);
}
The use keywords imports a specific class into the current namespace. When you said
use App\lib;
you were telling PHP
You know that global classApp\lib? I'm going to refer to it below as lib
Since you don't have a class named lib, this is meaningless, and it's why your use didn't help.
So that's namespaces. The other problem you need to solve is autoloading. Autoloading is what lets you skip the require or include statement/function when you want a class definition files in your project.
Laravel 4 used a bunch of different autoloaders, including something called a classmap autoloader. The classmap autoloader automatically parses all the files in your project looking for classes, and creates a giant map of which class is where (that's over simplifying it a bit, see the article series I linked earlier for the full details).
In Laravel 4, the classmap autoloader probably read the file in lib for you. Laravel 5 reduced the number of autoloaders, which included getting rid of the classmap autoloader for most folders.
The simplest thing you can do in Laravel 5 is to configure your project to use the classmap autoloader again. Open up composer.json and find this section
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
}
},
And add lib to the classmap autoloader section
"autoload": {
"classmap": [
"database",
"lib"
],
"psr-4": {
"App\\": "app/"
}
},
This tells composer to include the lib folders when it creates its autoloader files. You'll need to run the dumpautoload command
composer dump-autoload
after doing that, and you should be able to use the classes defined in lib/db_transformers.php as you wish.
You need to use the complete class name: use App\lib\dbDate;
You might also look into using view decorators for this purpose, as doing it in your model is really not appropriate.
Several packages exist to help with this, e.g. https://github.com/ShawnMcCool/laravel-auto-presenter
I have created a php file under the Models folder provided by Laravel.
Inside I have:
// Filename: Models/Shoopy.php
namespace Whatever\Something;
class Shoopy
{
public function Toot(){};
}
Now in another Model file I am using that namespace:
use \Whatever\Something\Shoopy;
class AnotherModel
{
public function Spop()
{
$harr = new Shoopy();
}
}
It comes up with a Laravel error:
class Whatever\Something\Shoopy not found
Any ideas?
I know this is an older issue, but if you go into your composer.json file, you'll probably see something like...
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
}
},
What you can do is tell composer where Whatever should be, say if it was a different location (or sub-folder) from where Laravel normally keeps it's files.
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/",
"Whatever\\": "app/Whatever",
}
},
Classes need to exist in files with directory paths that match their namespace. This is according to the PSR-0 Standard. In your example, try placing your Shoopy class in the file:
app/models/Whatever/Something/Shoopy.php
And then see if the autoloader can find it.