To develop a project where I am creating some methods which are common in all the controllers.
Before this I have used codeigniter and there I wrote MY_Controller class in core directory and then I extended the controller in all the controllers in controller directory.
Same I want to do inside Laravel. But I am confused that where should I write the common methods like send_email, validate_captcha, ajax_file_upload and other common methods which remains same across whole application.
So please suggest me a good way to define such a class or middleware.. What should one do to create that?
OK. Let me suggest some stuffs
Need to write methods which is apply to all Controllers. You
can/should modify App\Http\Controllers\Controller.php. Because all
Controllers in Laravel extend it
Need to write class that available across whole application. It is
never easier
Step 1: Write any class you want in app folder. And follow psr-4 convention
Step 2: Register to Laravel application
In App\Providers\AppServiceProvider. In register() method. Add
$this->app->bind('bindname', function ($app) {
return new \App\YourClass;
// If you want to inject other class to YourClass contructor
// return new \App\YourClass($app->make('otherbindname'));
});
Step 3: Use it. There are several ways to access YourClass in your whole application:
app()->make('bindname');
app('bindname');
app()['bindname'];
\App::make('bindname');
//etc
Related
I am working on a Yii1 old website. which is linked with some external PHP controllers. These external controllers provide some common functions that are used between 2 different applications. I have a function in Yii model that I want to use in one of the external PHP controller is there a way to do this? Currently, this is done by rewriting MySQL query in the PHP external controller but I don't want to follow this lame practice.
I found this link and I am able to access Yii externally but it's still not very helpful. Using Yii in 3rd-Party Systems
Here's a sample of my code:
namespace main\Helpers;
require_once('path/to/yii.php');
Class HelperClass {
public static function yiisupport($id){
// I am able to access Yii variables using
\Yii::app()->name
// But how to access the yii model or controller functions? I need something like the follwoing
$model = \Yii::app()->YiiModel::model()->findByPK($id);
}
}
Can anyone help?
You need to create Yii application first (using config file path) to access its models and controllers as it is mentioned in the documentation. Then you can access any model class in your external application just like you would access it in your Yii application, and you can use controller actions as below;
$controller = new \YOURController('ACTION_NAME');
$controller->ACTION_NAME();
If you have already imported models/controllers in your config file then you will not need to import any class but if you have not then you can import specific model/controller like below;
\Yii::import('application.models.MODEL_NAME');
\Yii::import('application.controllers.CONTROLLER_NAME');
Check the examples below;
namespace main\Helpers;
require_once('path/to/yii.php');
\Yii::createWebApplication('path/to/config.php');
Class HelperClass {
public static function yiisupport($id){
// Access Yii variables
\Yii::app()->name;
// Access yii model
$model = \YiiModel::model()->findByPK($id);
// Access yii controller and its actions
$controller = new \YiiController('actionCreate');
$controller->actionCreate();
}
}
Update:
As mentioned by #rob006 in the comment below that calling yii controller action outside Yii application is a bad idea, however if you still want to do that, there is a safer way which follows the Yii application lifecycle and this way access filters and beforeAction() will be triggered. So you can call controller action in a safer way as below;
\Yii::app()->runController('route/to/action');
Im new to Laravel and namespaces, but a colleague told me i have to use the namespaces and place all my models in a folder in the app directory, named after the project.
As far as i know this means that in every single controller that uses one or more models, have have to set "use" for every model my controller needs. Example:
<?php
use Foo\Entities\Entity;
use Foo\Entities\Inheritance;
use Foo\Entities\Type;
class EntitiesController extends BaseController {
public function index()
{
$inheritances = Inheritance::all();
$entities = Entity::all();
return View::make('settings/entities')
->with('entities', $entities)
->with('inheritances', $inheritances);
}
}
If we asume that the associated models above will be used everywhere, would it be completely crazy to put the models in the /app/model/ folder and if a controller need a model which overwrite the standard system, then use namespaces?
First things first: namespaces are NOT a Laravel thing, but a PHP feature created to better organize our code.
So, if you want your code organized, you should use namespaces for everything and, yes, you'll have to add 'use' clauses in the top of most of your PHP files. But in Laravel you also can be free to not use namespaces at all, you just have to add your autoload classes directories to your composer.json file:
"autoload": {
"classmap": [
"models"
],
},
Execute
composer dumpautoload
So Composer read all files in your models folder, to create a class map of them, and then you can just drop all uses clauses:
class EntitiesController extends BaseController {
public function index()
{
$inheritances = Inheritance::all();
$entities = Entity::all();
return View::make('settings/entities')
->with('entities', $entities)
->with('inheritances', $inheritances);
}
}
To not use namespaces in your PHP application, these days, may be considered a code smell. The only 'part' of Laravel where people doesn't usually use namespaces is Controllers, but this is also changing in Laravel 5, where controllers will be namespaced by default, but still, you will have the option to not use them, because this is a Composer/PHP thing, not Laravel.
Taylor Otwell has 3 big things always in mind when creating features and evolving Laravel: Best practices, fast coding and beautiful code.
EDIT
Answering your comment, if all your controllers needs to have access to some service or even model, why not add it to your BaseController?
But you may have to take a read at the repository pattern, because your controllers should not really be aware of your models. Developers are now creating a new layer (repository) between controllers and models, and perform the operations in those layers. You can, also, make use of Laravel Dependency Injection to help you with those use clauses you don't like.
It would be something like this:
Create a repository interface:
interface EntityRepositoryInterface {
}
Create the repository:
use Foo\Entities\Entity;
class EntityRepository {
public function find($id)
{
return Entity::find($id);
}
public function all()
{
return Entity::all();
}
}
Create your controllers using your repository:
class EntitiesController extends BaseController {
public function __construct(EntityRepositoryInterface $entityRepository)
{
$this->entityRepository = $entityRepository;
}
public function index()
{
$entities = $this->entityRepository->all();
return View::make('settings/entities')
->with('entities', $entities);
}
}
And you have to tell Laravel Dependency Injection what to instantiate when it needs a EntityRepositoryInterface:
App::bind('EntityRepositoryInterface', 'Foo\Entities\EntityRepository');
There's nothing wrong with putting your models anywhere you like. In fact, I put all my models that extend directly from Eloquent in app/models. You are free to follow this, or not follow it, in your own project.
However, this does come with a caveat. Very few of my classes actually directly interact with these models (Repositories are pretty much it). Those I do put in separate namespaces which are then injected into my controllers. Consequently, I must either use each repository that a controller needs at the top of each file or specify the fully qualified class name every time I reference it.
I'm trying to figure out how to add a method to a class in a Laravel package, so that all controllers and models that call that class can access the new method. How do I replace this class in the IoC?
This is the package in question, Angel CMS. The package is my creation, so I can modify it if we need to add aliases or anything to accomplish this.
Let's say I want to add a method to this class:
vendor/angel/core/src/models/PageModule.php
Okay, so I copy the class file to here:
app/models/PageModule.php
And then I modify the copied file, adding a namespace and the desired custom_function method:
<?php namespace MyModels;
use Eloquent;
class PageModule extends Eloquent {
protected $table = 'pages_modules';
public static function custom_function()
{
return 'It works!';
}
}
As you can see, I am using the MyModels namespace here.
Then, I run a composer dump-autoload.
Next, I open up my app/routes.php and register the binding and set up a test route:
App::bind('PageModule', function($app) {
return new \MyModels\PageModule;
});
Route::get('test-binding', function() {
return PageModule::custom_function();
});
But, when visiting the test route, I always receive the same error that the method is undefined.
What am I doing wrong here? Thank you in advance for any help.
To Clarify:
I am attempting to replace the class application-wide so that all other classes (controllers/models/etc.) that call PageModule will have access to the custom_function method. Thanks.
To be honest, I'm pretty new to all this IoC, dependency inversion/injection concept too. But I think I've gone through the same struggle before. What I would do, as much as my knowledge allows, is...
Add a constructor to src/controllers/admin/AdminPageController.php:
protected $pageModule;
public function __construct(PageModule $pageModule)
{
$this->pageModule = $pageModule;
}
Then where you did $module = new PageModule in the same file. You replace it with:
$module = $this->pageModule;
The two modifications above makes use of Laravel's IoC to allow injecting a different PageModule object into your controller, instead of strictly creating PageModule in your code.
Now at this point Laravel should know that when it constructs the AdminPageController, it should create a PageModule and inject into the controller for you.
Since your controller now expects a PageModule class, you can no longer do class PageModule extends Eloquent in your app anymore, because even though the name is the same, PHP does not think that it is! You'll need to extend it:
So let's rename your app/models/PageModule.php to app/models/CustomPageModule.php, and in the file change the class to:
class CustomPageModule extends \PageModule {
Up to this point, you also have a CustomPageModule class that is a child of your package's PageModule. All you need to do now is to let Laravel knows that if any controllers ask for PageModule, it should serve the controller with your MyModels\CustomPageModule instead.
So at the top of your app's routes.php file:
App::bind('PageModule', 'MyModels\CustomPageModule');
Your AdminPageController should now be using your CustomPageModule and can use whatever public methods that are in there!
I'm expecting to be editing this answer heavily since this will be quite a long discussion. My first try at answering above isn't the best code you can write, but I hope it takes the least amount of edit to the original code, and then we can work up from there.
Or fast track by reading up articles like http://culttt.com/2013/07/08/creating-flexible-controllers-in-laravel-4-using-repositories
You probably have a alias for the PageModule facade, you should override this alias using your class \MyModels\PageModule in your app/config/app.php file.
Be careful, it seems like you are overwriting the PageModule class instead of extending it. You should probably extend the parent class instead of Eloquent.
I'm trying to extend Laravel's Auth Guard class by one additional method, so I'm able to call Auth::myCustomMethod() at the end.
Following the documentation section Extending The Framework I'm stuck on how to exactly do this because the Guard class itself doesn't have an own IoC binding which I could override.
Here is some code demonstrating what I'm trying to do:
namespace Foobar\Extensions\Auth;
class Guard extends \Illuminate\Auth\Guard {
public function myCustomMethod()
{
// ...
}
}
Now how should I register the extended class Foobar\Extensions\Auth\Guard to be used instead of the original Illuminate\Auth\Guard so I'm able to call Auth::myCustomMethod() the same way as e.g. Auth::check()?
One way would be to replace the Auth alias in the app/config/app.php but I'm not sure if this is really the best way to solve this.
BTW: I'm using Laravel 4.1.
I would create my own UserProvider service that contain the methods I want and then extend Auth.
I recommend creating your own service provider, or straight up extending the Auth class in one of the start files (eg. start/global.php).
Auth::extend('nonDescriptAuth', function()
{
return new Guard(
new NonDescriptUserProvider(),
App::make('session.store')
);
});
This is a good tutorial you can follow to get a better understanding
There is another method you could use. It would involve extending one of the current providers such as Eloquent.
class MyProvider extends Illuminate\Auth\EloquentUserProvider {
public function myCustomMethod()
{
// Does something 'Authy'
}
}
Then you could just extend auth as above but with your custom provider.
\Auth::extend('nonDescriptAuth', function()
{
return new \Illuminate\Auth\Guard(
new MyProvider(
new \Illuminate\Hashing\BcryptHasher,
\Config::get('auth.model')
),
\App::make('session.store')
);
});
Once you've implemented the code you would change the driver in the auth.php config file to use 'nonDescriptAuth`.
Only way to add (and also replace existing functions) is to create copy of Guard.php file in your project and in app/start/global.php add:
require app_path().'/models/Guard.php';
Of course it's ugly method, but I spent over hour to test all possibilities [how to change things stored in Session by Auth] and it always end with error:
... _contruct of class HSGuard requires first parameter to be 'UserProviderInterface' and get 'EloquentUserProvider' ...
I am currently developing a Lithium application and have come across a function that I have written that I would like to use across multiple Controllers.
I obviously don't want to have the function in each controller. What is the standard way of creating a re-usable component in Lithium?
The lack of search facility on their documentation is making it difficult to find any specifics.
You could try extending controller. Extending controllers is not that bad according to core devs. If that is not and option you could extract your code into a plugin, still some code in controller though.
All you have to do is create a extensions/action/Controller.php and have your controllers extend that.
In your extensions/action/Controller.php
<?php
namespace app\extensions\action;
class Controller extends \lithium\action\Controller {
protected function _init() {
parent::_init();
//add your functionality here
}
}
?>
And then, your controller has to extend the above mentioned base controller: class MyController extends \app\extensions\action\Controller {
I think this is not a Lithium-specific thing. You could either inherit from the Controller and make your own base controller, but you can also create arbitrary classes that hold your functionality. Don't let a framework inhibit you =)
Regarding the documentation: I usually google in the sense of "<keywords> site:lithify.me"