This is how I create helper (App\Helpers\Settings.php)
namespace App\Helpers;
use Illuminate\Database\Eloquent\Model;
class Settings {
protected $settings = [];
public function __construct() {
$this->settings['AppName'] = 'Test';
}
/**
* Fetch all values
*
* #return mixed
*/
public function getAll () {
return $this->settings;
}
}
Creating facade (App\Helpers\Facades\SettingsFacade.php)
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Settings extends Facade {
protected static function getFacadeAccessor() {
return 'Settings';
}
}
Creating Service Provider (App\Providers\SettingsServiceProvider.php)
namespace App\Providers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\ServiceProvider;
class SettingsServiceProvider extends ServiceProvider {
/**
* Bootstrap the application events.
*
* #return void
*/
public function boot() {
}
/**
* Register the service provider.
*
* #return void
*/
public function register() {
App::bind( 'Settings', function () {
return new \App\Helpers\Settings;
});
} */
}
Registering provider (App\Providers\SettingsServiceProvider::class)
Creating alias: 'Settings' => App\Facades\Settings::class
Running composer dump-autoload
Trying to use facade Settings::getAll();
Getting error Class 'App\Http\Controllers\Settings' not found
Can’t figure out why I cannot create facade and getting that error
try this one.
App\Helpers\Settings.php
namespace App\Helpers;
use Illuminate\Database\Eloquent\Model;
class Settings {
protected $settings = [];
public function __construct() {
$this->settings['AppName'] = 'Test';
}
/**
* Fetch all values
*
* #return mixed
*/
public function getAll () {
return $this->settings;
}
}
App/Http/Controllers/XyzController.php
use Facades\App\Settings;
class XyzController extends Controller
{
public function showView()
{
return Settings::getAll();
}
}
web.php
Route::get('/','XyzController#showView');
use Facades\App\Helpers\Settings;
Route::get('/direct',function() {
return Settings::getAll();
});
use laravel Real time facades
Related
I have a StripeClient service provider which needs a key to instantiate:-
namespace App\Providers;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
use Stripe\StripeClient;
class StripeServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->singleton(StripeClient::class, function ($app) {
return new StripeClient(config('services.stripe.secret'));
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return [StripeClient::class];
}
Then a trait with a bunch of api call functions like this:-
trait StripeClientTrait
{
protected $stripe;
function __construct(StripeClient $stripeClient)
{
$this->stripe = $stripeClient;
}
/**
* #param User $user
*
* #return \Stripe\Customer
* #throws \Stripe\Exception\ApiErrorException
*/
function createCustomer(User $user)
{
return $this->stripe->customers->create([ 'name' => $user->fullname,
'email' => $user->email
]);
}
...
The trait works in a controller perfectly as expected:-
class SubscriptionContoller extends Controller
{
use StripeClientTrait;
public function checkout()
{
try {
$customer = $this->createCustomer(Auth::user());
if($checkoutSession = $this->createCheckoutSession($customer)) {
return redirect($checkoutSession->url);
}
} catch (ApiErrorException $ex){
Log::error($ex->getMessage());
return back()->with(['error'=>$ex->getMessage()]);
}
return back();
}
...
But I now need to use the trait in a model to provide access to some api functions.
class Company extends Tenant
{
use HasFactory, StripeClientTrait;
but adding the trait causes:-
Too few arguments to function App\Models\Company::__construct(), 0 passed in /home/vagrant/code/profiler/vendor/spatie/laravel-multitenancy/src/Models/Concerns/UsesTenantModel.php on line 13 and exactly 1 expected
Can anyone tell me how to implement the trait without using the constructor? I just need some static function helpers to lookup stuff on the API.
Thanks for any guidance :-)
having persevered I've found this way to use the service container in a model:-
public function getPrices()
{
$stripe = app(StripeClient::class);
return $stripe->prices->all(['active'=>true]);
}
But would still like to understand how to use the trait in the model, if anyone could explain I'd be grateful
Laravel CQRS
I am applying CQRS in Laravel just to learn how to use it.
I created a simple user registration and a controller that creates a command to dispatch the handle and use the right use case.
When Trying to use the interface in the controller, it looks like that I need to bind the interface and the implementation because it doesn't know which one to use but in this case I don't really understand how to bind the interface.
CreateUserController.php
<?php
declare(strict_types=1);
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\Users\CreateUserRequest;
use Illuminate\Http\RedirectResponse;
class CreateUserController extends Controller
{
public function __construct(private \Src\User\Infrastructure\CreateUserController $userController)
{
}
public function __invoke(CreateUserRequest $request): RedirectResponse
{
$this->userController->__invoke($request);
return redirect()->route('verify');
}
}
Src\User\Infrastructure\CreateUserController
<?php
declare(strict_types=1);
namespace Src\User\Infrastructure;
use App\Http\Requests\Users\CreateUserRequest;
use Src\Shared\Domain\Bus\Command\CommandBus;
use Src\User\Application\Create\CreateUserCommand;
final class CreateUserController
{
public function __construct(private CommandBus $commandBus)
{
}
public function __invoke(CreateUserRequest $request)
{
$name = $request->name;
$email = $request->email;
$password = $request->password;
$command = new CreateUserCommand($name, $email, $password);
$this->commandBus->dispatch($command);
}
}
CommandBus
<?php
declare(strict_types=1);
namespace Src\Shared\Domain\Bus\Command;
interface CommandBus
{
public function dispatch(Command $command): void;
}
Command
<?php
declare(strict_types=1);
namespace Src\Shared\Domain\Bus\Command;
interface Command
{
}
CreateUserCommandHandler
<?php
declare(strict_types=1);
namespace Src\User\Application\Create;
use Src\User\Domain\ValueObjects\UserEmail;
use Src\User\Domain\ValueObjects\UserName;
use Src\User\Domain\ValueObjects\UserPassword;
final class CreateUserCommandHandler
{
public function __construct(
private UserCreator $creator
)
{
}
public function __invoke(CreateUserCommand $command)
{
$name = new UserName($command->name());
$email = new UserEmail($command->email());
$password = new UserPassword($command->password());
$this->creator->__invoke($name, $email, $password);
}
}
The Error
I tried this:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Src\Shared\Domain\Bus\Command\Command;
use Src\User\Application\Create\CreateUserCommand;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(
Command::class,
CreateUserCommand::class
);
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
}
Here is how you can bind with the interface.
Create a class in app/Providers folder. You can give any name to this class. Eg. InterfaceServiceProvider. extends it with Illuminate\Support\ServiceProvider
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class InterfaceServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
$this->app->bind(YourInterFace::class, YourController::class);
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
Add this InterfaceServiceProvider in config/app.php in providers array
Eg.
'providers' => [
App\Providers\InterfaceServiceProvider::class,
]
I want to make a Collection macro function in the service provider.
The problem is after importing the Collection class i can not access the collection funtion $this->values()
But when I use the same code in the controller is working fine.
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Collection;
class CollectionExtensions extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
Collection::macro('transpose', function () {
$items = array_map(function (...$items) {
return $items;
}, ...$this->values());
return new static($items);
});
}
}
i have below contract/interface which is binded by a service provider ,however the i get below error :
ReflectionException in RouteDependencyResolverTrait.php line 81:
Class App\Http\Controllers\RocketShipContract does not exist
What am i doing wrong ?
Contract
namespace App\Contracts\Helpers;
Interface RocketShipContract
{
public function blastOff();
}
The concrete class
namespace app\Contracts;
use App\Contracts\Helpers\RocketShipContract;
class RocketShip implements RocketShipContract
{
public function blastOff()
{
return 'Houston, we have ignition';
}
}
The service provider
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Contracts\RocketShip;
class RocketShipServiceProvider extends ServiceProvider
{
protected $defer = true;
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->bind('App\Contracts\Helpers\RocketShipContract', function($app){
return new App\Contracts\RocketShip($app['HttpClient']);
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return ['App\Contracts\Helpers\RocketShipContract'];
}
}
The controller
public function test(RocketShipContract $rocketship)
{
$boom = $rocketship->blastOff();
return view('test.index', compact('boom'));
}
The error you're getting hints at the problem: the class is being resolved in the App\Http\Controllers namespace. That's because you need to specify the full namespace of your interface in the controller.
So either include it with a use statement:
use App\Contracts\Helpers\RocketShipContract;
Or type hint the full namespace:
public function test(App\Contracts\Helpers\RocketShipContract $rocketship)
{
// ...
}
I am implementing a repository pattern in Laravel, and it seems to be very tedious. For example, let's say I have products then I have to create a ProductRepository interface then a ProductRepository class that implements that interface, now I have some very generic methods on the ProductRepository like:
retrieveAll
store
update
delete
And now I have to do the same thing for ingredients. It would be nice if I could simply create a ModelRepository interface with all those generic methods and implement it by passing a generic data type (namely the model), something similar to Java Generics:
<?php
interface ModelRepositoryInterface<T> {
function retrieveAll(): Collection<T>;
function store(T $item);
function update(int $id, T $data);
function delete(int $id);
}
But since php doesn't support generics how can I achieve this simplicity?
You can create a RepositoryServiceProvider to bind your repository interfaces to actual classes.
You can create a abstract Repository class with retrieveAll, store, update, delete and extend your Repositories and implement the interface. I have included below example with magic functions to be able to eloquent methods if I don't have any customization.
The below is not tested but its just to get the idea.
<?php
namespace App\Repositories;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
abstract class AbstractRepository implements RepositoryInterface
{
/**
* #var Builder|Model
*/
protected $model;
/**
* #return mixed
*/
public function getModel()
{
return $this->model;
}
/**
* #param array $columns
* #return \Illuminate\Database\Eloquent\Collection|Model[]
*/
public function all($columns = ['*'])
{
return $this->model->all($columns);
}
/**
* #param $name
* #param $arguments
* #return mixed
*/
public function __call($name, $arguments)
{
return $this->model->{$name}($arguments);
}
}
OrderRepository
<?php
namespace App\Repositories;
use App\Models\Order;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
class OrderRepository extends AbstractRepository implements OrderRepositoryInterface
{
/**
* OrderRepository constructor.
* #param Order $model
*/
public function __construct(Order $model)
{
$this->model = $model;
}
public function countPaid(): int
{
return $this->model->paid()->count();
}
/**
* #return int
*/
public function countReady(): int
{
return $this->model->ready()->count();
}
/**
* #return int
*/
public function countCancelled(): int
{
return $this->model->cancelled()->count();
}
}
OrderRepositoryInterface
<?php
namespace App\Repositories;
interface OrderRepositoryInterface
{
}
RepositoryServiceProvider
<?php
namespace App\Providers;
use App\Repositories\OrderRepository;
use App\Repositories\OrderRepositoryInterface;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(OrderRepositoryInterface::class, OrderRepository::class);
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
}
RepositoryInterface
<?php
namespace App\Repositories;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
interface RepositoryInterface
{
function retrieveAll(): Collection;
function store(Model $item);
function update(int $id, Model $data);
function delete(int $id);
}