Change functionality of Laravel 4 Guard class - php

I'm trying to write an SSO implementation and for that I need to override some methods such as Auth::check() which are implemented in the Guard class.
I don't understand, however, how to extend that class using service providers. I tried looking in the AuthServiceProvider but there is a whole lot of mumbo jumbo going on I don't understand.

I figured it out! Fairly simple:
<?php
namespace Animekyun\Providers;
use Animekyun\Auth\CustomGuard;
use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Support\ServiceProvider;
class SsoServiceProvider extends ServiceProvider
{
public function boot()
{
\Auth::extend('custom', function () {
return new CustomGuard(
new EloquentUserProvider(
$this->app['hash'],
$this->app['config']['auth.model']),
$this->app['session.store']);
});
}
public function register()
{
}
}
and the CustomGuard class:
<?php
namespace Animekyun\Auth;
use Illuminate\Auth\Guard;
class CustomGuard extends Guard
{
public function check() {
// do some stuff
return parent::check();
}
}

Related

Laravel service provider does not see the main class of my package

I got the service provider and my class for shopping cart.
This is my service provider:
<?php
namespace Alexxosipov\Cart;
use Illuminate\Support\ServiceProvider;
use Alexxosipov\Cart\Cart as Cart;
class CartServiceProvider extends ServiceProvider {
public function boot() {
}
public function register() {
$this->app->singleton('cart', function() {
return new Cart;
});
}
}
but my phpstorm says me, that use Alexxosipov\Cart\Cart as Cart; is never used in code. Where did I go wrong?
According to laravel documentation, you need to type hint the Cart interface:
<?php
namespace Alexxosipov\Cart;
use Illuminate\Support\ServiceProvider;
use Alexxosipov\Cart\Cart as Cart;
class CartServiceProvider extends ServiceProvider {
public function boot() {
}
public function register() {
$this->app->singleton(Cart::class, function() {
return new Cart;
});
}
}

Laravel clean code

I am writing system for players where I use Laravel freamwork (just for learn) and I have question for more experience developer. I have one function which return me some data to view. I use this function in 3 controllers (but i copy and paste this function to each Controller files) and can I just put this function in one file and then use it in these 3 controllers? How can I use the same function in diffrent controller without copy and past?
You can also use Traits to share methods, however, traits are more usually for describing characteristics and types.
You should create a utility class, or use consider an abstract controller class if this is desired.
You can create Base Controller:
<?php
namespace App\Http\Controllers;
class BaseController
{
protected $playersRepository;
public function __construct(PlayersRepository $playersRepository)
{
$this->playersRepository = $playersRepository;
}
}
Which is injected with a repository object:
<?php
namespace App\Http\Controllers;
class PlayersRepository
{
public function getPlayers()
{
return Player::all();
}
}
Which has a common method, that can be used in more than one extended controller:
Games
<?php
namespace App\Http\Controllers;
class Games extends BaseController
{
public function index()
{
return view('games', ['players' => $this->playersRepository->getPlayers()]);
}
}
Matches
<?php
namespace App\Http\Controllers;
class Matches extends BaseController
{
public function show()
{
return view('matches', [
'matches' => $matches,
'players' => $this->playersRepository->getPlayers()
]);
}
}
Create module (util) or override main Controller class.

Laravel, namespaces and PSR-4

I'm trying to set up PSR-4 within a new Laravel 4 application, but I'm getting some troubles achieving what I want when it comes to build controllers.
Here's what I have now :
namespace MyApp\Controllers\Domain;
class DomainController extends \BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = \View::make('domain.home');
}
}
I'm not so fond of using \View, \Config, \Whatever to use Laravel's classes. So I was wondering if I could put a use Illuminate\View; to be able to use View::make without putting a \.
Unfortunately, while doing this, I'm getting the following error : Class 'Illuminate\View' not found.
Could somebody help with this please ?
The problem in your case is that View is not located in Illuminate namespace but in Illuminate\View namespace, so correct import would be not:
use Illuminate\View;
but
use Illuminate\View\View;
You can look at http://laravel.com/api/4.2/ to find out which namespace is correct for class you want to use
Assuming BaseController.php has a namespace of MyApp\Controllers\Domain
namespace MyApp\Controllers\Domain;
use View;
class DomainController extends BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = View::make('domain.home');
}
}
If BaseController.php has other namespace, i.e MyApp\Controllers
namespace MyApp\Controllers\Domain;
use MyApp\Controllers\BaseController;
use View;
class DomainController extends BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = View::make('domain.home');
}
}
If, for instance, you controller needs to use another base class from Laravel, lets say Config.
namespace MyApp\Controllers\Domain;
use MyApp\Controllers\BaseController;
use View;
use Config;
class DomainController extends BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = View::make('domain.home')->withName(Config::get('site.name'));
}
}
The use of View::make() takes advantage of the Laravel facades. To properly reference the facade, instead of directly referencing the class that gets resolved out of the iOC container, I would use the following:
use Illuminate\Support\Facades\View;
This will reference the View facade that is being used when calling View::make()

Target Interface is not instantiable. Laravel 4

When I search the error 'Target Interface is not instantiable' I get a lot of results. Somehow I can still not find the solution to my problem.
I am not sure where it goes wrong.
PartnerController.php
<?php use CmsBlox\MOD\PartnerInterface;
class PartnerController extends BaseController {
public function __construct(PartnerInterface $partner)
{
$this->partner = $partner;
}
public function Get()
{
return "I'm the Get function in class PartnerController";
}
}
PartnerServiceProvider.php
<?php namespace CmsBlox\Providers;
use App, Illuminate\Support\ServiceProvider;
class PartnerServiceProvider extends ServiceProvider {
public function register()
{
}
public function boot()
{
app::bind('CmsBlox\MOD\PartnerInterface') ;
}
}
Routes.php
app::bind('CmsBlox\MOD\PartnerInterface') ;
PartnerInterface.php
<?php namespace CmsBlox\MOD;
interface PartnerInterface {
public function get();
}
I have also added the provider to App.php (for testing also a app::bind() in the routes.php)
'CmsBlox\Providers\PartnerServiceProvider'
As far I know every file should be correct. Somehow I am missing something!
I just found the answer! Thanks to the Laravel.io forums.
<?php use CmsBlox\MOD\PartnerInterface;
class PartnerController extends BaseController implements PartnerInterface {
public function get() {...}
}

Issue with Facade and injected dependency in Laravel 4

I am having an issue getting a Facade to work properly with a dependency injected into the underlying class.
I have a class called 'Listing'. It has one dependency called 'AdvertRepository' which is an interface and a class called EloquentAdvert which implements the interface. The code for these three classes is here:
// PlaneSaleing\Providers\Listing.php
<?php namespace PlaneSaleing\Providers;
use PlaneSaleing\Repositories\Advert\AdvertRepository;
class Listing {
protected $advert;
public function __construct (AdvertRepository $advert_repository) {
$this->advert = $advert_repository;
}
public function test() {
$this->advert->test();
}
public function test2() {
echo "this has worked";
}
}
// PlaneSaleing\Repositories\Advert\AdvertRepository.php
<?php namespace PlaneSaleing\Repositories\Advert;
interface AdvertRepository {
public function test();
}
// PlaneSaleing\Repositories\Advert\EloquentAdvert.php;
<?php namespace PlaneSaleing\Repositories\Advert;
class EloquentAdvert implements AdvertRepository {
public function test() {
echo 'this has worked';
}
}
I have then created a service provider called ListingServiceProvider.php, which has the following code:
// PlaneSaleing/Providers/ListingServiceProvider.php
<?php namespace PlaneSaleing\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
class ListingServiceProvider extends ServiceProvider {
public function register() {
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', 'PlaneSaleing\Repositories\Advert\EloquentAdvert');
}
}
I also added this to the ServiceProviders array in app.php
Now, if I inject Listing as a dependency into a controller and call the test method (as shown below) Laravel correctly detects the dependency, instantiates EloquentAdvert via its binding and displays 'this has worked'.
// Controllers/TestController.php
use PlaneSaleing\Providers\Listing;
class TestController extends BaseController {
protected $listing;
public function __construct(Listing $listing) {
$this->listing = $listing;
}
public function test1() {
$this->listing->test();
}
}
Now, I then created a facade for Listing. I added a new facade as follows and added an alias in app.php:
// PlaneSaleing\Providers\ListingFacade.php
<?php namespace PlaneSaleing\Providers;
use Illuminate\Support\Facades\Facade;
class ListingFacade extends Facade {
protected static function getFacadeAccessor() {
return 'Listing';
}
}
I also added the following new lines to ListingServiceProvider.php:
<?php namespace PlaneSaleing\Providers;
use PlaneSaleing\Repositories\Advert\AdvertRepository;
use PlaneSaleing\Repositories\Advert\EloquentAdvert;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
class ListingServiceProvider extends ServiceProvider {
public function register() {
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', 'PlaneSaleing\Repositories\Advert\EloquentAdvert');
// New lines...
$this->app['Listing'] = $this->app->share(function() {
return new Listing(new AdvertRepository);
});
}
}
NOW...if I call Listing::test(), I get the following error: Cannot instantiate interface PlaneSaleing\Repositories\Advert\AdvertRepository.
If I call Listing::test2() , I get 'this has worked' so it seems the Facade is working correctly.
It seems that when accessing Listing via its Facade the binding between AdvertRepository and EloquentAdvert doesnt work. I have looked at my code in the ServiceProvider thinking it was the issue, but I cant figure it out.
Both the Facade and binding work when tested individually but not when both are used at the same time.
Any ideas???
OK, So I have figured it out...For those who run into a similar problem...
The offending statement was in ListingServiceProvider.php which read:
$this->app['Listing'] = $this->app->share(function() {
return new Listing(new AdvertRepository);
});
The error is the new AdvertRepository statement. The reason being is that, we are telling php to directly instantiate the interface 'AdvertRepository'. Instead, we need to tell Laravel to instantiate the appropriate implementation of the 'AdvertRepository' interface. To do that, we use App::make('AdvertRepository'). That way, Laravel uses the binding previously declared to instantiate the correct implementation.
If your constructor is not being inject with a class, you must tell Laravel what class will be used when it needs to instantiate a particular interface:
Put this in your filters or bindings file:
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', function()
{
return new PlaneSaleing\Repositories\Advert\EloquentAdvert;
});

Categories