Hello I have created a new Package for a Laravel project I am working on, I am new to the concept of packages and laravel itself, but here is the code I have come up with,
/workbench/cycs/proofhq/src/Cycs/Proofhq/ProofhqServiceProvider.php
public function boot()
{
$this->package('cycs/proofhq');
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app->booting(function()
{
$loader = \Illuminate\Foundation\AliasLoader::getInstance();
$loader->alias('Cycs', 'Cycs\Proofhq\Facades\Supyo');
});
$this->app['proofhq'] = $this->app->share(function($app)
{
return new Proofhq;
});
}
/workbench/cycs/proofhq/src/Cycs/Proofhq/Proofhq.php
<?php namespace Cycs\Proofhq;
class Proofhq {
public static function greeting() {
return "What's up dawg!";
}
}
/workbench/cycs/proofhq/src/Cycs/Proofhq/Facades/Proofhq.php
<?php namespace Cycs\Proofhq\Facades;
use Illuminate\Support\Facades\Facade;
class Proofhq extends Facade {
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor() {
return 'proofhq';
}
}
I have added the package to the app/config/app.php and the providers array, then try to access the package functions via a simple get,
Route::get('/test', function(){
echo proofhq::greeting();
});
But I get the following error,
Class 'proofhq' not found
I cannot work out why, I have followed the examples to the letter, and the class exists.
Can anyone shed anylight on this for me?
composer dump-autoload and change the class name first letter in the routes to uppercase seems to do the trick!
Related
I know there are so many answer, but I cannot really solve this.
I did follow this answer (How to make a REST API first web application in Laravel) to create a Repository/Gateway Pattern on Laravel 5.7
I have also the "project" on github, if someone really kindly want test/clone/see : https://github.com/sineverba/domotic-panel/tree/development (development branch)
App\Interfaces\LanInterface
<?php
/**
* Interface for LAN models operation.
*/
namespace App\Interfaces;
interface LanInterface
{
public function getAll();
}
App\Providers\ServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
/**
* Solve the "Key too long" issue
*
* #see https://laravel-news.com/laravel-5-4-key-too-long-error
*/
Schema::defaultStringLength(191);
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->register(RepositoryServiceProvider::class);
}
}
App\Providers\RepositoryServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(
'app\Interfaces\LanInterface', // Interface
'app\Repositories\LanRepository' // Eloquent
);
}
}
App\Gateways\LanGateway
<?php
/**
* The gateway talks with Repository
*/
namespace App\Gateways;
use App\Interfaces\LanInterface;
class LanGateway
{
protected $lan_interface;
public function __construct(LanInterface $lan_interface) {
$this->lan_interface = $lan_interface;
}
public function getAll()
{
return $this->lan_interface->getAll();
}
}
App\Repositories\LanRepository
<?php
/**
* Repository for LAN object.
* PRG paradigma, instead of "User"-like class Model
*/
namespace App\Repositories;
use App\Interfaces\LanInterface;
use Illuminate\Database\Eloquent\Model;
class LanRepository extends Model implements LanInterface
{
protected $table = "lans";
public function getAll()
{
return 'bla';
}
}
I did add also App\Providers\RepositoryServiceProvider::class, in providers section of config\app.php
This is finally the controller (I know that it is not complete):
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Gateways\LanGateway;
class LanController extends Controller
{
private $lan_gateway;
/**
* Use the middleware
*
* #return void
*/
public function __construct(LanGateway $lan_gateway)
{
$this->middleware('auth');
$this->lan_gateway = $lan_gateway;
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
$this->lan_gateway->getAll();
return view('v110.pages.lan');
}
}
And the error that I get is
Target [App\Interfaces\LanInterface] is not instantiable while building [App\Http\Controllers\LanController, App\Gateways\LanGateway].
I did try:
php artisan config:clear
php artisan clear-compiled
I think #nakov might be right about it being case-sensitive. I don't believe PHP itself cares about upper/lowercase namespaces, but the composer autoloader and the Laravel container use key->value array keys, which do have case-sensitive keys, to bind and retrieve classes from the container.
To ensure the names always match, try using the special ::class constant instead, like this:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Repositories\LanRepository;
use App\Interfaces\LanInterface;
class RepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(
LanInterface::class,
LanRepository::class
);
}
}
In my case i forgot to enlist the provider to confit/app.php that's why the error.
Clear the old boostrap/cache/compiled.php:
php artisan clear-compiled
Recreate boostrap/cache/compiled.php:
php artisan optimize
I've created a CustomProvider, added it to the app.php array of providers and registered a class as singleton:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\ReserveCart;
class CustomProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register services.
*
* #return void
*/
public function register()
{
$this->app->singleton('App\ReserveCart', function($app){
return new ReserveCart;
});
}
}
but everytime I request for the object with $rc = resolve('App\ReserveCart'); it keeps giving me different instances of the object instead of a single one (I've done some echo tracking).
Also tried passing the dependency to methods acording to Laravel Documentation. e.g
public function foo(App\ReserveCart $rc){
//
}
but the issue persists.
Is the output below same ?
$rc = resolve('App\ReserveCart');
$rc1 = resolve('App\ReserveCart');
dd(spl_object_hash($rc), spl_object_hash($rc1));
I have App\Http\NotificationComposer.php:
namespace App\Http\ViewComposers;
use Illuminate\View\View;
class NotificationComposer
{
public $notifications;
public function __construct(){
$this->notifications = json_decode(\Auth::user()->notifications, true);
}
public function compose (View $view)
{
dd($this->notifications);
$view->with('notifications');
}
}
I also have a App\Providers\ComposerServiceProvider.php:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
view()->composer(
'app',
'App\Http\ViewComposers\NotificationComposer'
);
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
And in my config\app.php:
'providers' => [
...
App\Providers\ComposerServiceProvider::class,
...
],
];
I believe I have set up the view composer correctly, however everytime layouts\app.blade.php is loaded (the default bootstrap bar in laravel) it isn't rendering any notifications, even though there are some in the database, I have attempted to dd them as you can see in the view composer.
Does anyone have any ideas why this might be happening or what I haven't done properly?
Thanks,
Ok I've made a workaround instead. This wasn't registering for some reason so I place this inside of the AppServiceProivder.php
view()->composer(
'layouts.app', function ($view){
$view->with('notifications', json_decode(\Auth::user()->notifications, true));
});
It's not as clean but for something this small, I guess it's ok.
Case (L5.4)
Currently trying to write an api wrapper using the package development Laravel offers.
I got a ServiceProvider which binds the model (Niki::class)
class NikiServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
$this->publishes([
__DIR__ . '/config/niki.php' => config_path('niki.php'),
]);
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->bind('niki', function () {
return new Niki;
});
}
}
A Facade which registers the name of the component
class Facade extends \Illuminate\Support\Facades\Facade
{
/**
* Get the registered name of the component.
*
* #return string
*/
public static function getFacadeAccessor()
{
return 'niki';
}
}
And a model
class Niki extends Model
{
/**
* Config
*
* #var array
*/
public function __construct()
{
$this->config = config('niki')['api_key'];
}
public static function getHouses()
{
$response = $this->config;
return $response;
}
}
Above files are located in packages/prsc/niki/src and are being loaded using the psr-4 autoloading:
"psr-4": {
"App\\": "app/",
"PRSC\\Niki\\": "packages/prsc/niki/src/"
},
Error
So now my problem, the bind in the ServiceProvider returns a FatalError because of the file not being found.
FatalThrowableError in NikiServiceProvider.php line 37: Class
'PRSC\Niki' not found
I think it's just a namespace problem. I'm not sure I have all the clue about your namespaces, but here is something that should work (if I did not misunderstood):
Replace:
return new Niki;
By:
return new \PRSC\Niki\Niki;
If it does not work, please add your namespaces in each code snippet you pasted.
I'm making a Laravel ServiceProvider for a package.
The package is https://github.com/sumocoders/Teamleader
I get the following error
FatalErrorException in ProviderRepository.php line 150:
Class 'Notflip\Teamleader\TeamleaderServiceProvider' not found
I have no clue what I'm doing wrong, Here's my folder structure
composer.json in my package
"autoload": {
"psr-4": {
"Notflip\\Teamleader": "src/"
}
}
TeamleaderServiceProvider
<?php namespace Teamleader\Laravel;
use Illuminate\Support\ServiceProvider;
class TeamleaderServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* #return void
*/
public function publishes()
{
$this->publishes([
__DIR__.'/Config/config.php' => config_path('teamleader.php'),
]);
}
public function register()
{
$this->app->bind('Teamleader\Laravel', function () {
return new Teamleader(config('teamleader.API_GROUP'), config('teamleader.API_SECRET'), config('teamleader.SSL'));
});
}
}
Facade
<?php namespace Teamleader\Laravel\Facade;
class Teamleader extends Facade
{
protected static function getFacadeAccessor()
{
return 'Teamleader';
}
}
In my config.php I added the following line to the providers
'Notflip\Teamleader\TeamleaderServiceProvider',
And this line to the aliasses
'Teamleader'=> 'Notflip\Teamleader\Facade\Teamleader'
Anyone has any idea what I might be doing wrong? Thank you! I'm so close to the result!
Your definition in composer is missing the initial slashes and you haven't specified the path to src from root.
"psr-4": {
"\\Notflip\\Teamleader": "notflip/teamleader-laravel/src/"
}
Also your declaration of the name space at the top of TeamleaderServiceProvider is wrong, it should be:
<?php namespace Notflip\Teamleader;
Solved
In the facade, the IOC binding was named wrong ( wrong case )
The name should have been 'teamleader' in lowercase.
Facade
class Teamleader extends Facade
{
protected static function getFacadeAccessor()
{
return 'teamleader';
}
}
Service Provider
<?php namespace Teamleader\Laravel;
use Illuminate\Support\ServiceProvider;
class TeamleaderServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* #return void
*/
public function publishes()
{
$this->publishes([
__DIR__.'/Config/config.php' => config_path('teamleader.php'),
]);
}
public function register()
{
$this->app->bind('teamleader', function () {
return new Teamleader(config('teamleader.API_GROUP'), config('teamleader.API_SECRET'), config('teamleader.SSL'));
});
}
}