Extend Input Class in Laravel – 4
Input
class in Laravel
, instead it uses Request
class for any Input::method()
calls.
Basically, we extend a class in OOP
language to add some extra functionalities to a base (already created) class and in PHP
, for example, if you have following class
class BaseClass { public function hello() { echo "Say Hello!"; } }
Now, if you need to extend this class then you can simply extend a this class like this way
class ChildClass extends BaseClass { public function helloWorld() { echo "Say Hello World!"; } }
So now, ChildClass
has two methods, one it’as own and one from it’s base class because it extended the functionality from BaseClass
class. It’s simple.
But, in Laravel
, you can’t just extend every core class like this way, it means that, you can extend it same way but you an’t use it normally you use any class in any PHP
application because, Laravel
uses a different approach to access it’s core classes. In laravel
, when you want to call a class method, you basically do something like this
// Get all user input from $_REQUEST $input = Input::all();
Here, it looks like that, Input
is a class and all()
is it’s static method but actually, it’s not what it looks like. Actually, Laravel-4
doesn’t use static methods and here is a nice article about it, if you read this article, you can find that, actually Laravel-4
doesn’t use static methods, instead it mimics the static calling behavior. It uses Facade
design pattern, when you call a static
method, actually much more things happen behind the scene than it appears. So, when we call View::make('hello');
, actually, Laravel
loads Illuminate\Support\Facades\View
class and if you look at this class, you can see something like this
class View extends Facade { protected static function getFacadeAccessor() { return 'view'; } }
This is not the original class for View
class, instead it’s a Facade
class, through this class and IoC Container
, somehow Laravel
reaches to it’s original class, which is stored in the vendor
folder, where all the other vendors
are stored and the path for the original View
class is vendor/laravel/framework/src/Illuminate/View/View.php
, so to extend the View
class, you have to extent the main class from vendor
folder mentioned above. Actually, this article is about extending the Input
class and it looks like I’m talking about something irrelevant but I think it’s relevant because if you want to extend the Input
class, you may think that, there is a class in the vendor
folder something like this vendor/laravel/framework/src/Illuminate/Input/Input.php
but there is nothing like this. Then the question is, where is the main Input
class ? If you look into the Facade
of Input
class, then you can find the answer, the code may looks something like this
// vendor/laravel/framework/src/Illuminate/Support/Facades/Input.php class Input extends Facade { // other code protected static function getFacadeAccessor() { return 'request'; } }
It returns the request
just like Request Facade
, which means, when you call Input::all()
, actually, you use the Request
class and all the methods that we use as Input::method()
, we actually use the method from the Request
class, which is stored in
vendor/laravel/framework/src/Illuminate/Http/Request.php
So, Input
is just a wrapper to separate the methods calls from using Request::method()
but if you use Request::all()
instead of Input::all()
, you’ll get the same result. So, if you want to extend the functionality for Input
, you have to extend the Request
class.
So, how to extend Input
class, oops! sorry, actually Request
class ?
So, now we know that, there is no Input
class, instead it’s Request
class, which provides all the methods for Input
and to extend the Request
class we should know that, Laravel components are typically extended in one of two ways:IoCbindings and the Manager classes. The manager classes serve as an implementation of the “factory” design pattern, and are responsible for instantiating driver based facilities such as cache and session but extending the Request class works a little differently than all other classes. Because it’s such a foundational piece of the framework and is instantiated very early in the request cycle, Taylor Otwell
himself mentioned about it in his book titled Laravel: From Apprentice To Artisan. So, to extend the Request
class you may first create your own class by extending the base Request
class using something like this
// apps/libs/extensions/Request.php namespace Libs\Extensions; class Request extends \Illuminate\Http\Request { // code goes here }
I have put my class in apps/libs/extensions
folder but you may put it where you like. Once you extended the class, open the bootstrap/start.php
file. This file is one of the very first files to be included on each request to your application. The first line of code in this file is
$app = new Illuminate\Foundation\Application;
Which creates an instance of Illuminate\Foundation\Application
and inside this class, you can see something like this
public function __construct(Request $request = null) { $this['request'] = $this->createRequest($request); // other code }
When any application is instantiated, it creates a new Illuminate\Http\Request
instance and it happens before any Events are fired or any Service Providers or Aliases
are registered. So, instead of using the conventional way to extend and use it via service provider we should extend it normally we did in the example given above and after extending the class we can just replace the following line in the bootstrap/start.php
file
$app = new Illuminate\Foundation\Application;
with this two lines of code
$request = Libs\Extensions\Request::createFromGlobals(); $app = new Illuminate\Foundation\Application( $request );
Once we are done with this, we have to add "app/libs/extensions"
in our composer.json file, in classmap
array of autoload
section something like this
"autoload": { "classmap": [ "app/commands", "app/controllers", "app/models", "app/database/migrations", "app/database/seeds", "app/tests", "app/tests/TestCase.php", "app/libs/extensions" ] }
Finally, from the console, execute composer dumpautoload
and you are done. Well, recently I’ve answered a question on StackOverflow and question was to use Input::only
method with wildcard, like $actInputs = Input::only('act*');
which should return all the inputs whose name begins with act
such as acting, actor etc and after answering that question I’ve extended the functionality of Input
or say Request
, so here is the full code of my extended class
Use of new methods in
Input
orRequest
class// return inputs that starts with f (first_name, fathers_name) $inputs = Input::inputStartsWith("f"); // return inputs that ends with _name (first_name, last_name) $inputs = Input::inputEndsWith("_name"); // return inputs that matches digit at the end (name1, name2 etc) $inputs = Input::InputMatching("/^.*\d$/");I've extended and tested it on my local
Laravel
installation and works just fine. Hope it could be helpful.