I would like to know if this is possible in Object Oriented Programming in php. I have a controller
class BaseController extends Controller{
/**
* #Route("/sample", name="sample")
*/
public function postSampleAction(Request $request){
}
}
and I have a file called ProductEvent and PriceEvent
class ProductEvent extends BaseController{
public function checkEvent(){
echo "product event";
}
}
class PriceEvent extends BaseController{
public function checkEvent(){
echo "price event";
}
}
as you can see I extend the BaseController. What I want to happen is that I need to put the checkEvent() to the BaseController in postSampleActioin()
class BaseController extends Controller{
/**
* #Route("/sample", name="sample")
*/
public function postSampleAction(Request $request){
$this->checkEvent();
}
}
I don't know if this is a proper way. I want to test if that will echo the checkEvent() function.
Sorry my mistake. I forgot to add what framework do I used. I used symfony for this.
That means you want to make BaseController an incomplete, abstract class which requires to be inherited and the checkEvent method to be implemented there:
abstract class BaseController extends Controller {
public function postSampleAction(Request $request) {
$this->checkEvent();
}
abstract public function checkEvent();
}
You now cannot instantiate BaseController by itself, and any inheriting non-abstract class needs to implement checkEvent; that gives you the required type safety that allows you to depend on checkEvent in postSampleAction.
Related
I have created an abstract BaseController class that extends AbstractController.
This is so that all the Common Dependencies don't have to be injected in each Controller class that I have (e.g. EntityManager and RequestStack).
However, I have some Controller classes where I would like to inject additional services in the constructor, but this is causing problems.
// src/Controller/BaseController.php
namespace App\Controller;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RequestStack;
abstract class BaseController extends AbstractController
{
protected $em;
protected $request;
public function __construct(EntityManagerInterface $em, RequestStack $request)
{
$this->em = $em;
$this->request = $request->getCurrentRequest();
}
}
I can then just extend my Controller classes and call for example $this->em in any of the methods.
However, let's say that I wanted to do the following:
// src/Controller/DashboardController.php
namespace App\Controller;
use Symfony\Component\Translation\TranslatorInterface;
class DashboardController extends BaseController
{
public function __construct(TranslatorInterface $translator)
{
parent::__construct();
$this->translator = $translator;
}
public function index()
{
// use $this->translator()
}
}
This would cause an error as the constructor of the BaseController is expecting two arguments to be passed.
I've tried adding the following to my services.yaml but to no avail:
App\Controller\BaseController:
arguments: ['#doctrine.orm.entity_manager', '#request_stack']
What would be the best way to autowire these arguments, and would this be a good practice?
I am following this tutorial about authentication
I have a custom security class called FormLoginAuthenticator.php
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Core\Security;
abstract class FormLoginAuthenticator extends AbstractFormLoginAuthenticator
{
protected $router;
protected $enconder;
public function __construct(RouterInterface $router, UserPasswordEncoderInterface $encoder)
{
$this->router = $router;
$this->encoder = $encoder;
}
}
which extends the AbstractFormLoginAuthenticator from the symfony guard component which itself is a abstract class.
However I keep gettting
Cannot instantiate abstract class App\Security\FormLoginAuthenticator
I have read about extending abstract classes and if my custom class has more than 1 abstract method I should use prefix the class keyword with `abstract. However I get that error when I added the abstract keyword. How to get around this problem
You don't have abstract method in your
FormLoginAuthenticator
, so this class shouldn't be abstract. The only abstract method is from its parent, but when you extend abstract parent, you don't define your new class as Abstract, unless there is next child, which is extending it. You can't instantiate abstract classes, thats where your error comes from. You have to define your class as normal or final
Small example here - https://3v4l.org/4MQpU#v560
Just drop the keyword 'abstract' and implement abtract methods from parent class:
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
...
protected function getLoginUrl(): string
{
return $this->router->generate('login');
}
...
}
And you are done.
As required, a small example.
From symfony github https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Guard/Authenticator/AbstractFormLoginAuthenticator.php, you should at least implement this function
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
class ExampleFormAuthenticator extends AbstractFormLoginAuthenticator
{
/**
* Return the URL to the login page.
*
* #return string
*/
protected function getLoginUrl(){
// [TODO: implement]
}
}
I'm trying to reuse a Job code for handling two different tasks with same methods (MyClass1 and MyClass2). I've write an abstract class for passing it to the Job handler, however I get the message 'is not instantiable'.
This is what I'm trying to do
abstract class MyAbstractClass
{
abstract public function doSomething();
}
class MyClass1 extends MyAbstractClass
{
public function doSomething(){
// do some staff
}
}
class MyClass2 extends MyAbstractClass
{
public function doSomething(){
// do some staff
}
}
class MyJob extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
public function __construct()
{
}
public function handle(MyAbstractClass $myObj)
{
$myObj->doSomething();
// it executes the method doSomething of MyClass1 or MyClass2 depending on the enqueued Job
}
}
Any solution? If not, I will do two Jobs, one for each class... what do you think?
Thank you
I'm trying to find out why I'm receiving this error. I'm following along. However the only difference is that at the time of the recording it was done with Laravel 4.25 and I am now using Laravel 5.0.
Repositories and Inheritance
BindingResolutionException in Container.php line 785:
Target [App\Repositories\User\UserRepository] is not instantiable.
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Repositories\User\UserRepository;
use Illuminate\Http\Request;
class UsersController extends Controller {
private $userRepository;
public function __construct(UserRepository $userRepository) {
$this->userRepository = $userRepository;
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index() {
$users = $this->userRepository->getAll();
return $users;
}
}
<?php
namespace App\Repositories\User;
use App\Repositories\EloquentRepository;
class EloquentUserRepository extends EloquentRepository implements UserRepository
{
private $model;
function __construct(User $model) {
$this->model = $model;
}
}
<?php
namespace App\Repositories\User;
interface UserRepository {
public function getAll();
}
<?php
namespace App\Repositories;
abstract class EloquentRepository {
public function getAll() {
return $this->model->all();
}
public function getById() {
return $this->model->findOrFail($id);
}
}
You are type hinting an interface, and not the class itself. This error is occurring because Laravel cannot bind an interface because the binding must be instantiable. Abstract classes or interfaces are not valid unless Laravel knows the concrete (instantiable) class to substitute in for the abstract class / interface.
You will need to bind the EloquentUserRepository to the interface:
App::bind('UserRepository', 'EloquentUserRepository');
Hello this is my AppModel.php Class
<?php
App::uses('Model', 'Model');
class AppModel extends Model{
static public function message()
{
return 'this is a message';
}
}
and I have my model User.php
<?
class User extends AppModel {
}
and my controller UsersController.php
class UsersController extends AppController
{
public function index()
{
$this->layout ='main';
}
}
My question is, how can I call method message() from its AppModel Class in UsersController or at least in my model Users?
You can call it like you do with any static method
AppModel::message();
Though, I suggest not using it as static. In your controllers and definitely in your models you will have already an instance of a model that extends the AppModel. So if you change
/*static*/ public function message()
{
return 'this is a message';
}
then you can call it in controllers like
$this->User->message();
and in the user model with
$this->message();
And while we're on it, change it to protected so only it's children can use the function.