I made a custom guard implementation that force disables "remember me". Specifics of this custom implementation aside - when I try binding it to the Guard Contract it seems something goes wrong.
Customguard.php
<?php
namespace App\Contracts\Auth;
use Illuminate\Auth\Guard as StockGuard;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Contracts\Auth\Guard as GuardContract;
class CustomGuard extends StockGuard implements GuardContract
{
/**
* Log a user into the application.
*
* #param \Illuminate\Contracts\Auth\Authenticatable $user
* #param bool $remember
* #return void
*/
public function login (UserContract $user, $remember = false)
{
parent::login($user, false);
}
}
(Guard->login is overridden with exactly the same method signature)
I did the binding as follows, in the boot method of app/Providers/AuthServiceProvider.php
$this->app->bind('Illuminate\Contracts\Auth\Guard', App\Contracts\Auth\CustomGuard::class);
Everything works up until the point where CustomGuard->login is invoked.
BindingResolutionException in Container.php line 749:
Target [Illuminate\Contracts\Auth\UserProvider] is not instantiable.
What am I doing wrong?
Userprovider is an interface, you must use the class that implements the interface, I think that is eloquente Userprovidev.
Changed:
use Illuminate\Contracts\Auth\UserProvider;
To:
use App\Http\Controllers\Auth\CustomUserProvider as UserProvider;
Related
I am using Laravel 5.8 and attempting to set up a custom validation extension.
I have created a class GroupValidator containing a validate function.
I have created a ValidationServiceProvider with the following code:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
use App\Classes\GroupValidator;
class ValidationExtensionServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
Validator::extend('valid_parent_id', 'GroupValidator#validate');
}
}
When my validation triggers I get a Class GroupValidator does not exist exception. However if I specify the full path to my class in the extend function call like so:
Validator::extend('valid_parent_id', 'App\Classes\GroupValidator#validate');
then everything works fine.
Is there some way I can set this up so that I don't have to include the full path to my class?
In my app I have a service called "LogService" to log events and other items. I basically need to use this on every controller to log events by users. Instead of having to instantiate this service in each controller, I had two thoughts for accomplishing this.
Option 1: Bind the service into the IoC and then resolve it that way
Option 2: Make a master class with the service in it and then extend it for other classes so they come with the service already bound
I have questions for each of these methods:
Option 1: Is this even possible? If so, would it just be with "App::make()" that it would be called? That way doesn't seem to play too well with IDE's
Option 2: I have done this kind of thing in the past but PHPStorm does not seem to recognize the service from the parent object because it is instantiated by "App::make()" and not through the regular dependency injection.
What would be the best course of action?
Thanks!
You can have it both ways, I think the neatest way would be:
1) Have an interface that describes your class, let's call it LogServiceInterface
2) Create a Service Provider that instantiates your class, like so:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class LoggerServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* #return void
*/
public function register()
{
$this->app->bind(LogServiceInterface::class, function($app)
{
return new LogService();
});
}
}
3) Register this service provider in config/app.ph file:
'providers' => [
// Other Service Providers
App\Providers\LoggerServiceProvider::class,
],
4) Now, in controller you can request the instance of something that implements LoggerServiceInterface straight in the constructor:
(Some controller):
<?php namespace App\Http\Controllers;
use Illuminate\Routing\Controller;
use App\Repositories\OrderRepository;
class OrdersController extends Controller {
/**
* The logger service.
* #var LoggerServiceInterface $loggerService
*/
protected $loggerService;
/**
* Create a controller instance.
*
* #param OrderRepository $orders
* #return void
*/
public function __construct(LoggerServiceInterface $loggerService)
{
$this->loggerService = $loggerService;
}
/**
* Show all of the orders.
*
* #return Response
*/
public function index()
{
// $this->loggerService will be an instance of your LoggerService class that
// is instantiated in your service provider
}
}
This way, you have got an easy way to quickly change the implementation of your service, moreover, Phpstorm can handle this very easily.
You will still be able to use app()->make() to obtain an instance of your service.
This, however, will not be automatically picked up by Phpstorm. But you can help it to understand that, all you need to do is to use #var annotation, see:
/**
* #var LoggerServiceInterface $logger
*/
$logger = app()->make(LoggerServiceInterface::class);
That way, Phpstorm will know what to expect from that $logger object.
I've got a User Entity defined (mapping in yml)
namespace My\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class User
{
...
And I created a child class that inherits from that entity, so that I can add some custom validation methods and a few fields that I need but do not need to be persisted (e.g. ConfirmPassword, ConfirmEmail fields)
namespace My\SecondBundle\EditModels;
use My\CoreBundle\Entity\User;
class UserModel extends User
{
When the user submit a registration form, I map the request to a UserModel entity, and if it is valid I try to persist the user.
The following code throws an exception
$entityManager->persist($userModel);
//=>The class 'My\SecondBundle\EditModels\UserModel' was not found in the chain configured namespaces My\CoreBundle\Entity
Question: How can I persist $userModel (instance of UserModel) as a User entity class? Possible options:
Do not use an inherited class and add custom fields and validation method to the User entity itself
Copy the fields from the UserModel to the User entity and persist the user entity
I don't think I should use Doctrine inheritance mechanism as I do not want to save the extra fields.
Thank you
I think your problem here, is that you've just configured My\CoreBundle\Entity namespace in Doctrine2, but the entity you actually want to persist is located in My\SecondBundle\EditModels.
Usually when inheriting classes marked as #ORM\Entity() the class you are extending from must have the class annotation #ORM\MappedSuperclass(). But normally you use this for single table inhertiance e.g., not for your usecase.
In my opinion the approach to split database related attributes from the others, is not affordable. I would keep validation related stuff in the model itself - you need it in your create/update action.
I'm not familiar with XML configuration, but when using annotations you need to mark each property to be mapped with database (using #ORM\Column()). So Doctrine will ignore all the other attributes and methods entirely.
So here I share my recently developed AbstractModel for you, to see how I've implemented validation (with respect/validation):
<?php
namespace Vendor\Package\Model;
use Doctrine\ORM\Mapping as ORM;
/**
* Abstract Model
*
* #ORM\MappedSuperclass()
*/
abstract class AbstractModel
{
/**
* #var \Respect\Validation\Validator
*/
protected $validator;
/**
* AbstractModel constructor
*/
public function __construct()
{
$this->validator = static::validation();
}
/**
* Defines validation for this model
*
* #return \Respect\Validation\Validator
*/
public static function validation() : \Respect\Validation\Validator
{
return \Respect\Validation\Validator::create();
}
/**
* Executes validations, defined in validation method.
*
* #return bool
*/
public function isValid() : bool
{
if (is_null($this->validator)) {
$this->validator = new \Respect\Validation\Validator();
$this->validation();
}
return $this->validator->validate($this);
}
}
A model which extends from the AbstractModel needs to implement a static validate method, to define class validation:
<?php
namespace Vendor\Package\Model;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity()
* #ORM\Table(name="my_model")
*/
class MyModel extends AbstractModel
{
/**
* #var string
* #ORM\Column(type="string")
*/
private $name;
/**
* Defines validation for this model
*
* #return \Respect\Validation\Validator
*/
public static function validation() : \Respect\Validation\Validator
{
return \Respect\Validation\Validator::create()
->attribute('name', \Respect\Validation\Validator::notEmpty()->stringType()->length(null, 32))
;
}
// getter, setter, ...
}
Each entity, persisted to database, will have the $validator property and all these methods, but because I left annotations here (and pretty sure this also works with xml/yaml) Doctrine ignores it.
And this way you also keep validation related stuff out of the model class itself, which is good for readability. The validation itself should be defined in the model itself, imho. But this respect/validation framework is neat way to achive this. Hope this helps :)
I'm getting error:
Fatal error: Class Blog\Factory\ListControllerFactory contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Zend\ServiceManager\Factory\FactoryInterface::__invoke) in /d0/home/kgendig/www/Zend/module/Blog/src/Blog/Factory/ListControllerFactory.php on line 28
I'm doing all with
https://framework.zend.com/manual/2.4/en/in-depth-guide/services-and-servicemanager.html
What i have to change, my zend_version(); is 2.6.0
<?php
// Filename: /module/Blog/src/Blog/Factory/ListControllerFactory.php
namespace Blog\Factory;
use Blog\Controller\ListController;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class ListControllerFactory implements FactoryInterface
{
/**
* Create service
*
* #param ServiceLocatorInterface $serviceLocator
*
* #return mixed
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$realServiceLocator = $serviceLocator->getServiceLocator();
$postService = $realServiceLocator->get('Blog\Service\PostServiceInterface');
return new ListController($postService);
}
}
Your ListControllerFactory class implements the FactoryInterface. So you have to define all abstract functions of this interface in your class. Here, your FactoryInterface needs the __invoke() method (check how you call it), so you have to define it in your ListControllerFactory.
It seems you are mixing ZF2/3 components. In ZF3 FactoryInterface code (see here), you have instructions for upgrading from V2 to V3:
If upgrading from v2, take the following steps:
rename the method createService() to __invoke(), and:
rename the $serviceLocator argument to $container, and change the typehint to Interop\Container\ContainerInterface
add the $requestedName as a second argument
add the optional array $options = null argument as a final argument
create a createService() method as defined in this interface, and have it proxy to __invoke().
This describe how to solve your problem, but maybe there are several similar issues in your code. Try not mixing ZF2.4 and ZF3 component. Don't use dev-master in your composer.json. I suggest you to use only ZF2 component and ZF2 tutorial, or, if you want to learn ZF3, only ZF3 components and the ZF3 tutorial.
How can i implement laravel contracts and service providers ?
I have a class Cart and its method purchase , the class will of course contain my program structure to which most of my controllers will rely upon.
How can effectively manage dependency injection of this class among other controllers ?
You can simply reference the class as dependency in your controller. It will be instantiated even if you don't use an interface.
<?php
namespace App\Http\Controllers;
use App\Users\Repository as UserRepository;
class UserController extends Controller
{
/**
* The user repository instance.
*/
protected $users;
/**
* Create a new controller instance.
*
* #param UserRepository $users
* #return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}
If you were to use an interface just make sure your class implements it and simply call use the bind method from the app instance in any of your service providers.
$this->app->bind(UserRepository::class, EloquentUserRepository::class);
https://laravel.com/docs/5.2/container
https://laravel.com/docs/5.2/providers