I have developed a package containing package controllers. Everything is loading and working fine, but currently the package controller looks like this:
<?php
namespace MyPackage\App\Http\Controllers;
use App\Http\Controllers\Controller; // Stock Laravel controller class
use Illuminate\Http\Request;
use Voice\CustomFields\App\Form;
class FormController extends Controller
{
...
}
I want the class to extend Laravel Controller class, however inside my package this class of course doesn't exist as it is a part of a standard Laravel app.
I ended up including use App\Http\Controllers\Controller;, but I don't see it as a good practice since I'm referencing something that doesn't exist up to the point I include my package in the app.
How can I do this the right way? I can replicate the class within my package, but this would be duplicating logic + additional problems if tomorrow a new Laravel version is released with a modified Controller class.
Just look in source code of App\Http\Controllers\Controller
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
You can extend BaseController in your package controllers. If Laravel team change something, it will be written in migration instructions.
If you need some specyfic logic in your package BaseController and the same logic in app BaseController, consider using trait or ServiceProvider.
Your controller doesn't necessarily need to extend the default "base controller". Usually packages either extend the Illuminate\Routing\Controller directly or have their own base controller to extend all the other controllers with.
If you are using the stock base controller without any custom code added, there won't be any duplicate lines if you choose to copy it to your package as it only consists of three optional traits providing helper functions wrapping more complicated code.
Related
I'm developing a package which has controllers in it and I want this package to be compatible with (or useable by) both Laravel and Lumen projects. My problem is Laravel controllers extend Illuminate\Routing\Controller and Lumen controllers extend Laravel\Lumen\Routing\Controller. The controller inside my package can't extend them both.
The only solution I've come up with is to have the controllers inside the package extend App\Http\Controllers\Controller.
But I see some problems:
App\Http\Controllers\Controller should exist; which means it wouldn't work if the App namespace is named differently.
The package is now "aware" that it is being included in something.
Testability: I can't test the controller independently because of the reference to App\Http\Controllers\Controller.
Is there a better way of doing this?
Edit 1
I'm finding other classes which are affected in a similar way. For example, the namespace of the trait Authorizable is Illuminate\Foundation\Auth\Access in Laravel while it is Laravel\Lumen\Auth in Lumen. I am using a model which uses that trait. How do I make my model compatible with both Lumen and Laravel?
Well, you could simply have two different files and classes wrapped in if statements and check for the corresponding classes to extend. So:
LaravelClass.php:
if(class_exists(Illuminate\Routing\Controller:class)){
class LaravelClass extends Illuminate\Routing\Controller {
use YourCodeTrait;
// any more code that is not in your trait
}
}
LumenClass.php
if(class_exists(Laravel\Lumen\Routing\Controller:class)){
class LaravelClass extends Laravel\Lumen\Routing\Controller {
use YourCodeTrait;
// any more code that is not in your trait
}
}
Loading both files will only load one of the classes. In the code above I use a trait to load the contents of your controller, assuming the contents is the same, you could use the same trait and not have to repeat yourself.
trait YourCodeTrait{
// whatever would normally go in your controllers
}
I am attempting to add custom repsitories (contract and Eloquent) in Laravel.
I don't understand where to add them and how to bind with services.
Can any body show the best example for add own wn repository class and interfaces in Laravel?
Thanks in advance
Create a directory in your App folder.Like - App/Acme
Create a Repository File in Acme folder. App/Acme/CustomRepository.php and also import the name space on that Repository file.Like- namespace Acme;
Use your model. Like- use App\Models\User;
In you controller inject the CustomRepository Class.Like-
class CustomController extends Controller{
private $customRepo;
public function __construct(CustomRepository $customRepo)
{
$this->customRepo= $customRepo;
}
}
The way I like to structure my Laravel Code would be:
Models - App\Models\*
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as BaseModel;
class Model extends BaseModel
{
//
}
Contracts - App\Repositories\Contracts\*
<?php
namespace App\Repositories\Contracts;
interface Repository
{
// All the common methods for eloquent like - all, paginate, find, where, etc...
}
Repository - App\Repositories\Db\*
<?php
namespace App\Repositories\Db;
class ExampleRepository
{
// All the CRUD related methods here...
}
Services - App\Services\*
<?php
namespace App\Services;
class ExampleService
{
// All the logic & business related methods here...
}
This is what I like to structure my code in a laravel way.
Hope this helps!
For make usage of repository pattern (if it is that what you want to say), you have two options, one of it is to implement under a self-defined namespace (let's say App\Repositories), an interface with the methods you want to use in all your repositories, maybe AbstractRepository or something like that, this one choice is painful because of the lot of code you have to write, the other choice (what I would use), is to install the following package https://github.com/andersao/l5-repository, is really useful and already have inside a lot of methods, just follow the instructions of the readme file and you will not have any issue at all implementing this pattern, hope it helps, bests! ;)
I have started with YII2 just today. i have installed it successfully and also created required Model, Controllers & views in that using CRUD.
Now my question is as below:
I want to create one Global Validator Rule which we can use in throughout the Models in system.
What i have tried so far:
For that i have created one new model file(FormValidator) in common folder and generate one custom rule method in it.
common/model/FormValidator.php
namespace common\models;
use Yii;
use yii\base\Model;
class FormValidator extends \yii\db\ActiveRecord {
}
then i tried to extend this model file to my frontend model file. but its not working.
frontend/model/Customerprofile.php
namespace frontend\models;
use Yii;
use common\models\FormValidator;
class Customerprofile extends FormValidator{
}
It's throw below error message:
PHP Fatal Error – yii\base\ErrorException
Class 'common\models\FormValidator' not found
I don't know what i have missing in all these process, if anyone of you help me out from this, would be much appreciated!
Thanks in Advance.
If you want to extend some master class for model you have to simply extend CActiveRecord and then your models will extend this masterclass.
I was trying to migrate a Laravel 4.2 app into Laravel 5.0
and previously in Laravel 4.2 you have a BaseController which other Controllers you create can extend, meaning if I add a method inside it. The other controllers will extending the BaseController can use it.
Now on Laravel 5.0, they somehow changed it instead of using class they made use of an abstract class
<?php namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesCommands;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
abstract class Controller extends BaseController {
use DispatchesCommands, ValidatesRequests;
}
Now I'm not familiar with what an abstract class is so my main concert is will I still be able to add functions() that can be used by other controllers extending it?
So as an example in a controller extending the BaseController
$this->method_from_base_controller();
Yes, you can create for abstract classes methods that will be used in classes that inherits from abstract class.
The main difference between abstract classes and normal classes is that you cannot create objects of abstract classes. You can also create in abstract classes methods you want to be implemented in child classes. Reference on abstract clasess on php.net
Like in Codeigniter we do have 'core' folder where we can define our own controller like 'MY_Controller' and can be used to extend all the class to extend from this controller is there any possibility to do so in Symfony2.
In symfony I want to create class 'MY_Controller' which extends from the base class 'Controller', and I want all the classes in the controllers to extend from MY_Controller' class.
Thanks in Advance...
Note:
When working with Symfony2 it is strongly recommended you follow the Symfony2 coding style. It's basically the same as PHP-FIG, with one or two deviations. So underscores are a no-no in class names. Other than that: Symfony is pretty easy to work with, and fully OO, so changing the class a controller extends from is as simple as replacing extends Controller with extends AnotherClass.
But now, the symfony2-way of using a custom controller:
What you could do, is create a Core bundle (CoreBundle henceforth). Then, in this CoreBundle, define a controller, that extends from the Symfony Controller component. From the command line, in your project root, use this command:
php app/console generate:bundle --namespace=YourNameSpace/CoreBundle --bundle-name=YourNameSpaceCoreBundle
More options can be found here
After that, you'll find a DefaultController class in the bundle directories. (probably in the folder src/YourNamespace/CoreBundle/Controller). Then, set about generating your Core controller:
php app/console generate:controller --controller=YourNameSpaceCoreBundle:Core
See the documentation for more options on how to generate your core controller.
After you've finished setting up your custom controller, you can use it in any of the other bundles at will:
namespace YourNameSpace\AnotherBundle\Controller;
use YourNameSpace\CoreBundle\Controller\CoreController;
class DefaultController extends CoreController
{//extends from your custom controller
}
And that's it: you're done.
First, don't name the class using underscores as in PSR-0 each underscore char is converted to a directory separator, when used in class name.
Second, put your controllers to <bundledir>/Controller/
Third, name your controller something like BaseController and extend all other controllers from it.
Fourth, think of using dependency injection rather than coupling functionality in a base controller.