I have created some library services in app\Library. I used AppServiceProvider to bind that service using following code:
$this->app->bind('App\Library\Globalfunction', function ($app) {
return new Globalfunction();
});
app\Library\Globalfunction.php
<?php
namespace App\Library;
class Globalfunction {
protected $_ci;
public $siteConfig=array();
public $smtpConfig=array();
public $socialConfig=array();
public $paramConfig;
public $paramFrom;
public function test($param) {
return $param;
}
}
?>
To use this test() in controller i am including namespace using following:
use App\Library\Globalfunction;
once namespace is included i use following code:
$globalFunction = new Globalfunction();
echo $globalFunction->test('hello');
All of this code working fine but i don't want to add use App\Library\Globalfunction; in each file so is there anyway i can do that? is there any autoload file where i can put this and i can access Globalfunction?
I google solution for that and i tried several solutions like add this in composer or create package etc but it's not working so please if anyone have solution for this problem please let me know.
Maybe you can follow the same approach as Laravel?
Let me give you an example on how to achieve this.
First, create a Helpers.php file in app/Helpers.php.
You also need to autoload it.
"autoload": {
"classmap": [
"database/seeds",
"database/factories",
"database/providers"
],
"files": [
"app/Helpers.php"
],
"psr-4": {
"App\\": "app/"
}
}
Once that is done, you could define a function as such in your newly autoloaded Helpers.php:
if(! function_exists('global_function')) {
function global_function()
{
return new \App\Library\Globalfunction();
}
}
Then to use it anywhere, you can just do this.
global_function()->test('hello');
This is just a simple example. Obviously there are a lot of considerations you have to make before implementing this.
However, Laravel has a similar approach to providing global helper functions. For example:
use Illuminate\Support\Facades\Session;
// This
echo Session::get('key');
// is the same as
echo session()->get('key');
Related
Hi i am trying to show all count for left sidebar menu but unfortunately i am getting error class not found Class 'app/Http/Helpers/Helpers.php' not found please help me how can id do that thanks.
app/Http/Helpers/Helpers.php
function NotificationCount()
{
return Example::where('status', 1)->where( 'created_at', '>', Carbon::now()->subDays(3))->latest()->count();
}
leftsidebar
#php
$className = 'app/Http/Helpers/Helpers.php';
$count = new $className();
return $count->NotificationCount();
#endphp
Best Practices for custom helpers in Laravel.
Create a helpers.php file in your app folder and load it up with composer:
"autoload": {
"classmap": [
...
],
"psr-4": {
"App\\": "app/"
},
"files": [
"app/helpers.php" // <---- ADD THIS
]
},
After adding that to your composer.json file, run the following command:
composer dump-autoload
add your function
function propertyNotificationCount()
{
return Property::where('status', 1)->where( 'created_at', '>', Carbon::now()->subDays(3))->latest()->count();
}
in helper.php file
Now in any blade file you can call propertyNotificationCount() this function.
As far as I know, it's not really a good practice to use #php #endphp inside blade templates.
I would probably consider another approach and try to return the notification count from the controller somehow and inside php you could handle more easily the class not found error ( maybe just declare it with use at the begging of the controller and you can use it afterwards )
I have 2 models:
Bill:
id, account_id, descripcion, monto_pagado, saldo
Payment:
id, bill_id, monto
Each time someone insert a new bill to the account or insert a new payment I pretend to calculate the balance of the account.
What would be the best place to accomplish this:
as service
as mutators in the model
as function in the controller
I know i would have to call this in others places of my project. So i would like it to be a global function. What would be the best place to do it?
You could use an event in your models. Use creating if you want to calculate before the model is actually created in the database, or created if you want to calculate after it has been created.
In your App\Providers\AppServiceProvider::boot() method, define the events for both models:
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Bill::creating(function ($bill) {
// Do something with $bill
});
}
// etc
}
To avoid code repetition, you may use a trait and use it in both classes. Call it PretendCalculationTrait for example and place it in app/Traits (create the directory if needed):
<?php
namespace App\Traits;
trait PretendCalculationTrait
{
public function pretendCalculate()
{
// Do your stuff
}
}
Then in your model, use this trait:
class Bill extends Eloquent
{
use App\Traits\PretendCalculationTrait;
// etc.
}
Finally, in your AppServiceProvider, call the method defined in the trait:
public function boot()
{
Bill::creating(function ($bill) {
return $bill->pretendCalculate();
});
Payment::creating(function ($payment) {
return $payment->pretendCalculate();
});
}
See Laravel Model Events documentation for more details.
One possible solution, since you mentioned wanting it to be a global function, is to use Laravel's autoloading feature.
Create a file that contains the function for your calculation. It can be placed anywhere, and contain other functions, but for brevity we'll place it here: App/Http/customFunctions.php. In your file, create your function:
function pretendCalculation()
{
return $something;
}
Next, tell Laravel to autoload it by adding it to your autoloading list in composer.json:
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
},
"files": [
"app/Http/customFunctions.php" <-- Here is the new file
]
Then just execute a composer dump auto-load -o or the like, and now you'll have access to this file/all functions within the file, anywhere in your application.
I was going through socialite tutorial which is created by Laravel 5 and I'm using Laravel 5.1 and I saw that there is a file in tutorial like AuthenticateUser.php in repositories folder. But repositories folder doesn't even exist in Laravel 5.1. Where I should create a file AuthenticateUser.php in Laravel 5.1?
Laravel uses composer's autoloading, so it doesn't matter where you store your files, so long as their autoloading mechanism is defined in the composer.json file. Laravel 5 apps start with this defined in their composer.json:
"psr-4": {
"App\\": "app/"
}
So if you created a directory at app/Repositories, you could create a file in it that looked like this:
<?php namespace App\Repositories;
class MyRepository {
public function doSomething() {}
}
Then you can reference it in the rest of your application like this:
<?php namespace App\Http\Controllers;
use App\Repositories\MyRepository;
use Illuminate\Routing\Controller as BaseController;
FooController {
protected $repo;
public function __construct(MyRepository $repo)
{
$this->repo = $repo;
}
public function someAction()
{
return $this->repo->doSomething();
}
}
Composer will load the file for you, so long as you've defined a mechanism for doing so.
When using a separate class for a model observer, where exactly should I register the observer? The documentation says to call User::observe(new UserObserver); but I’m not sure where the best place to do this would be.
https://laravel.com/docs/5.4/eloquent#observers
Since an observer is just a collection of events you are listening to, I'd say place it where Laravel suggests you place individual events: on the boot method of the model itself.
class User extends Eloquent
{
public static function boot()
{
parent::boot();
User::observe(new UserObserver);
}
}
Where to put the UserObserver class is a little more flexible and depends on how complex it will end up being.
For simple observers
If you can bare having it load every time the app runs, create an app/observers.php file, then put this at the end of your app/start/global.php:
require app_path().'/observers.php';
Alternatively, you can use composer to autoload that one file, by appending your composer.json:
{
"autoload": {
"classmap": [
//...
],
"files": [
"app/observers.php"
]
}
}
For more complex observers
If you plan to have many different observers, I'd say create your own namespace and let Laravel / Composer do the autoloading for you. In order to do that, create a folder like app/MyNamespace/Observers, then place each observer file inside of it (each named exactly like the class -- i.e. UserObserver.php).
Your UserObserver.php class should now look like this:
<?php
namespace MyNamespace\Observers;
class UserObserver
{
public function saving($model)
{
// ...
}
public function saved($model)
{
// ...
}
}
And you'll have to declare the full class whenever you are using it:
User::observe(new MyNamespace\Observers\UserObserver);
Or:
use MyNamespace\Observers\UserObserver;
class User extends Eloquent
{
public static function boot()
{
parent::boot();
User::observe(new UserObserver);
}
}
Finally, edit your composer.json and add your namespace to follow PSR-0 autoloading:
{
"autoload": {
"classmap": [
//...
],
"psr-0": [
"MyNamespace": "app/"
]
}
}
PS: Don't forget to run composer dump-autoload after editing composer.json.
I am a newb learning laravel 4. I want to override specific helper functions. Or add new functions to Url, Str etc. How to do this?
Depending on what part of Laravel you want to extend or replace, there are different approaches.
Macros
Adding functions to Str is really easy, because of "macros":
Here's a short example for adding function:
Str::macro('test', function($str) {
return 'Testing: ' . $str . '!';
});
You can then call this function as expected:
echo Str::test('text'); // Outputs "Testing: text!"
Adding functions using macros are supported by Str, Form, HTML and Response.
IOC Based Extension
To extend URL one must use the IOC of Laravel. This is explained in the docs (as mentioned by BenjaminRH). I agree it can be a bit hard to understand. Here's a step-by-step to extend URL:
Create folder app/lib to hold your extension classes.
Add this folder to autoloading:
In app/start/global.php, append the lib path to the class loader:
ClassLoader::addDirectories(array(
app_path().'/commands',
app_path().'/controllers',
app_path().'/models',
app_path().'/database/seeds',
app_path().'/lib'
));
Then add the path to composer.json classmap:
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php",
"app/lib"
]
},
Create the custom UrlGenerator app/lib/CustomUrlGenerator.php:
<?php
use \Illuminate\Routing\UrlGenerator;
class CustomUrlGenerator extends UrlGenerator
{
public function test()
{
return $this->to('/test');
}
}
Create a service provider app/lib/CustomRoutingServiceProvider.php:
<?php
use \Illuminate\Routing\RoutingServiceProvider;
class CustomRoutingServiceProvider extends RoutingServiceProvider
{
public function boot()
{
App::bind('url', function()
{
return new CustomUrlGenerator(
App::make('router')->getRoutes(),
App::make('request')
);
});
parent::boot();
}
}
Register the service provider in app/config/app.php:
Add CustomRoutingServiceProvider to the providers array.
For example, right after the Workbench provider:
'Illuminate\Workbench\WorkbenchServiceProvider',
'CustomRoutingServiceProvider',
Run composer dump-autoload from project root folder.
Done. Use like:
URL::test();
NOTE The code is tested, but may contain some errors
Interesting that you should mention this, actually. A whole documentation section was just recently added, which covers this in detail. It's very clear, and easy to understand. If you've been using Laravel at all, it might not even surprise you that Laravel actually provides an extend method for a lot of core components.
Following Fnatte's answer, today's versions of Laravel do some extra processing in the url binding. Redefining the whole binding is no longer a practical option.
Here is how I ended up for extending the URL facade.
First, create your child class using this boilerplate:
use Illuminate\Routing\UrlGenerator;
class YourUrlGenerator extends UrlGenerator {
public function __construct(UrlGenerator $url)
{
parent::__construct($url->routes, $url->request);
}
// redefine or add new methods here
}
Then, add this in a ServiceProvider:
$url = $this->app['url'];
$this->app->singleton('url', function() use ($url)
{
return new YourUrlGenerator($url);
});
The point is simply that the original url binding should be executed at least once before we override it with our own.