Exact place to register observer in Laravel 4 - laravel

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.

Related

How to fetch data from table in model in larvel framework and directly use in view?

I have created a model like below
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class countData extends Model
{
//
public function countAbc () {
// i don't know how to write in laravel query so for understanding purpose i wrote in simple pg query
$sql=pg_query("select count(*) as countrow from s_abc");
$countfetch=pg_fetch_array($sql);
return $countfetch[0];
}
}
I don't have any route for this function. On view page I am check
#if( $Item->ClassID == 'abc' )
{
//then call the above model and use countAbc () function
countAbc();
}
Basically my view is already loaded, I need to check the condition and call the above model to count the data.
I think you're looking for helper function.
In question you've created countAbc() function and you want to call it everywhere.
Use to make function in helpers.php file instead of model file
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
Afterward, put your this function in helpers.php
public function countAbc () {
$sql=pg_query("select count(*) as countrow from s_abc");
$countfetch=pg_fetch_array($sql);
return $countfetch[0];
}
Now, You can access it anywhere.
public function countAbc () {
$counts_abc = \DB::table('s_abc')->count();
return $counts_abc;
}
Create a model that corresponds to the table:
php artisan make:model Sabc
Open that model file, and set the table name:
protected $table = 's_abc';
If you want to get the count of the amount of rows within your table that corresponds to the model, it's simple:
Sabc::count();
First Of All I think you have to look Laravel Framework structure: Laravel Directory Structure And contents inside it.
Basically you don't have to define route to fetch data from database.
You have to define model properly - long story short every table in your database have to have one model in your app.
You have tablse s_abc You have to define model SAbc.
php artisan make:model SAbc - this command will make model for you.
After that you can use Eloquent aggregate functions to get count or you can write your own method in it:
Using Aggregate function:
...
use App\SAbc;
...
class SomeClass {
...
$count_sabc = SAbc::count();
...
}
...
Using Your Own Method
In your model write:
...
class SAbc extends Model {
public function getCount() {
return self::count();
// Or with raw query
// return self::selectRaw('count(*) as count')->first()->count
}
}
...
// Then you can use this methd anywhere you want like that:
(new SAbc)->getCount();
Hope this helps you

How to autoload service namespace in laravel 5.6

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');

Laravel global function

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.

Where are Laravel 5.1 Repositories?

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.

Laravel 4 Aliases in custom classes

i want to use the alias classes on laravel 4 "facades" like App::method , Config::method.
Well the thing is that i create a custom class and i have to import the namespaces like
<?php
namespace Face\SocialHandlers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
class FacebookHandler implements SocialHandlerInterface {
public function registrar($perfil) {
Config::get('facebook');
}
}
is there any way to use those classes like in controllers or routes files of the framework ?
like
<?php
namespace Face\SocialHandlers;
//use Illuminate\Support\Facades\App;
//use Illuminate\Support\Facades\Config;
class FacebookHandler implements SocialHandlerInterface {
public function registrar($perfil) {
Config::get('facebook');
}
}
Cya
ps: sry for my english
You can use use Config; instead of the more verbose use Illuminate\Support\Facades\Config; and the autoloader should handle it correctly.
Just as a tip, you shouldn't hardcode dependencies in your code. Instead of using the facades, you could create an "ConfigInterface" to get the common dependencies you need. Then create a "LaravelConfig class" (Or Laravel4Config.php) and implement those methods.
For a Quick Fix Answer, "catch the underliying facade instance":
namespace Face\SocialHandlers;
//use Illuminate\Support\Facades\App;
//use Illuminate\Support\Facades\Config;
class FacebookHandler implements SocialHandlerInterface {
protected $config;
protected $app;
public function __construct()
{
$this->config = \Illuminate\Support\Facades\Config::getFacadeRoot();
$this->app = \Illuminate\Support\Facades\App::getFacadeRoot();
}
public function registrar($perfil) {
$this->config->get('facebook');
}
}
For a Real Answer, maybe tedious, but good in the long run, instead of using the facades use an interface.
interface SocialConfigInterface
{
public function getConfigurationByKey($key)
}
Then
class Laravel4Config implements SocialConfigInterface
{
protected $config;
public function __construct()
{
$this->config = \Illuminate\Support\Facades\Config::getFacadeRoot(); //<-- hard coded, but as expected since it's a class to be used with Laravel 4
}
public function getConfigurationByKey($key)
{
return $this->config->get($key);
}
}
And Your Code
namespace Face\SocialHandlers;
//use Illuminate\Support\Facades\App;
//use Illuminate\Support\Facades\Config;
class FacebookHandler implements SocialHandlerInterface {
protected $config;
public function __construct(SocialConfigInterface $config)
{
$this->config = $config;
}
public function registrar($perfil) {
$this->config->get('facebook');
}
}
This way, if you want to change between frameworks you just need to create a SocialConfigInterface Implementation, or imagine the scenario where Laravel 5 wont use Facades, you want your code to be independent of "outsider changes" this is inversion of control IoC
First run,
php artisan dump-autoload
This will add your class namespace to vendor/composer/autoload_classmap.php. Now locate the entry for your class in this classmap array and get the proper namespace from there.
For example, you will get something like,
'Illuminate\\Support\\Facades\\App' => $vendorDir . '/laravel/framework/src/Illuminate/Support/Facades/App.php',
For this particular entry you have an alias in app/config/app.php
'App' => 'Illuminate\Support\Facades\App',
At the same way, locate your entry and use an alias in app/config/app.php.
You just have to create a folder, or place a class wherever already is listed for autoload. Me, for exemple, have this class PDFMaker, that uses a DomPDF Laravel implementation. I created a folder named libraries and put the path to it (under the app folder) in the autoload:classmap key on composer.json
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/libraries",
"app/models",
"app/helpers",
"app/database/migrations"
]
I did the same with commands for artisan commands! When you do that, you only have to declare a new object for any class under that folder, or call it in a static way, if the class has defined static methods. Something like Class::method.
Hope it helps you, have a nice day! :D
EDIT: After that, don't forget the dump-autoload for placing the new class in autoload scope.
EDIT 2: Remember that once you've put the class on autoload, it will be in same scope the others, so you won't have to import it to other, neither others to it!
You can also prefix the class names with a backslash, to use the global namespace: \Config::get('facebook') and \App::someMethod() will work without the need to add a use statement, regardless of the file's namespace.

Resources