I have two controller file homecontroller and backendcontroller. What is the best way to create global function and access it from both files?
I found here Arian Acosta's answer helpful but I wonder if there is an easiest way. I would appreciate any suggestions.
Solution
One way to do this is to create a class and use its instance, this way you can not only access the object of the class within a controller, blade, or any other class as well.
AppHelper file
In you app folder create a folder named Helpers and within it create a file name AppHelper or any of your choice
<?php
namespace App\Helpers;
class AppHelper
{
public function bladeHelper($someValue)
{
return "increment $someValue";
}
public function startQueryLog()
{
\DB::enableQueryLog();
}
public function showQueries()
{
dd(\DB::getQueryLog());
}
public static function instance()
{
return new AppHelper();
}
}
Usage
In a controller
When in a controller you can call the various functions
public function index()
{
//some code
//need to debug query
\App\Helpers\AppHelper::instance()->startQueryLog();
//some code that executes queries
\App\Helpers\AppHelper::instance()->showQueries();
}
In a blade file
Say you were in a blade file, here is how you can call the app blade helper function
some html code
{{ \App\Helpers\AppHelper::instance()->bladeHelper($value) }}
and then some html code
Reduce the overhead of namespace (Optional)
You can also reduce the overhead of call the complete function namespace \App\Helpers by creating alias for the AppHelper class in config\app.php
'aliases' => [
....
'AppHelper' => App\Helpers\AppHelper::class
]
and in your controller or your blade file, you can directly call
\AppHelper::instance()->functioName();
Easy Solution:
Create a new Helpers folder in your app directory.
Create a php file named your_helper_function.php in that Helpers directory.
Add your function(s) inside your_helper_function.php
function your_function($parameters){
//function logic
}
function your_another_function($parameters){
//function logic
}
Add this file to the Files key of your composer.json like
"autoload": {
...
"files": [
"app/Helpers/your_helper_function.php"
]
...
}
Finally, regenerate composer autoload files. (Run this in your project directory)
composer dump-autoload
That's it! and now you can access your_function() or your_another_function() in any part of your Laravel project.
If you still have any confusion, check my blog post on how to do this:
How to Add a Global Function in Laravel Using Composer?
Updated:
Step 1
Add folder inside app folder
app->Helper
Step 2
add php Class inside Helper folder
Eg. Helper.php
Add namespace and class to the Helper.php
namespace App\Helper;
class Helper
{
}
Register this Helper.php into config/app.php file
'aliases' => [
....
'Helper' => App\Helper\Helper::class
]
Now, write all the functions inside Helper.php and it will be accessible everywhere.
How to access from Controller?
Step 1 - Add a namespace at top of the controller.
use App\Helper\Helper;
Step 2 - Call function - Assume there a getInformation() inside the Helper Class.
$information = Helper::getInformation()
In your Controller.php which extends BaseController, you can create a function like;
public function data($arr = false)
{
$data['foo'] = 'bar';
return array_merge($data,$arr);
}
And from any controller when you send a data to a view;
public function example()
{
$data['smthg'] = 'smthgelse';
return view('myView',$this->data($data));
}
The data in the the main controller can be accessed from all controllers and blades.
The Laravel Service Provider way
I've been using global function within Laravel for a while and I want to share how I do it. It's kind of a mix between 2 answers in this post : https://stackoverflow.com/a/44021966/5543999 and https://stackoverflow.com/a/44024328/5543999
This way will load a file within a ServiceProvider and register it within your Laravel app.
Where is the difference, the scope, it's always about the scope.
Composer //Autload whitin composer.json method
|
|--->Laravel App //My method
|
|--->Controller //Trait method
|--->Blade //Trait method
|--->Listener //Trait method
|--->...
This is a really simplist way to explain my point, all three methods will achieve the purpose of the "Global function". The Traits method will need you to declare use App\Helpers\Trait; or App\Helpers\Trait::function().
The composer and service provider are almost about the same. For me, they answer better to the question of what is a global function, because they don't require to declare them on each place you want to use them. You just use them function(). The main difference is how you prefer things.
How to
Create the functions file : App\Functions\GlobalFunctions.php
//App\Functions\GlobalFunctions.php
<?php
function first_function()
{
//function logic
}
function second_function()
{
//function logic
}
Create a ServiceProvider:
//Into the console
php artisan make:provider GlobalFunctionsServiceProvider
Open the new file App\Providers\GlobalFunctionsServiceProvider.php and edit the register method
//App\Providers\GlobalFunctionsServiceProvider.php
public function register()
{
require_once base_path().'/app/Functions/GlobalFunctions.php';
}
Register your provider into App\Config\App.php wihtin the providers
//App\Config\App.php
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Auth\AuthServiceProvider::class,
...
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
App\Providers\GlobalFunctionsServiceProvider::class, //Add your service provider
Run some artisan's commands
//Into the console
php artisan clear-compiled
php artisan config:cache
Use your new global functions
//Use your function anywhere within your Laravel app
first_function();
second_function();
Laravel uses namespaces by default. So you need to follow the method described in that answer to setup a helper file.
Though in your case you want to access a method in different controllers. For this there's a simpler way. Add a method to you base controller app/Http/Controllers/Controller.php and you can access them in every other controller since they extend it.
// in app/Http/Controllers/Controller.php
protected function dummy()
{
return 'dummy';
}
// in homecontroller
$this->dummy();
There are a few ways, depending on the exact functionality you're trying to add.
1) Create a function inside Controller.php, and make all other controller extend that controller. You could somewhat compair this to the master.blade.php
2) Create a trait, a trait can do a lot for you, and keeping ur controllers clean. I personally love to use traits as it will look clean, keep my Controller.php from being a mess with tons of different lines of code.
Creating a global function
create a Helpers.php file under a folder, let's name it 'core'.
core
|
-- Helpers.php
namespace Helpers; // define Helper scope
if(!function_exists('html')) {
function html($string) {
// run some code
return $str;
}
}
In your composer.json
"autoload": {
"psr-4": {
},
"files": [
"core/Helpers.php"
]
}
in the file that you want to use it
// the " use " statement is not needed, core/Helpers is loaded on every page
if(condition_is_true) {
echo Helpers\html($string);die();
}
Remove the namespace in Helpers.php if you want to call your function without the need to prefix namespace. However I advise to leave it there.
Credit: https://dev.to/kingsconsult/how-to-create-laravel-8-helpers-function-global-function-d8n
By using composer.json and put the function containing file(globalhelper.php) to the autoload > files section, then run
composer dump-autoload
You can access the function inside the file(globalhelper.php) without having to calling the class name, just like using default php function.
I am calling a simple function from a controller:
flash('my message');
flash function is inside a helpers.php file in App\Http
function flash($message)
{
$flash = app('App\Http\Flash');
return $flash->message($message);
}
flash function calls a Flash object
namespace App\Http;
class Flash{
public function message($message)
{
session()->flash('flash_message', $message);
}
}
Composer.json includes:
"autoload": {
"files": [
"app/Http/helpers.php"
],
Ran the command - composer dump-autoload
Page is showing - Call to undefined function App\Http\Controllers\flash()
I've tried so many things! Even if I add a tiny test function into the helpers.php file I can't use it in controller.
Is this a namespace issue? I didn't think I had to add a use xxxx; at top of controller as the helpers.php is added to autoload and global?
EDIT.
I believe that the registering of the helpers.php file is the key here. All I am doing is adding some functions to global file but cannot get to them from my controller. I added a really simple function to the helpers.php file yet couldn't access it from the controller: do I need to add anything to the controller in order to be able to use the helpers file?
I have managed to get this working by including the helpers.php file in the controller method:
include(app_path() . '/helpers.php');
flash('my message');
This now allows me to call the function. So the autoloading is not working! A little puzzled...
UPDATE.
I had to put the desired function into a class and call the class. This now works fine. I just couldn't get the helpers.php to autoload anything.
I would place the helper file in a global position and in your composer.json file:
"files":[
"app/helper.php"
],
In helper.php:
function newflash($message)
{
session()->flash('flash_message', $message);
}
Do a composer dump-autoload
It's as simple as this.
Now you can call the newflash() method from anywhere in your application.
Don't forget to register your class in the service provider.
I'd like to log the user's name along with the error that is outputted to the log. How do I add a variable to the beginning of an error log entry that outputs an exception?
I think I've got a fairly easy way to do this.
Solution 1
Create a new folder under app called handlers and create a new class called CustomStreamHandler.php which will hold the custom monolog handler.
namespace App\Handlers;
use Monolog\Handler\StreamHandler;
use Auth;
class CustomStreamHandler extends StreamHandler
{
protected function write(array $record)
{
$record['context']['user'] = Auth::check() ? Auth::user()->name : 'guest';
parent::write($record);
}
}
Make sure you set the namespace if you changed it from App and also modify the line where it's setting the user in the context so it works with your users table.
Now we need to drop the current StreamHandler from monolog. Laravel sets this up by default and as far as I can see, there isn't a good way to stop Laravel from doing this.
in app/Providers/AppServiceProvider, we should modify the boot() function to do remove the handler and insert the new one. Add the following...
// Get the underlying instance of monolog
$monolog = \Log::getMonolog();
// Instantiate a new handler.
$customStreamHandler = new \App\Handlers\CustomStreamHandler(storage_path('logs/laravel.log'));
// Set the handlers on monolog. Note this would remove all existing handlers.
$monolog->setHandlers([$customStreamHandler]);
Solution 2
This is a much easier solution but also not exactly what you are looking for (but it might still work for you).
Add the following to AppServiceProvider.php boot().
Log::listen(function()
{
Log::debug('Additional info', ['user' => Auth::check() ? Auth::user()->name : 'guest']);
});
This will simply listen for any logging and also log a debug line containing user information.
I installed Mailgun for Laravel. I then tried to run the example
$data = [];
Mailgun::send('emails.welcome', $data, function($message)
{
$message->to('foo#example.com', 'John Smith')->subject('Welcome!');
});
But I got the following error:
"Argument 1 passed to Bogardo\\Mailgun\\Mailgun::__construct() must be an instance of Illuminate\\View\\Environment, instance of Illuminate\\View\\Factory given, called in /Users/koushatalebian/CLG/CL2G/app/vendor/bogardo/mailgun/src/Bogardo/Mailgun/MailgunServiceProvider.php on line 33 and defined"
What is going on?
If you are using Laravel 4.2, Please use Illuminate\View\Factory instead of Illuminate\View\Environment.
Bogardo mail gun package pointing wrong file.
/Users/koushatalebian/CLG/CL2G/app/vendor/bogardo/mailgun/src/Bogardo/Mailgun/MailgunServiceProvider.php
View / Pagination Environment Renamed
If you are directly referencing the Illuminate\View\Environment class or
Illuminate\Pagination\Environment class, update your code to reference Illuminate\View\Factory and
Illuminate\Pagination\Factory instead. These two classes have been renamed to better reflect their
function.
Edit:
You can use the correct class by editing the following file:
vendor/bogardo/mailgun/src/Bogardo/Mailgun/Mailgun.php
in Line 5:
remove use Illuminate\View\Environment; and use use Illuminate\View\Factory;
in line 53:
remove
public function __construct(Environment $views)
{
$this->views = $views;
}
use
public function __construct(Factory $views)
{
$this->views = $views;
}
Hope this will fix.
I know this has been asked before, and I've looked through every answer posted, but to no avail. Basically, I am trying to extend the Codeigniter form validation library on a CI2+ project, but every single time I get the error:
Fatal error: Call to a member function get_errors_array() on a non-object
Below is my code:
application/core/CB_Form_validation.php
class CB_Form_validation extends CI_Form_validation{
function __construct($rules = array()) {
parent::__construct($rules);
log_message('debug', "CB_Form_validaiton class initialized");
}
public function get_errors_array() {
return $this->_error_array;
}
}
and then in my ajax file I have the construct etc.
public function save(){
if($this->form_validation->run() == FALSE){
}
}
and inside that if statement I have tried the following:
echo $this->form_validation->get_errors_array();
echo $this->cb_form_validation->get_errors_array();
echo get_errors_array();
I have also tried placing the CB_Form_validation.php in application/libraries as well. Just as well, I have also tried this in my construct of my ajax controller
$this->load->library('CB_Form_validation');
$this->load->library('core/CB_Form_validation');
And I have set CB_ as my custom class prefix
Turns out that to fix this, you should do the following:
Move your custom form validation class to the application/libraries folder
You can keep the construct of your custom class how it is
Use $this->form_validation->method() to access the function you would like
As long as your loading the form_validation library, you don't need to perform $this->load->library('custom_class') because CI picks up on your custom prefix anyways
Hope this helps someone