How to create Helper Methods on Laravel not a Facade - php

I've read a lot of questions on how to make helper methods in Laravel 5.1. But I don't want to achieve this via a Facade.
HelperClass::methodName();
I want to make helper methods just like on these methods Laravel Helper Methods like:
myCustomMethod();
I don't want to make it a Facade. Is this possible? How?

If you want to go the 'Laravel way', you can create helpers.php file with custom helpers:
if (! function_exists('myCustomHelper')) {
function myCustomHelper()
{
return 'Hey, it\'s working!';
}
}
Then put this file in some directory, add this directory to autoload section of an app's composer.json:
"autoload": {
....
"files": [
"app/someFolder/helpers.php"
]
},
Run composer dumpauto command and your helpers will work through all the app, like Laravel ones.
If you want more examples, look at original Laravel helpers at /vendor/laravel/framework/Illuminate/Support/helpers.php

To start off I created a folder in my app directory called Helpers. Then within the Helpers folder I added files for functions I wanted to add. Having a folder with multiple files allows us to avoid one big file that gets too long and unmanageable.
Next I created a HelperServiceProvider.php by running the artisan command:
artisan make:provider HelperServiceProvider
Within the register method I added this snippet
public function register()
{
foreach (glob(app_path().'/Helpers/*.php') as $filename){
require_once($filename);
}
}
lastly register the service provider in your config/app.php in the providers array
'providers' => [
'App\Providers\HelperServiceProvider',
]
After that you need to run composer dump-autoload and your changes will be visible in Laravel.
now any file in your Helpers directory is loaded, and ready for use.
Hope this works!

This is what is suggested by JeffreyWay in this Laracasts Discussion.
Within your app/Http directory, create a helpers.php file and add your functions.
Within composer.json, in the autoload block, add "files": ["app/Http/helpers.php"]. And run
composer dump-autoload.

Related

How laravel's helper functions are available globally in every file?

I have just started exploring laravel but I have one confusion . I know how to create own custom function file and make it available globally using compose.json file but I was trying to figure out how laravel's helper function like route() , view() are accessible without including there source file and I can't find any auto discovery in composer.json file neither in any Service Provider .
PS : I have only checked in in Providers/ Directory.
Can anyone tell me how this thing works?
Through composer Laravel has defined which files should be autoloaded. With the line in the composer.json file in Laravel/framework it specifies what should be autoloaded.
It loads the following file.
You can create similar autoloaders if you prefer, but having to much logic in such helpers could easily become an anti pattern. As the logic, is a little more hidden than class based logic, when people have to look through your projet.
On your composer.json file on the root directory of your laravel app, look for the entry autoload.
This means all methods on those directories are autoloaded.
That is why if you have (newly) created a method / function within those directory and it doesn't work (or not found) as expected, you need to run composer dump-autoload to make sure that everything has been loaded.
That's also where I put my custom helper file:
"files": [
"app/Helpers/helpers.php"
]
All function here will then be available on all controllers, traits and views.

What steps it takes to add GitHub repo to Laravel application?

I would like to use following GitHub repo in my Laravel application:
https://github.com/khanamiryan/php-qrcode-detector-decoder
It doesn't have composer set up nor it can be found from Packagist. I tried to use regular php_require but it tells me "Class 'App\Http\Controllers\QrReader' not found".
Using php_require feels wrong anyways. What is the correct way to handle situation like this?
Create a new directory in your app root
mkdir third-party
cd third-party
Clone the repo
git clone https://github.com/khanamiryan/php-qrcode-detector-decoder
Edit your composer.json file and add it to the classmap:
"classmap": [
"database",
"third-party/php-qrcode-detector-decoder"
],
Update class maps:
composer dumpautoload
And you should see in your vendor/composer/autoload_classmap.php
'Zxing\\Binarizer' => $baseDir . '/third-party/php-qrcode-detector-decoder/lib/Binarizer.php',
'Zxing\\BinaryBitmap' => $baseDir . '/third-party/php-qrcode-detector-decoder/lib/BinaryBitmap.php',
...
Then you just have to use it:
use Zxing\Reader;
I think the major class is QrReader(). You can use this class as controller class but you need to extend the controller class and fix imports. You can import this class as third party class on your laravel controller too.
Do you need to use QrReader() class?
Then just put all the library files App\Libraries and the main class in App\classes. Or you can do in our own way too. But follow the following
1) Manage namespaces
2) import the class to your controller by using
use App\classes\QrReader
Finally, you will have access to all the methods defined in the imported class. But in you main class you need to correct the path and dependencies of libraries files.
You can try this tutorial too:
How to use external classes
You can read the discussion here (Nice)
Best way to import third party classes
Because this github project does not have a composer.json file, I don't think you can use it with composer.
However, you could branch the repo, make your own copy, and add a composer file to it. Then you'd be able to add it to your main project's composer.json file:
{
"repositories": [
{
"type": "git",
"url": "https://github.com/your-git-account/php-qrcode-detector-decoder"
}
],
"require": {
"your-git-account/php-qrcode-detector-decoder": "dev-master"
}
Hope this helps!
(Source https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository)

Laravel custom directory structure

I am attempting to create a sort of custom directory structure, my proposed structure is as follows
App/ - Contains all Laravel core code
Repo/ - Contains packages, each package contains Controllers, Views, Modals, Seeds and Migrations specific to that package
Is it possible via Composer or would it take a lot of core modification?
Controller routing in routes.php
Route::resource('account', '\Repo\Accounts\Accounts');
The first occurrence of accounts is the folder and the second being the class. I know I could write each directory seperetly then dump composer autoload, however when you have 30 seperate packages per app, it is a little time consuming. Am I missing something super straight forward?
This is possible with composer. Add inside of your composer.json:
"autoload": {
"classmap": [
// ...
],
"psr-4": {
"Repo\\" : "Repo"
}
},
Then you can use classes inside of the /Repo directory, and classes in there will reside in the \Repo namespace.

how to call modules' model and controllers files in a controller in laravel 4.1

I created a modular system by using laravel 4.1 I have a tree scheme as follows:
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 the model from a controller in app/controllers/ class.
How I can call that module and its model?
Make sure your /app/modules is added to your composer.json file's autoload : classmap and issue composer dump-autoload or php artisan dump-autoload. Then you can just create an instance like new ModuleModel or whatever name you gave your class. Though it's better to pass to your controller by dependency injection. This way your code will be easier to test because you can pass in stub data.
public function __construct(ModuleModel $module_model_instance) {
$this->module_model_instance = $module_model_instance;
}
I'd rather add this as a comment but have insufficient rep.
If everything is correctly autoloaded by composer in the PSR-0 (or 4) section, then you should just be able to reference it using it's namespace?
I sometimes need to run
composer dump-autoload
to refresh the autoloaded files, especially if using vagrant.
Hope this is helpful. I'm not sure if I've fully understood your problem.

Organizing Laravel and autoloading sub directories

I am wanting to structure my laravel app in a way that all of my code is under the src directory. My project structure would look something like the below. How would I do this where I can still call Route::get('accounting/item/{id}','AccountingItemController#getId')
I am wanting to avoid adding every module under src to the ClassLoader. Is there a way to tell the class loader to load all sub-directories under the parent directory src?
app
app/src
app/src/accounting
app/src/accounting/controllers
app/src/accounting/models
app/src/accounting/repos
app/src/accounting/interfaces
app/src/job
app/src/job/controllers
app/src/job/models
app/src/job/repos
app/src/job/interfaces
Yes, it's called PSR-0.
You should namespace all of your code. Typically you'll have a vendor name that you'll use a the top level namespace. Your application structure should then look something like this.
app/src/Vendor/Accounting/Controllers
app/src/Vendor/Job/Controllers
Your controllers will then be namespaced accordingly.
namespace Vendor\Accounting\Controllers;
And when using them in routes.
Route::get('accounting/item/{id}','Vendor\Accounting\Controllers\ItemController#getId');
Lastly, you can register your namespace with Composer in your composer.json.
"autoload": {
"psr-0": {
"Vendor": "app/src"
}
}
Of course, if you don't want that top level Vendor namespace you can remove it, but you'll need to register each component as PSR-0.
"autoload": {
"psr-0": {
"Accounting": "app/src",
"Job": "app/src",
}
}
Once done, run composer dump-autoload once and you should be able to add new controllers, models, libraries, etc. Just make sure the directory structure aligns with the namespacing of each file.
Do you have composer installed? You should use this:
composer dump-autoload
But you can could add directories to the Laravel's classloader. Check the reference here: http://laravel.com/api/class-Illuminate.Support.ClassLoader.html

Categories