How to autoload helper functions as needed in Composer? - php

Say you have 1 file per function:
/src/Helpers/fooHelper.php
<?php
namespace MyHelper;
function fooHelper() {};
/src/Helpers/barHelper.php
<?php
namespace MyHelper;
function barHelper() {};
I see that there is
"autoload": {
"files": ["src/Helpers/functions.php"]
}
Is it possible to autoload these functions via Composer on demand instead of every request?

Is it possible to autoload these functions via Composer on demand instead of every request?
No, there is no autoloading support for functions in PHP. You need to either load them manually or add files with functions declaration to autoload.files config in composer.json - they're will be loaded on each request, even if you never use it.
The only sane workaround at this moment is to wrap helpers in some static class, which could be autoloaded without any trouble.
class MyHelper {
public static function fooHelper() {}
public static function barHelper() {}
}
MyHelper::fooHelper();
MyHelper::barHelper();

If you want to add it for every helper file you should do the following way:
"autoload": {
"files" : [
"path_to file_1.php",
"path_to file_2.php",
"and so on"
]
}
It should work after running the command: composer dump-autoload or composer dumpautoload.

Related

Laravel helper files not working?

Seems like my helper file app/helpers.php isn't working at all.
I just get a Call to undefined function App\Http\Controllers\test() error when I try to call functions in it even though it has the exact same setup (i think?) as another project that works.
All the things that seemed to help everyone else with this problem doesn't work for me. Ie, adding the file to the composer.json, dumping autoload and so on.
Content of helper file:
<?php
function test()
{
dd(":(");
}
Calling the function from a Controller:
public function test()
{
test();
}
You need to load the file with custom helpers. For example, if its name is helper and it's in the app directory:
"autoload": {
....
"files": [
"app/helper.php"
]
},
Also, run the composer dump-autoload command after that.

Composer autoload file not working

My Autoload specification are as follows
"autoload" : {
"psr-4" : {
"MyMVC\\" : "app/"
},
"classmap": [
"app/Controllers",
"app/Helpers"
],
"files": ["app/routes.php"]
},
The contents of routes.php file are:
<?php
use MyMVC\Core\Route;
$route = new Route;
$route->add('/', 'HomeController#index');
$route->add('about', 'AboutController#index');
$route->add('contact', 'ContactController#index');
now in my app/init.php i am trying to use the $route object but its giving me error
Notice: Undefined variable: route in /var/www/html/mymvc/app/init.php on line 29
Here is how i am trying to use the $route object.
/**
* Constructor
* Bootstrap our application based on the configurations provided
*/
public function __construct()
{
// require 'app/routes.php` This will work fine but it should be autoloaded
var_dump($route);
exit;
}
I have also ran command composer dump-autoload
Autoloading won't work here. PHP can only autoload classes. Your expectation that app/routes.php will be autoloaded is not possible, because that file does not contain a class declaration, and you are not able to trigger it's execution by using a previously unknown class.
It is true that Composer will execute that file once when you include vendor/autoload.php - however, this is really bad behavior of your software. Don't use the "files" autoloading to include configuration files. Mind the performance impact this may have when being used in libraries. You should avoid using it altogether, it is meant to be used for legacy code that cannot otherwise be made working.
On the other hand, your architecture is broken. You shouldn't write a class that "magically" knows about the configuration just by accessing a variable that is supposed to be initialized somewhere else. A good pattern would be to pass the configuration as a parameter to the constructor:
public function __construct ($routes)
{
$this->routes = $routes;
}
The part of the code that creates this class is supposed to grab the configuration from somewhere and pass it as a parameter. This concept is called inversion of control or dependency injection: Classes do not invoke the other classes they need to work with, they ask for them and get them as a parameter.

How do I make global helper functions in laravel 5? [duplicate]

This question already has answers here:
How to create custom helper functions in Laravel
(23 answers)
Closed 7 months ago.
If I wanted to make a currentUser() function for some oauth stuff I am doing where I can use it in a view or in a controller (think rails, where you do helper_method: current_user in the application controller).
Everything I read states to create a helpers folder and add the function there and then that way you can do Helpers::functionName Is this the right way to do this?
Whats the "laravel way" of creating helper functions that can be used in blade templates and controllers?
Create a new file in your app/Helpers directory name it AnythingHelper.php
An example of my helper is :
<?php
function getDomesticCities()
{
$result = \App\Package::where('type', '=', 'domestic')
->groupBy('from_city')
->get(['from_city']);
return $result;
}
generate a service provider for your helper by following command
php artisan make:provider HelperServiceProvider
in the register function of your newly generated HelperServiceProvider.php add following code
require_once app_path('Helpers/AnythingHelper.php');
now in your config/app.php load this service provider and you are done
'App\Providers\HelperServiceProvider',
An easy and efficient way of creating a global functions file is to autoload it directly from Composer. The autoload section of composer accepts a files array that is automatically loaded.
Create a functions.php file wherever you like. In this example, we are going to create in inside app/Helpers.
Add your functions, but do not add a class or namespace.
<?php
function global_function_example($str)
{
return 'A Global Function with '. $str;
}
In composer.json inside the autoload section add the following line:
"files": ["app/Helpers/functions.php"]
Example for Laravel 5:
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
},
"files": ["app/Helpers/functions.php"] // <-- Add this line
},
Run composer dump-autoload
Done! You may now access global_function_example('hello world') form any part of your application including Blade views.
Laravel global helpers
Often you will find your self in need of a utility function that is access globally throughout you entire application. Borrowing from how laravel writes their default helpers you're able to extend the ability with your custom functions.
Create the helper file, not class
I prefer to you a file and not a class since I dont want to bother with namespaces and I want its functions to be accessible without the class prefixes like: greeting('Brian'); instead of Helper::greeting('Brian'); just like Laravel does with their helpers.
File: app/Support/helper.php
Register helper file with Composer: composer.json
{
...
"autoload": {
"classmap": [
"database"
],
"files": [
"app/Support/helpers.php"
],
"psr-4": {
"App\\": "app/"
}
},
...
}
Create your first helper function
<?php
if (!function_exists('greet')) {
/**
* Greeting a person
*
* #param string $person Name
* #return string
*/
function greet($person)
{
return 'Hello ' . $person;
}
}
Usage:
Remember to autoload the file before trying to access its functions:
composer dump-autoload
Let's test with Tinker
$ php artisan tinker
Psy Shell v0.8.17 (PHP 7.0.6 ΓÇö cli) by Justin Hileman
>>> greet('Brian');
=> "Hello Brian"
>>> exit
Exit: Goodbye.
With Blade
<p>{{ greet('Brian') }}</p>
Advanced usage as Blade directive:
A times you will find yourself wanting to use a blade directive instead of a plain function.
Register you Blade directive in the boot method of AppServiceProvider: app/Providers/AppServiceProvider.php
public function boot()
{
// ...
Blade::directive('greet', function ($expression) {
return "<?php echo greet({$expression}); ?>";
});
}
Usage:
<p>#greet('Brian')</p>
Note: you might need to clear cache views
php artisan view:clear
The above answers are great with a slight complication, therefore this answer exists.
utils.php
if (!function_exists('printHello')) {
function printHello()
{
return "Hello world!";
}
}
in app/Providers/AppServiceProvider.php add the following in register method
public function register()
{
require_once __DIR__ . "/path/to/utils.php"
}
now printHello function is accessible anywhere in code-base just as any other laravel global functions.
Another option, if you don't want to register all your helper functions one by one and wondering how to register them each time you create a new helper function:
Again in the app/Providers/AppServiceProvider.php add the following in register method
public function register()
{
foreach (glob(app_path().'/Helpers/*.php') as $filename) {
require_once($filename);
}
}

Include a file in laravel controller?

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
-...
-...

Creating a base test-class for PHPUnit and extending it for common functionality results in class not found error

I'm running PHPUnit using a bootstrap file for autoloading classes (generated by composer).
All my tests load up classes just fine, but for two of my tests, I made a "base" test class which extends \PHPUnit\Framework\TestCase (similar to PHPUnit_Framework_TestCase before PHPUnit7), and then two test classes that extend the base class, similar structure to the following example code:
abstract class BaseTest extends \PHPUnit\Framework\TestCase
{
abstract function setUp();
protected function getCommonTestVariables()
{
// ...
}
protected function runCommonTests()
{
// ...
}
}
class BlahBlahTest extends BaseTest
{
public function setUp()
{
$variables=$this->getCommonTestVariables();
//etc...
}
public function testThings()
{
$this->runCommonTests();
}
}
Whenever I run this, PHPUnit gives an error:
Fatal error: Class 'BaseTest' not found in BlahBlahTest.php on line 13
I've checked filenames, locations, namespaces and everything seems to be in order. Any help would be appreciated to get to the bottom of this
I ran into the same problem and if you are not too familiar with the inner workings of both PHPUnit and Composer this can indeed seem perplexing.
PHPunit does not use use the Composer autoloader to find any of your test classes. It just scans any directory you give it and operates on one file at a time.
Hence it does not know about any other class than the one in the file it is currently operating on. That is where the bootstrap file comes into play.
If you want to use the Composer Autoloader to load other test classes, you need to tell it where it can find these test classes (and, optionally, in which namespace).
There are two ways to do this:
Add an autoload-dev section to your composer.json or
Add the test directory to the Composer Autoloader
Use autoload-dev
The autoload-dev sections allows you to define autoload rules for development purposes.
Quoting directly from the manual:
Classes needed to run the test suite should not be included in the
main autoload rules to avoid polluting the autoloader in production
and when other people use your package as a dependency.
Therefore, it is a good idea to rely on a dedicated path for your unit
tests and to add it within the autoload-dev section.
Example:
{
"autoload": {
"psr-4": { "MyLibrary\\": "src/" }
},
"autoload-dev": {
"psr-4": { "MyLibrary\\Tests\\": "tests/" }
}
}
Add to the Composer Autoloader
An alternative would be to get the Composer Autoloader and add your testing namespace (if you have any) and the directory where your tests live. How to do this, as described in the manual (at the bottom of the autoloading section in "Basic Usage") is :
$loader = require('/path/to/vendor/autoload.php');
$loader->add('Test\\', __DIR__ . '/Tests');
If your tests use namespaces that mirror the test directory and you still run into trouble, you can try omitting the prefix by replacing the first parameter ('Test\\') with ''.
If you want further insight into how all of this works you should take a look at the Composer ClassLoader class, especially the add() and findFile() methods.
For me the solution was much simpler.
I changed the capital letter of Test to test at the end of the file and the class name
BaseSomethingtest.php
<?php
namespace Something\Tests\Sub1\Sub2;
class BaseSomethingtest
{
}
I just put a word at the end of my base class. As far as it
didn't finish with Test, phpunit didn't call it
BaseSomethingTestCase.php
<?php
namespace Something\Tests\Sub1\Sub2;
class BaseSomethingTestCase
{
}
I'm not sure if you still need a solution, but this worked for me:
Non-testable base class extending PHPUnit_Framework_TestCase
In PHP 7.0+ extends PHPUnit_Framework_TestCasechanged to extends \PHPUnit\Framework\TestCase, try this one.

Categories