i am using design patterns repository and i wrote every thing coorect but i have an error returns
Target [App\Repository\categoryRepositoryInterface] is not instantiable while building [App\Http\Controllers\CategoryController]. i dont know why although i wrote every thing correct please help
here is my code
my config/app
App\Providers\RepositoryServiceProvider::class,
and my categorycontroller
<?php
namespace App\Http\Controllers;
use App\Repository\categoryRepositoryInterface;
use Illuminate\Http\Request;
class CategoryController extends Controller
{
private categoryRepositoryInterface $categoryRepository;
public function __construct(categoryRepositoryInterface $categoryRepository)
{
$this->categoryRepository = $categoryRepository;
}
and my repositoryinterface
<?php
namespace App\Repository;
use Illuminate\Http\Request;
interface categoryRepositoryInterface
{
public function createCategory(Request $request);
public function validation(Request $request);
}
and my category repository
<?php
namespace App\Repository;
use App\Models\Category;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class categoryRepository implements categoryRepositoryInterface{
public function validation(Request $request){
$validation = Validator::make($request->all(),[
'name' => 'required',
]);
if($validation->fails()){
return response()->json([
'status' => 400,
'errors' => $validation->errors(),
]);
}
}
public function createCategory(Request $request)
{
$category = new Category();
$category->name = $request->name;
$category->save();
}
}
and my servicerepositoryprovider
<?php
namespace App\Providers;
use App\Repository\CategoryRepository;
use App\Repository\CategoryRepositoryInterface;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
$this->app->bind(CategoryRepositoryInterface::class, CategoryRepository::class);
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
You have typos in your RepositoryServiceProvier
use App\Repository\categoryRepository; //First alphabet should be lower case
use App\Repository\categoryRepositoryInterface; //First alphabet should be lower case
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
//First alphabet should be lower case as per your class and interface names
$this->app->bind(categoryRepositoryInterface::class, categoryRepository::class);
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
Would like to give you a piece of advice. When developing with Laravel it would be easier for you to follow Laravel's naming conventions - Laravel conventions overall. Following conventions will help you better understand examples on the internet as well.
Whatever you decide remember to follow them with consistency. In this particular case you are naming classes in camel case starting with small alphabet so when importing via use statements you need to stick to that.
Related
I'm using Laravel 8 and I'm creating a custom Facade, but I cannot recall it with LogActivity::log($payload) but only with LogActivityFacade::log($payload).
Cannot see where is my fault...
app\Helpers\LogActivityFacade.php
<?php
namespace App\Helpers;
use Illuminate\Support\Facades\Facade;
class LogActivityFacade extends Facade
{
protected static function getFacadeAccessor()
{
return 'logactivity';
}
}
app\Helpers\LogActivityHelper.php
<?php
namespace App\Helpers;
use App\Repositories\LogActivityRepository;
class LogActivityHelper
{
public function log($payload)
{
$repository = new LogActivityRepository();
$repository->store($payload);
}
}
app\Providers\LogActivityServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\Facades\App;
use App\Helpers\LogActivityHelper;
use Illuminate\Support\ServiceProvider;
class LogActivityServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
$this->app->bind('logactivity', function() {
return new LogActivityHelper();
});
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
config/app.php
In providers array
[...]
App\Providers\LogActivityServiceProvider::class,
In alias array
'LogActivity' => App\Helpers\LogActivityFacade::class,
I tried also composer dump-autoload and php artisan config:clear, but I can access to the Facade (and it works...) only with LogActivityFacade::log() instead of LogActivity.
This is the expected behavior. Laravel doesn't create new classes for you it just proxies methods from the service class in the facade using the __call magic method. If you take a peek at, for example, the Auth or Route facade in the vendor directory you will see that they are named Auth and Route respectively not AuthFacade and RouteFacade. So just name your facade LogActivity. If you need to differentiate it from the service class you can use namespacing or just postfix the service class name with something as you have already done.
You can do this for easy access to the facades
namespace App\Facade;
use Illuminate\Support\Facades\Facade;
abstract class BaseFacade extends Facade
{
/**
* #return string
*/
public static function getFacadeAccessor()
{
return static::class ;
}
/**
* #param $class
*/
static function shouldProxyTo($class)
{
app()->singleton(self::getFacadeAccessor(),$class);
}
}
extend other facades
namespace App\Facade\Plugins;
use App\Facade\BaseFacade;
/**
* #method static convertPersianNumberToEnglish($number)
* #method static bool checkDataIsTrue(array $results = [])
* #method static string|null removeFileTypeName(string $string = null)
*/
class GlobalPluginsFacade extends BaseFacade
{
}
register in services provider
public function boot()
{
// global facades
GlobalPluginsFacade::shouldProxyTo(GlobalPluginsRepo::class);
}
And easy to use.
GlobalPluginsFacade::getFunction();
In laravel 6 app I created facade app/Facades/MyFuncsClass.php :
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class MyFuncsClass extends Facade{
protected static function getFacadeAccessor() { return 'MyFuncsClass'; }
}
But I got error :
"message": "Non-static method App\\Helpers\\MyFuncsClass::debToFile() should not be called
statically",
calling it from boot method:
protected static function boot() {
parent::boot();
static::deleting(function($task) {
$hostel_image_image_path= Task::getTaskImagePath($task->id, $task->image);
MyFuncsClass::debToFile(print_r($hostel_image_image_path, true), '-9 $hostel_image_image_path::');
...
Is there is a way to escape this error and run MyFuncsClass::debToFile in boot method ?
MODIFIED :
Sure I registered my facade in config/app.php, 'providers' block :
...
App\Providers\MyFuncsClassProvider::class,
file app/Http/Helpers/MyFuncsClass.php has a lot of public methods, with heading:
<?php
namespace App\Helpers;
use Illuminate\Http\Request;
use Barryvdh\Debugbar\Facade as Debugbar;
use Carbon\Carbon;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
class MyFuncsClass {
public $concat_str_max_length = 50;
public $m_concat_str_add_chars = '...';
public function debToFile($contents, string $descr_text = '', bool $is_sql = false, string $file_name = '')
{
try {
...
and in app/Providers/MyFuncsClassProvider.php :
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
class MyFuncsClassProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
App::bind('MyFuncsClass', function()
{
return new \App\Helpers\MyFuncsClass;
});
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
Actually I can call \MyFuncsClass::debToFile( ok from not static methods, like control actions, but I have the error
calling from static boot method...
MODIFIED # 2 :
With real time facades https://laravel.com/docs/5.7/facades#real-time-facades defintions
I tried
<?php
namespace App;
use DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use App\Facades\MyFuncsClass;
use App\Http\Helpers\MyFuncsClassContainer; // Alias for my helper class
use Illuminate\Database\Eloquent\Model;
use Barryvdh\Debugbar\Facade as Debugbar;
class Task extends Model
{
use Sluggable;
protected $table = 'tasks';
protected $primaryKey = 'id';
}
protected static function boot() {
parent::boot();
static::deleting(function($task) {
$hostel_image_image_path= Task::getTaskImagePath($task->id, $task->image);
\Log::info( '-9 $hostel_image_image_path::' );
\Log::info( print_r($hostel_image_image_path, true) );
$myFuncsClassCore = factory(MyFuncsClassContainer::class)->create();
$myFuncsClassCore->debToFile(' debToFile string REDSA');
Bur anywat I got error :
Cannot declare class App\Helpers\MyFuncsClassContainer, because the name is already in use {"userId":1,"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalErrorException
I tried a way to rename my helper class to “MyFuncsClassContainer”, supposing
having the same name for helper and facade could raise error, but failed
If there is a way to fix this error ?
Thanks!
I'd like to share data with all views via the AppServiceProvider. Moreover, I'd like to check the guard type first to give some specific output for each user type.
I tried to check the guard in AppServiceProvider via Auth::guard('admin')->check() but it returns false. However, the same if statement works perfectly in my Controllers.
I've also included Illuminate\Support\Facades\Auth and Illuminate\Support\Facades\View.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\View;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
if (Auth::guard('admin')->check()) {
// Share data with views
}
}
}
The if statement returns false, although I'm logged in as admin.
you need view composer for this.
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Auth;
use DB;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
view()->composer('*', function ($view)
{
if (Auth::guard('admin')->check()) {
}
});
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
If you want to pass data in views.
view()->composer('*', function ($view)
{
if (Auth::guard('admin')->check()) {
$admin = DB::table('admins')->first(); // for example
$view->with(compact('admin'));
}
});
I'm trying to apply a sort of "repository-pattern" to a custom service.
What I'd like to do is to actually bind this library to my custom service provider to create an abstraction layer and, eventually, switch that library with another one in the future.
I'm trying to move the 'providers' and 'aliases' references from config/app.php to my service provider, but I get a Class 'GoogleMaps' not found error.
I've added App\Providers\GeoServiceProvider::class to config/app.php providers array and this is my relevant code:
GeoServiceProvider.php(my custom service provider)
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class GeoServiceProvider extends ServiceProvider
{
/** * Register services.
*
* #return void
*/
public function register()
{
$this->app->bind(\App\Interfaces\GeoInterface::class, \App\Services\GoogleGeoService::class);
$this->app->alias(\GoogleMaps\Facade\GoogleMapsFacade::class, 'GoogleMaps');
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
}
}
GeoInterface.phpinterface defining standard methods
<?php
namespace App\Interfaces;
interface GeoInterface
{
public function geoCode();
}
GoogleGeoService.php(The actual library implementation)
<?php
namespace App\Services;
use App\Interfaces\GeoInterface;
class GoogleGeoService implements GeoInterface
{
public function geoCode()
{
$response = \GoogleMaps::load( 'geocoding' ) <--- HERE IS WHERE I GET THE ERROR
->setParamByKey( 'latlng', "45.41760620,11.90208370")
->setEndpoint( 'json' )
->get();
$response = json_decode($response, true);
return $response;
}
}
TestController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Interfaces\GeoInterface;
class TestController extends Controller
{
protected $geoService;
public function __construct(GeoInterface $geoService) {
$this->geoService = $geoService;
}
public function index() {
return $this->geoService->geoCode();
}
}
Thank you,
Alex
Here is my validation service provider.
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\Validation\CustomValidation;
class ValidationServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
// We don't have to register anything here so we keep this empty!
}
/**
* Boot the service provider.
*/
public function boot()
{
// Need to override the default validator with our own validator
// We can do that by using the resolver function
$this->app->validator->resolver(function ($translator, $data, $rules, $messages) {
// This class will hold all our custom validations
return new CustomValidation($translator, $data, $rules, $messages);
});
}
}
Here is the custom validation class that extends Laravel validator class. I am confusing around where should I write my error messages for the custom rule. I could find any documentation for it.
<?php namespace App\Services\Validation;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Validator;
class CustomValidation extends Validator
{
/**
* $attribute Input name
* $value Input value
* $parameters Table, field1
*/
public function validateCustomRule($attribute, $value, $parameters)
{
// Logic to be written later
return false;
}
}
Have you tried adding them to the validation language file using the same convention? 'custom_rule' => 'Some message'