There is no 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.
If you don’t want to read the full article and just want to find out the main topic then you may directly
jump here.
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
or Request
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.