Commit baf46fa8 authored by Taylor Otwell's avatar Taylor Otwell

Merge branch 'develop'

parents 50c37f1d 7d50f5f9
## Authentication Configuration
Most interactive applications have the ability for users to login and logout. Obvious, right? Laravel provides a simple class to help you validate user credentials and retrieve information about the current user of your application.
The quickest way to get started is to create an [Eloquent User model](/docs/database/eloquent) in your **application/models** directory:
class User extends Eloquent {}
Next, you will need to define **email** and **password** columns on your user database table. The password column should hold 60 alpha-numeric characters. The Auth class **requires** that all passwords be hashed and salted.
> **Note:** The password column on your user table must really be named "password".
Great job! You're ready to start using the Auth class. However, there are more advanced configuration options available if you wish to use them.
Let's dig into the **application/config/auth.php** file. In this file you will find two closures: **by\_id** and **by\_username**:
'by_id' => function($id)
{
return User::find($id);
}
The **by_id** function is called when the Auth class needs to retrieve a user by their primary key. As you can see, the default implementation of this function uses an "User" Eloquent model to retrieve the user by ID. However, if you are not using Eloquent, you are free to modify this function to meet the needs of your application.
'by_username' => function($username)
{
return User::where('email', '=', $username)->first();
}
The **by_username** function is called when the Auth class needs to retrieve a user by their username, such as when using the **login** method. The default implementation of this function uses an "User" Eloquent model to retrieve the user by e-mail address. However, if you are not using Eloquent or do not wish to use e-mail addresses as usernames, you are free to modify this function as you wish as long as you return an object with **password** and **id** properties.
\ No newline at end of file
## Authentication Usage
- [Salting & Hashing](#hash)
- [Logging In](#login)
- [Protecting Routes](#filter)
- [Retrieving The Logged In User](#user)
- [Logging Out](#logout)
> **Note:** Before using the Auth class, you must [specify a session driver](/docs/session/config).
<a name="hash"></a>
### Salting & Hashing
If you are using the Auth class, Laravel requires all passwords to be hashed and salted. Web development must be done responsibly. Salted, hashed passwords make a rainbow table attack against your user's passwords impractical.
Don't worry, salting and hashing passwords is easy using the **Hash** class. The Hash class provides a simple way to hash passwords using the **bcrypt** hashing algorithm. Check out this example:
$password = Hash::make('secret');
The **make** method of the Hash class will return a 60 character hashed string.
You can compare an unhashed value against a hashed one using the **check** method on the **Hash** class:
if (Hash::check('secret', $hashed_value))
{
return 'The password is valid!';
}
> **Note:** Before using the Auth class, be sure to [create the "password" column](/docs/auth/config) on your user table.
<a name="login"></a>
### Logging In
Logging a user into your application is simple using the **login** method on the Auth class. Simply pass the username and password of the user to the method. The login method will return **true** if the credentials are valid. Otherwise, **false** will be returned:
if (Auth::login('example@gmail.com', 'password'))
{
return Redirect::to('user/profile');
}
If the user's credentials are valid, the user ID will be stored in the session and the user will be considered "logged in" on subsequent requests to your application.
To determine if the user of your application is logged in, call the **check** method:
if (Auth::check())
{
return "You're logged in!";
}
<a name="filter"></a>
### Protecting Routes
It is common to limit access to certain routes only to logged in users. It's a breeze in Laravel using the built-in [auth filter](/docs/start/routes#filters). If the user is logged in, the request will proceed as normal; however, if the user is not logged in, they will be redirected to the "login" [named route](/docs/start/routes#named).
To protect a route, simply attach the **auth** filter:
'GET /admin' => array('before' => 'auth', 'do' => function() {})
> **Note:** You are free to edit the **auth** filter however you like. A default implementation is located in **application/filters.php**.
<a name="user"></a>
### Retrieving The Logged In User
Once a user has logged in to your application, you may easily access the user model via the **user** method on the Auth class:
return Auth::user()->email;
> **Note:** If the user is not logged in, the **user** method will return NULL.
<a name="logout"></a>
### Logging Out
Ready to log the user out of your application? It's simple:
Auth::logout();
This method will remove the user ID from the session, and the user will no longer be considered logged in on subsequent requests to your application.
\ No newline at end of file
## Cache Configuration
- [Memcached](#memcached)
- [Cache Keys](#keys)
Imagine your application displays the ten most popular songs as voted on by your users. Do you really need to look up these ten songs every time someone visits your site? What if you could store them for 10 minutes, or even an hour, allowing you to dramatically speed up your application? Caching makes it simple.
Laravel provides three wonderful cache drivers out of the box:
- File System
- Memcached
- APC
By default, Laravel is configured to use the **file** system cache driver. It's ready to go. The file system driver stores cached items as files in the **application/storage/cache** directory. If you're satisfied with this driver, no other configuration is required. You're ready to start using it.
> **Note:** Before using the file system cache driver, make sure your **application/storage/cache** directory is writeable.
<a name="memcached"></a>
### Memcached
[Memcached](http://memcached.org) is an ultra-fast, open-source distributed memory object caching system used by sites such as Wikipedia and Facebook. Before using Laravel's Memcached driver, you will need to install and configure Memcached and the PHP Memcache extension on your server.
Once Memcached is installed on your server, configuring the Laravel driver is a breeze. First, set the **driver** in the **application/config/cache.php** file:
'driver' => 'memcached'
Next, add your Memcached servers to the **servers** array:
'servers' => array(
array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100),
)
<a name="keys"></a>
### Cache Keys
To avoid naming collisions with other applications using APC or a Memcached server, Laravel prepends a **key** to each item stored in the cache using these drivers. Feel free to change this value:
'key' => 'laravel'
\ No newline at end of file
## Cache Usage
- [Storing Items](#put)
- [Retrieving Items](#get)
- [Removing Items](#forget)
<a name="put"></a>
### Storing Items
Storing items in the cache is simple. Simply call the **put** method on the Cache class:
Cache::put('name', 'Taylor', 10);
The first parameter is the **key** to the cache item. You will use this key to retrieve the item from the cache. The second parameter is the **value** of the item. The third parameter is the number of **minutes** you want the item to be cached.
> **Note:** It is not necessary to serialize objects when storing them in the cache.
<a name="get"></a>
### Retrieving Items
Retrieving items from the cache is even more simple than storing them. It is done using the **get** method. Just mention the key of the item you wish to retrieve:
$name = Cache::get('name');
By default, NULL will be returned if the cached item has expired or does not exist. However, you may pass a different default value as a second parameter to the method:
$name = Cache::get('name', 'Fred');
Now, "Fred" will be returned if the "name" cache item has expired or does not exist.
What if you need a value from your database if a cache item doesn't exist? The solution is simple. You can pass a closure into the **get** method as a default value. The closure will only be executed if the cached item doesn't exist:
$users = Cache::get('count', function() {return DB::table('users')->count();});
Let's take this example a step further. Imagine you want to retrieve the number of registered users for your application; however, if the value is not cached, you want to store the default value in the cache. It's a breeze using the **remember** method:
$users = Cache::remember('count', function() {return DB::table('users')->count();}, 5);
Let's talk through that example. If the **count** item exists in the cache, it will be returned. If it doesn't exist, the result of the closure will be stored in the cache for five minutes **and** be returned by the method. Slick, huh?
Laravel even gives you a simple way to determine if a cached item exists using the **has** method:
if (Cache::has('name'))
{
$name = Cache::get('name');
}
<a name="forget"></a>
### Removing Items
Need to get rid of a cached item? No problem. Just mention the name of the item to the **forget** method:
Cache::forget('name');
\ No newline at end of file
## Getting Started
- [Requirements & Installation](/docs/start/install)
- [Basic Configuration](/docs/start/config)
- [Routes](/docs/start/routes)
- [Defining Routes](/docs/start/routes#define)
- [Wildcard URI Segments](/docs/start/routes#segments)
- [Named Routes](/docs/start/routes#named)
- [Route Filters](/docs/start/routes#filters)
- [Organizing Routes](/docs/start/routes#organize)
- [Views & Responses](/docs/start/views)
- [Creating Views](/docs/start/views#create)
- [Binding Data To Views](/docs/start/views#bind)
- [Nesting Views Within Views](/docs/start/views#nest)
- [Redirects](/docs/start/views#redirect)
- [Downloads](/docs/start/views#downloads)
- [Building URLs](/docs/start/views#urls)
- [Building HTML](/docs/start/views#html)
- [Interaction](/docs/start/interaction)
- [Input](/docs/start/interaction#basics)
- [Old Input](/docs/start/interaction#old)
- [Cookies](/docs/start/interaction#cookies)
- [Building Forms](/docs/start/interaction#forms)
- [Data Validation](/docs/start/validation)
## Database
- [Configuration](/docs/database/config)
- [Usage](/docs/database/usage)
- [Fluent Query Builder](/docs/database/query)
- [Eloquent ORM](/docs/database/eloquent)
## Caching
- [Configuration](/docs/cache/config)
- [Usage](/docs/cache/usage)
## Sessions
- [Configuration](/docs/session/config)
- [Usage](/docs/session/usage)
## Authentication
- [Configuration](/docs/auth/config)
- [Usage](/docs/auth/usage)
## Other Topics
- [Working With Files](/docs/other/file)
- [Localization](/docs/other/lang)
- [Encryption](/docs/other/crypt)
- [Benchmarking Code](/docs/other/benchmark)
\ No newline at end of file
## Database Configuration
- [Quick Start Using SQLite](#quick)
- [Configuring MySQL or PostgreSQL](#server)
- [Setting The Default Connection Name](#default)
Database configuration in Laravel is easy. The hardest part is deciding which database to use. Three popular open-source databases are supported out of the box:
- MySQL
- PostgreSQL
- SQLite
All of the database configuration options live in the **application/config/db.php** file. Let's get started.
<a name="quick"></a>
### Quick Start Using SQLite
[SQLite](http://sqlite.org) is an awesome, zero-configuration database system. By default, Laravel is configured to use a SQLite database. Really, you don't have to change anything. Just drop a SQLite database named **application.sqlite** into the **application/storage/db directory**. You're done.
Of course, if you want to name your database something besides "application", you can modify the database option in the SQLite section of the **application/config/db.php** file:
'sqlite' => array(
'driver' => 'sqlite',
'database' => 'your_database_name',
)
If your application receives less than 100,000 hits per day, SQLite should be suitable for production use in your application. Otherwise, consider using MySQL or PostgreSQL.
> **Note:** Need a good SQLite manager? Check out this [Firefox extension](https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/).
<a name="server"></a>
### Configuring MySQL or PostgreSQL
If you are using MySQL or PostgreSQL, you will need to edit the configuration options in **application/config/db.php**. Don't worry. In the configuration file, sample configurations exist for both systems. All you need to do is change the options as necessary for your server and set the default connection name.
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
),
<a name="default"></a>
### Setting The Default Connection Name
As you have probably noticed, each database connection defined in the **application/config/db.php** file has a name. By default, there are three connections defined: **sqlite**, **mysql**, and **pgsql**. You are free to change these connection names. The default connection can be specified via the **default** option:
'default' => 'sqlite';
The default connection will always be used by the [fluent query builder](/docs/database/query) and [Eloquent ORM](/docs/database/eloquent). If you need to change the default connection during a request, use the **Config::set** method.
\ No newline at end of file
This diff is collapsed.
## Fluent Query Builder
- [Retrieving Records](#get)
- [Building Where Clauses](#where)
- [Dynamic Where Clauses](#dynamic)
- [Table Joins](#joins)
- [Ordering Results](#ordering)
- [Skip & Take](#limit)
- [Aggregates](#aggregates)
- [Inserting Records](#insert)
- [Updating Records](#update)
- [Deleting Records](#delete)
Laravel provides an awesome, easy-to-use fluent interface for building SQL queries and working with your database. All queries use prepared statements and are protected against SQL injection. Working with your database doesn't have to be a headache.
You can begin a fluent query using the **table** method on the DB class. Just mention the table you wish to query:
$query = DB::table('users');
You now have a fluent query builder for the "users" table. Using this query builder, you can retrieve, insert, update, or delete records from the table.
<a name="get"></a>
### Retrieving Records
There are two methods available for retrieving records using a fluent query: **get** and **first**. The **get** method will return an array of records from your database. Each record will be an object with properties corresponding to the columns of the table:
$users = DB::table('users')->get();
foreach ($users as $user)
{
echo $user->email;
}
Instead of returning an array, the **first** method will return a single object:
$user = DB::table('users')->first();
echo $user->email;
It's easy to limit the columns returned by your query. Simply pass an array of columns you want into the **get** or **first** method:
$user = DB::table('users')->get(array('id', 'email as user_email'));
Need to get distinct records from the database? It's easy. Call the **distinct** method before retrieving your records:
$user = DB::table('users')->distinct()->get();
> **Note:** If no results are found, the **first** method will return NULL. The **get** method will return an empty array.
<a name="where"></a>
### Building Where Clauses
#### where and or\_where
Building WHERE clauses in Laravel is painless. There are a variety of methods to assist you. The most basic of these methods are the **where** and **or_where** methods. Here is how to use them:
return DB::table('users')
->where('id', '=', 1)
->or_where('email', '=', 'example@gmail.com')
->first();
Of course, you are not limited to simply checking equality. You may also use **greater-than**, **less-than**, **not-equal**, and **like**:
return DB::table('users')
->where('id', '>', 1)
->or_where('name', 'LIKE', '%Taylor%')
->first();
You may have assumed that the **where** method will add to the query using an AND condition, while the **or_where** method will use an OR condition. You assumed correctly.
#### where\_in, where\_not\_in, or\_where\_in, and or\_where\_not\_in
The suite of **where_in** methods allows you to easily construct queries that search an array of values:
DB::table('users')->where_in('id', array(1, 2, 3))->get();
DB::table('users')->where_not_in('id', array(1, 2, 3))->get();
DB::table('users')
->where('email', '=', 'example@gmail.com')
->or_where_in('id', array(1, 2, 3))
->get();
DB::table('users')
->where('email', '=', 'example@gmail.com')
->or_where_not_in('id', array(1, 2, 3))
->get();
#### where\_null, where\_not\_null, or\_where\_null, and or\_where\_not\_null
The suite of **where_null** methods makes checking for NULL values a piece of cake:
return DB::table('users')->where_null('updated_at')->get();
return DB::table('users')->where_not_null('updated_at')->get();
return DB::table('users')
->where('email', '=', 'example@gmail.com')
->or_where_null('updated_at')
->get();
return DB::table('users')
->where('email', '=', 'example@gmail.com')
->or_where_not_null('updated_at')
->get();
<a name="dynamic"></a>
### Dynamic Where Clauses
Ready for some really beautiful syntax? Check out **dynamic where methods**:
$user = DB::table('users')->where_email('example@gmail.com')->first();
$user = DB::table('users')->where_email_and_password('example@gmail.com', 'secret');
$user = DB::table('users')->where_id_or_name(1, 'Fred');
Aren't they a breathe of fresh air?
<a name="joins"></a>
### Table Joins
Need to join to another table? Try the **join** and **left\_join** methods:
DB::table('users')
->join('phone', 'users.id', '=', 'phone.user_id')
->get(array('users.email', 'phone.number'));
The **table** you wish to join is passed as the first parameter. The remaining three parameters are used to construct the **ON** clause of the join.
Once you know how to use the join method, you know how to **left_join**. The method signatures are the same:
DB::table('users')
->left_join('phone', 'users.id', '=', 'phone.user_id')
->get(array('users.email', 'phone.number'));
<a name="ordering"></a>
### Ordering Results
You can easily order the results of your query using the **order_by** method. Simply mention the column and direction (desc or asc) of the sort:
return DB::table('users')->order_by('email', 'desc')->get();
Of course, you may sort on as many columns as you wish:
return DB::table('users')
->order_by('email', 'desc')
->order_by('name', 'asc')
->get();
<a name="limit"></a>
### Skip & Take
If you would like to **LIMIT** the number of results returned by your query, you can use the **take** method:
return DB::table('users')->take(10)->get();
To set the **OFFSET** of your query, use the **skip** method:
return DB::table('users')->skip(10)->get();
<a name="aggregates"></a>
### Aggregates
Need to get a **MIN**, **MAX**, **AVG**, **SUM**, or **COUNT** value? Just pass the column to the query:
$min = DB::table('users')->min('age');
$max = DB::table('users')->max('weight');
$avg = DB::table('users')->avg('salary');
$sum = DB::table('users')->sum('votes');
$count = DB::table('users')->count();
Of course, you may wish to limit the query using a WHERE clause first:
$count = DB::table('users')->where('id', '>', 10)->count();
<a name="insert"></a>
### Inserting Records
Inserting records is amazingly easy using the **insert** method. The method only expects an array of values to insert. It couldn't be simpler. The insert method will simply return true or false, indicating whether the query was successful:
DB::table('users')->insert(array('email' => 'example@gmail.com'));
Inserting a record that has an auto-incrementing ID? You can use the **insert\_get\_id** method to insert a record and retrieve the ID:
$id = DB::table('users')->insert_get_id(array('email' => 'example@gmail.com'));
> **Note:** The **insert\_get\_id** method expects the name of the auto-incrementing column to be "id".
<a name="update"></a>
### Updating Records
Updating records is just as simple as inserting them. Simply pass an array of values to the **update** method:
$affected = DB::table('users')->update(array('email' => 'new_email@gmail.com'));
Of course, when you only want to update a few records, you should add a WHERE clause before calling the update method:
$affected = DB::table('users')
->where('id', '=', 1)
->update(array('email' => 'new_email@gmail.com'));
<a name="delete"></a>
### Deleting Records
When you want to delete records from your database, simply call the **delete** method:
$affected = DB::table('users')->where('id', '=', 1)->delete();
Want to quickly delete a record by its ID? No problem. Just pass the ID into the delete method:
$affected = DB::table('users')->delete(1);
\ No newline at end of file
## Database Usage
### Queries
Running queries against a database connection is a breeze using the **query** method on the DB class:
$users = DB::query('select * from users');
The **query** method also allows you to specify bindings for your query in the second parameter to the method:
$users = DB::query('select * from users where name = ?', array('test'));
The return value of the query method depends on the type of query that is executed:
- **SELECT** statements will return an array of stdClass objects with properties corresponding to each column on the table.
- **INSERT** statements will return **true** or **false**, depending on the success of the query.
- **UPDATE** and **DELETE** statements will return the number of rows affected by the query.
### Connections
Need to get the raw PDO object for a connection? It's easy. Just mention the connection name to the **connection** method on the DB class:
$pdo = DB::connection('sqlite');
> **Note:** If no connection name is specified, the **default** connection will be returned.
### Driver
Want to know which PDO driver is being used for a connection? Check out the **driver** method:
$driver = DB::driver('connection_name');
> **Note:** If no connection name is specified, the **default** connection driver will be returned.
\ No newline at end of file
## Benchmarking Code
- [The Basics](#basics)
- [Using Timers](#timers)
- [Checking Memory Usage](#memory)
<a name="basics"></a>
### The Basics
When making changes to your code, it's helpful to know the performance impact of your changes. Laravel provides a simple class to help you time code execution and check memory consumption. It's called the **Benchmark** class and it's a breeze to use.
<a name="timers"></a>
### Using Timers
To start a timer, simply call the **start** method on the Benchmark class and give your timer a name:
Benchmark::start('foo');
Pretty easy, right?
You can easily check how much time has elapsed (in milliseconds) using the **check** method. Again, just mention the name of the timer to the method:
echo Benchmark::check('foo');
<a name="memory"></a>
### Checking Memory Usage
Need to know how much memory is being used by your application? No problem. Just call the **memory** method to get your current memory usage in megabytes:
echo Benchmark::memory();
\ No newline at end of file
## Encryption
- [The Basics](#basics)
- [Encrypting A String](#encrypt)
- [Decrypting A String](#decrypt)
<a name="basics"></a>
### The Basics
Need to do secure, two-way encryption? Laravel has you covered with the **Crypt** class. The Crypt class provides strong AES-256 encryption and decryption out of the box via the Mcrypt PHP extension.
To get started, you must set your **application key** in the **application/config/application.php** file. This key should be very random and very secret, as it will be used during the encryption and decryption process. It is best to use a random, 32 character alpha-numeric string:
'key' => 'xXSAVghP7myRo5xqJAnMvQwBc7j8qBZI';
Wonderful. You're ready to start encrypting.
> **Note:** Don't forget to install the Mcrypt PHP extension on your server.
<a name="encrypt"></a>
### Encrypting A String
Encrypting a string is a breeze. Just pass it to the **encrypt** method on the Crypt class:
Crypt::encrypt($value);
Do you feel like James Bond yet?
<a name="decrypt"></a>
### Decrypting A String
So you're ready to decrypt a string? It's simple. Just use the **decrypt** method on the Crypt class:
Crypt::decrypt($encrypted_value);
> **Note:** The decrypt method will only decrypt strings that were encrypted using **your** application key.
\ No newline at end of file
## Working With Files
- [Reading Files](#get)
- [Writing Files](#put)
- [File Uploads](#upload)
- [File Extensions](#ext)
- [Checking File Types](#is)
- [Getting MIME Types](#mime)
<a name="get"></a>
### Reading Files
It's a breeze to get the contents of a file using the **get** method on the **File** class:
$contents = File::get('path/to/file');
<a name="put"></a>
### Writing Files
Need to write to a file? Check out the **put** method:
File::put('path/to/file', 'file contents');
Want to append to the file instead of overwriting the existing contents? No problem. Use the **append** method:
File::append('path/to/file', 'appended file content');
<a name="upload"></a>
### File Uploads
After a file has been uploaded to your application, you will want to move it from its temporary location to a permanent directory. You can do so using the **upload** method. Simply mention the **name** of the uploaded file and the path where you wish to store it:
File::upload('picture', 'path/to/pictures');
> **Note:** You can easily validate file uploads using the [Validator class](/docs/start/validation).
<a name="ext"></a>
### File Extensions
Need to get the extension of a file? Just pass the filename to the **extension** method:
File::extension('picture.png');
<a name="is"></a>
### Checking File Types
Often, it is important to know the type of a file. For instance, if a file is uploaded to your application, you may wish to verify that it is an image. It's easy using the **is** method on the **File** class. Simply pass the extension of the file type you are expecting. Here's how to verify that a file is a JPG image:
if (File::is('jpg', 'path/to/file.jpg'))
{
//
}
The **is** method does not simply check the file extension. The Fileinfo PHP extension will be used to read the content of the file and determine the actual MIME type. Pretty cool, huh?
> **Note:** You may pass any of the extensions defined in the **application/config/mimes.php** file to the **is** method.
<a name="mime"></a>
### Getting MIME Types
Need to know the MIME type associated with a file extension? Check out the **mime** method:
echo File::mime('gif');
The statement above returns the following string:
image/gif
> **Note:** This method simply returns the MIME type defined for the extension in the **application/config/mimes.php** file.
\ No newline at end of file
## Localization
- [The Basics](#basics)
- [Retrieving A Language Line](#get)
- [Place Holders & Replacements](#replace)
<a name="basics"></a>
### The Basics
Localization is the process of translating your application into different languages. The **Lang** class provides a simple mechanism to help you organize and retrieve the text of your multilingual application.
All of the language files for your application live under the **application/lang** directory. Within the **application/lang** directory, you should create a directory for each language your application speaks. So, for example, if your application speaks English and Spanish, you might create **en** and **sp** directories under the **lang** directory.
Each language directory may contain many different language files. Each language file is simply an array of string values in that language. In fact, language files are structured identically to configuration files. For example, within the **application/lang/en** directory, you could create a **marketing.php** file that looks like this:
return array(
'welcome' => 'Welcome to our website!',
);
Next, you should create a corresponding **marketing.php** file within the **application/lang/sp** directory. The file would look something like this:
return array(
'welcome' => 'Bienvenido a nuestro sitio web!',
);
Nice! Now you know how to get started setting up your language files and directories. Let's keep localizing!
<a name="basics"></a>
### Retrieving A Language Line
To retrieve a language line, first create a Lang instance using the **line** method, then call the **get** method on the instance:
echo Lang::line('marketing.welcome')->get();
Notice how a dot was used to separate "marketing" and "welcome"? The text before the dot corresponds to the language file, while the text after the dot corresponds to a specific string within that file.
But, how did the method know which language directory to retrieve the message from? By default, the **get** method will use the language specified in your **application/config/application.php** configuration file. In this file you may set the default language of your application using the **language** option:
'language' => 'en'
Need to retrieve the line in a language other than your default? Not a problem. Just mention the language to the **get** method:
echo Lang::line('marketing.welcome')->get('sp');
<a name="replace"></a>
### Place Holders & Replacements
Now, let's work on our welcome message. "Welcome to our website!" is a pretty generic message. It would be helpful to be able to specify the name of the person we are welcoming. But, creating a language line for each user of our application would be time-consuming and ridiculous. Thankfully, you don't have to. You can specify "place-holders" within your language lines. Place-holders are preceeded by a colon:
'welcome' => 'Welcome to our website, :name!'
Then, simply pass an array of place-holder replacements to the **replace** method on a Lang instance:
echo Lang::line('marketing.welcome')->replace(array('name' => 'Taylor'))->get();
This statement will return a nice, heart-warming welcome message:
Welcome to our website, Taylor!
\ No newline at end of file
<a name="config"></a>
## Session Configuration
- [File System Sessions](#file)
- [Database Sessions](#database)
- [Memcached Sessions](#memcached)
The web is a stateless environment. This means that each request to your application is considered unrelated to any previous request. However, **sessions** allow you to store arbitrary data for each visitor to your application. The session data for each visitor is stored on your web server, while a cookie containing a **session ID** is stored on the visitor's machine. This cookie allows your application to "remember" the session for that user and retrieve their session data on subsequent requests to your application.
Sound complicated? If so, don't worry about it. Just tell Laravel where to store the sessions and it will take care of the rest.
Three great session drivers are available out of the box:
- File System
- Database
- Memcached
<a name="file"></a>
### File System Sessions
Most likely, your application will work great using file system sessions. However, if your application receives heavy traffic or runs on a server farm, use database or Memcached sessions.
To get started using file system sessions, just set the driver option in the **application/config/session.php** file:
'driver' => 'file'
That's it. You're ready to go!
> **Note:** File system sessions are stored in the **application/storage/sessions** directory, so make sure it's writeable.
<a name="database"></a>
### Database Sessions
To start using database sessions, you will first need to [configure your database connection](/docs/database/config).
Already setup your database? Nice! Next, you will need to create a session table. Here are some SQL statements to help you get started:
#### SQLite
CREATE TABLE "sessions" (
"id" VARCHAR PRIMARY KEY NOT NULL UNIQUE,
"last_activity" INTEGER NOT NULL,
"data" TEXT NOT NULL
);
#### MySQL
CREATE TABLE `sessions` (
`id` VARCHAR(40) NOT NULL,
`last_activity` INT(10) NOT NULL,
`data` TEXT NOT NULL,
PRIMARY KEY (`id`)
);
If you would like to use a different table name, simply change the **table** option in the **application/config/session.php** file:
'table' => 'sessions'
Great! All you need to do now is set the driver in the **application/config/session.php** file:
'driver' => 'db'
<a name="memcached"></a>
### Memcached Sessions
Before using Memcached sessions, you must [configure your Memcached servers](/docs/cache/config#memcached).
All done? Great! Just set the driver in the **application/config/session.php** file:
'driver' => 'memcached'
\ No newline at end of file
## Session Usage
- [Storing Items](#put)
- [Retrieving Items](#get)
- [Removing Items](#forget)
- [Regeneration](#regeneration)
<a name="put"></a>
### Storing Items
Storing items in the session is a breeze. Simply call the put method on the Session class:
Session::put('name', 'Taylor');
The first parameter is the **key** to the session item. You will use this key to retrieve the item from the session. The second parameter is the **value** of the item.
Need to store an item in the session that should expire after the next request? Check out the **flash** method. It provides an easy way to store temporary data like status or error messages:
Session::flash('status', 'Welcome Back!');
<a name="get"></a>
### Retrieving Items
Retrieving items from the session is no problem. You can use the **get** method on the Session class to retrieve any item in the session, including flash data. Just pass the key of the item you wish to retrieve:
$name = Session::get('name');
By default, NULL will be returned if the session item does not exist. However, you may pass a default value as a second parameter to the get method:
$name = Session::get('name', 'Fred');
$name = Session::get('name', function() {return 'Fred';});
Now, "Fred" will be returned if the "name" item does not exist in the session.
Laravel even provides a simple way to determine if a session item exists using the **has** method:
if (Session::has('name'))
{
$name = Session::get('name');
}
<a name="forget"></a>
### Removing Items
Need to get rid of a session item? No problem. Just mention the name of the item to the **forget** method on the Session class:
Session::forget('name');
You can even remove all of the items from the session using the **flush** method:
Session::flush();
<a name="regeneration"></a>
### Regeneration
Sometimes you may want to "regenerate" the session ID. This simply means that a new, random session ID will be assigned to the session. Here's how to do it:
Session::regenerate();
\ No newline at end of file
## Basic Configuration
- [Quick Start](#quick)
- [Cleaner URLs](#clean)
- [Errors & Logging](#errors)
<a name="quick"></a>
### Quick Start
When starting a new project, you shouldn't be bombarded with loads of confusing configuration decisions. For that reason, Laravel is intelligently configured out of the box. The **application/config/application.php** file contains the basic configuration options for your application.
There is only one option that **must** be set when starting a new application. Laravel needs to know the URL you will use to access your application. Simply set the url in the **application/config/application.php** file:
'url' => 'http://localhost';
> **Note:** If you are using mod_rewrite, you should set the index option to an empty string.
<a name="clean"></a>
### Cleaner URLs
Most likely, you do not want your application URLs to contain "index.php". You can remove it using HTTP rewrite rules. If you are using Apache to serve your application, make sure to enable mod_rewrite and create a **.htaccess** file like this one in your **public** directory:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
Is the .htaccess file above not working for you? Try this one:
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
After setting up HTTP rewriting, you should set the **index** configuration option in **application/config/application.php** to an empty string.
> **Note:** Each web server has a different method of doing HTTP rewrites, and may require a slightly different .htaccess file.
<a name="errors"></a>
### Errors & Logging
- [404 Errors](#error-404)
- [Error Detail](#error-detail)
- [Logging](#error-logging)
<a name="error-404"></a>
#### 404 Errors
When a request is made to your application that cannot be matched to a route, the 404 error view will be sent to the browser. This view lives in **application/views/error/404.php** and you are free to modify it however you wish.
<a name="error-detail"></a>
#### Error Detail
You can easily control the level of error detail via the **detail** option in the **application/config/errors.php** file.
'detail' => true;
When set to **true**, error messages will be detailed with a stack trace and snippet of the relevant file. When set to **false**, the generic error page (**application/views/error/500.php**) will be displayed. Feel free to modify this view.
> **Note:** In a production environment, it is strongly suggested that you turn off error details.
<a name="error-logging"></a>
#### Logging
You may wish to log any errors that occur in your application. Laravel makes it a breeze. You can turn on logging by setting the log option to **true** in the **application/config/errors.php** file:
'log' => true;
You have total control over how your errors are logged via the **logger** function defined in **application/config/error.php**. This function is called every time there is an unhandled error or exception in your application.
As you can see, the default logger implementation writes to the **application/storage/log.txt** file; however, you are free to modify this function however you wish.
\ No newline at end of file
## Requirements & Installation
### Requirements
- Apache, nginx, or another compatible web server.
- PHP 5.3+.
### Installation
1. [Download Laravel](https://github.com/taylorotwell/laravel/zipball/master)
2. Extract the Laravel archive and upload the contents to your web server.
4. Set the URL of your application in the **application/config/application.php** file.
5. Navigate to your application in a web browser.
If all is well, you should see a pretty Laravel splash page. Get ready, there is lots more to learn!
### Extras
Installing the following goodies will help you take full advantage of Laravel, but they are not required:
- SQLite, MySQL, or PostgreSQL PDO drivers.
- [Memcached](http://memcached.org) or APC.
### Problems?
- Make sure the **public** directory is the document root of your web server.
- If you are using mod_rewrite, set the **index** option in **application/config/application.php** to an empty string.
\ No newline at end of file
## Interaction
- [Input](/docs/start/interaction#basics)
- [Old Input](/docs/start/interaction#old)
- [Cookies](/docs/start/interaction#cookies)
- [Building Forms](/docs/start/interaction#forms)
All web applications receive input via HTTP requests. The input can be sent to your application via any of the four HTTP verbs: **GET**, **POST**, **PUT**, or **DELETE**. Input can also be sent to your application via cookies, which can store small amounts of information and are stored on the user's computer.
Let's dig into the classes Laravel provides for working with user input!
> **Note:** Laravel doesn't mess with your query strings. Feel free to use them.
<a name="basics"></a>
## Input
The **Input** class handles input that comes into your application via GET, POST, PUT, or DELETE requests. Retrieving input using the Input class is effortless. Just use the **get** method:
$email = Input::get('email');
> **Note:** The get method is used for all request types, not just GET requests. You may use it on POST, PUT, and DELETE requests as well.
By default, NULL will be returned if the input item does not exist. However, you may pass a different default value as a second parameter to the method:
$name = Input::get('name', 'Fred');
Now, "Fred" will be returned if the "name" input item does not exist. You may even pass a closure as a default value:
$name = Input::get('name', function() {return 'Fred';});
Need to determine if an input item exists? Use the **has** method:
if (Input::has('name'))
{
$name = Input::get('name');
}
> **Note:** The **has** method will return **false** if the input item exists but is an empty string.
Need to access the **$_FILES** array? It's easy using the **file** method:
$picture = Input::file('picture');
$size = Input::file('picture.size');
Sometimes you may need to merge the input and $_FILES array. Check out the **all** method:
$input = Input::all();
<a name="old"></a>
## Old Input
Have you ever tried to re-populate an input form after an invalid form submission? It can get pretty clunky. Not in Laravel. You can easily retrieve the input from the previous request using the **old** method on the Input class:
$name = Input::old('name');
> **Note:** You must specifiy a session driver before using the **old** Input method.
As you would expect, you may pass a default value in the second parameter to the method:
$name = Input::old('name', 'Fred');
Once again, there is a simple way to determine if an old input item exists using the **had** method:
if (Input::had('name'))
{
$name = Input::old('name');
}
<a name="cookies"></a>
## Cookies
The **Cookie** class provides simple functions for retrieving, setting, and deleting cookies.
To retrieve a cookie value, simply mention its name to the **get** method:
$name = Cookie::get('name');
Of course, just like the Input class, you may pass a default value in the second parameter to the **get** method:
$name = Cookie::get('name', 'Fred');
Also just like the Input class, the Cookie class has a simple method to determine if a cookie exists:
if (Cookie::has('name'))
{
$name = Cookie::get('name');
}
Need to create a cookie? No problem. Check out the **put** method:
Cookie::put('name', 'Fred', 60);
The put method accepts almost the exact same parameters as the PHP setcookie method. However, just pass the number of **minutes** you want the cookie to live as the third parameter. You don't have to worry about any clunky expiration date calculations.
If you need to create a "permanent" cookie, try the **forever** method. It creates a cookie that lives for five years:
Cookie::forever('name', 'Fred');
To delete a cookie, use the **forget** method:
Cookie::forget('name');
<a name="forms"></a>
## Building Forms
- [Opening A Form](#form-open)
- [CSRF Protection](#form-csrf)
- [Labels](#form-labels)
- [Text, Text Area, Password & Hidden Fields](#form-text)
- [Checkboxes & Radio Buttons](#form-check)
- [Drop-Down Lists](#form-lists)
- [Buttons](#form-buttons)
Almost every web application receives input through HTML forms. As you have probably already learned, Laravel is here to make your life easier. That's why generating forms using the **Form** class is a breeze.
> **Note:** All input data displayed in elements generated by the **Form** class is filtered through the HTML::entities method.
<a name="form-open"></a>
### Opening A Form
Opening a form is simple. Just call the **open** method on the Form class:
echo Form::open();
When called without any parameters, the open method will create a form that will POST to the current URL. However, you'll probably want to point your forms to other URLs too. No problem. Just mention the URL to the method. You can even specify the request method (GET, POST, PUT, or DELETE) in the second parameter to the method:
echo Form::open('user/profile', 'PUT');
Need to apply a class or other attribute to the form tag generated by the open method? Simply pass an array of attributes as a third parameter:
echo Form::open('user/profile', 'PUT', array('class' => 'awesome'));
> **Note:** The open method automatically prepares your form to receive UTF-8 input.
Need a form that can handle file uploads? Use the **open_for_files** method:
echo Form::open_for_files('user/profile');
<a name="form-csrf"></a>
### CSRF Protection
Laravel provides an easy method of protecting your application from [cross-site request forgeries](http://en.wikipedia.org/wiki/Cross-site_request_forgery). First, a random token is placed in your user's session. Don't sweat it, this is done automatically. Next, use the **token** method to generate a hidden form input field containing the random token on your form:
echo Form::token();
Now, simply [attach the built-in CSRF filter](/docs/start/routes#filters) to the route the form is posting to. If the token submitted by the form does not match the token in the user's session, the **application/views/error/500.php** view will be displayed.
Want to just get the CSRF token without generating a hidden input field? Use the **raw_token** method:
echo Form::raw_token();
> **Note:** Don't forget to [specify a session driver](/docs/session/config) before using these methods.
<a name="form-labels"></a>
### Labels
Need to generate a label for a form element? It's simple using the **label** method. Just pass the label name and display value to the method:
echo Form::label('email', 'E-Mail Address');
Of course, you may pass any attributes you wish in the third parameter to the method:
echo Form::label('email', 'E-Mail Address', array('class' => 'awesome'));
> **Note:** After creating a label, any form element you create with a name matching the label name will automatically receive an ID matching the label name as well.
<a name="form-text"></a>
### Text, Text Area, Password & Hidden Fields
Generating text boxes couldn't be easier. Just call the **text** method on the Form class and mention the name of the field:
echo Form::text('username');
Already have a value you want to put in the text box? Throw it in as a second parameter:
echo Form::text('email', 'example@gmail.com');
Again, any other attributes you wish to apply to the text box may be passed in an array as the third parameter:
echo Form::text('email', 'example@gmail.com', array('class' => 'awesome'));
> **Note:** The **password**, **hidden**, and **textarea** methods have the same signature as the text method. You just learned four methods for the price of one!
<a name="form-check"></a>
### Checkboxes & Radio Buttons
What website doesn't have a checkbox? Actually, this one doesn't! But, thankfully, generating them is simple using the **checkbox** method on the Form class. Just give the checkbox a name and a value:
echo Form::checkbox('remember', 'yes');
Of course, the example above will generate the following HTML:
<input type="checkbox" name="remember" value="yes">
Need to generate a "checked" checkbox? No problem. Simply pass **true** as the third parameter to the method:
echo Form::checkbox('remember', 'yes', true);
As always, you may specify any extra attributes that should be applied to the checkbox. Pass them as the fourth parameter to the method:
echo Form::checkbox('remember', 'yes', true, array('class' => 'awesome'));
> **Note:** The **radio** method has the same signature as the checkbox method. Two for one!
<a name="form-lists"></a>
### Drop-Down Lists
Generating drop-down lists can be a headache. Thankfully, Laravel makes it refreshingly simple using the **select** method on the Form class. All you need to do is give your list a name and an array of options:
echo Form::select('size', array('L' => 'Large', 'S' => 'Small'));
If you wish to set the selected item, just pass the value as the third parameter to the method:
echo Form::select('size', array('L' => 'Large', 'S' => 'Small'), 'S');
You may specify any other attributes that should be applied to the list in the fourth parameter to the method:
echo Form::select('size', array('L' => 'Large', 'S' => 'Small'), 'S', array('class' => 'awesome'));
<a name="form-buttons"></a>
### Buttons
Creating a submit button is a cinch. Use the **submit** method on the Form class:
echo Form::submit('Click Me!');
Again, any other attributes that should be applied to the button may be passed to the method:
echo Form::submit('Click Me!', array('class' => 'awesome'));
> **Note:** Need to create a button element? Try the **button** method. It has the same signature as submit.
\ No newline at end of file
## Routes
- [Defining Routes](/docs/start/routes#define)
- [Wildcard URI Segments](/docs/start/routes#segments)
- [Named Routes](/docs/start/routes#named)
- [Route Filters](/docs/start/routes#filters)
- [Organizing Routes](/docs/start/routes#organize)
Unlike other PHP frameworks, Laravel places routes and their corresponding functions in one file: **application/routes.php**. This file contains the "definition", or public API, of your application. To add functionality to your application, you add to the array located in this file. It's a breeze.
<a name="define"></a>
## Defining Routes
All you need to do is tell Laravel the request methods and URIs it should respond to. You define the behavior of the route using an anonymous method:
'GET /home' => function()
{
// Handles GET requests to http://example.com/index.php/home
},
You can easily define a route to handle requests to more than one URI. Just use commas:
'POST /, POST /home' => function()
{
// Handles POST requests to http://example.com and http://example.com/home
}
> **Note:** The routes.php file replaces the "controllers" found in most frameworks. Have a fat model and keep this file light and clean. Thank us later.
<a name="segments"></a>
## Wildcard URI Segments
Laravel makes matching wildcard URI segments a breeze using the **(:num)** and **(:any)** place-holders. Check out these routes:
'PUT /user/(:num)' => function($id) {}
'DELETE /user/(:any)' => function($username) {}
Laravel will automatically pass the value of the wildcard segment into your route function.
> **Note:** The **(:any)** place-holder matches letters, number, dashes, and underscores.
Want to make an URI segment optional? No problem. Just put a **?** in the place-holder:
'GET /download/(:any?)' => function($branch = 'master') {}
If you need more power and precision (or just want to be extra nerdy), you can even use regular expressions:
'GET /product/([0-9]+)' => function($id) {}
<a name="named"></a>
## Named Routes
Once you start using named routes, you won't be able to live without them. They are that great. Here's how to do it:
'GET /user/login' => array('name' => 'login', 'do' => function() {})
Notice the route now has an array value with two keys: **name** and **do**. As you learned while studying filters, the **do** value is the method that will be executed by the route. As you have probably guessed, the **name** value is the name of the route.
Now that you have named the route, you can [generate URLs](/docs/start/views#urls) and [perform redirects](/docs/start/views#redirect) using the route name instead of the route URI. This means that you can change the route URI as much as you want and the links to that route on your views will always be correct. It's beautiful, isn't it?
<a name="filters"></a>
## Route Filters
Filters are methods that run before and after a request to your application. "Before" filters can even halt the request cycle by returning a response, providing an amazingly simple way to implement common tasks like redirecting a user to a login view. Let's dig in.
All filters are defined in the **application/filters.php** file. Intuitive, right? If you open the file, you will see that four filters have already been defined for you: **before**, **after**, **auth**, and **csrf**. The **before** and **after** filters are the two "global" filters. They are always executed on every request, regardless of the request method or URI.
All other filters must be attached to individual routes. Don't worry, you'll learn how to do this soon. The built-in **auth** and **csrf** filters handle two scenarios that are common to almost every web application: redirecting users to a login page and protecting against cross-site request forgeries.
### Defining Filters
To define your own filter, simply add it to the array in the **application/filters.php** file:
'my_filter' => function()
{
return 'Filtered!';
}
### Attaching Filters To Routes
Alright, ready to attach the filter to a route? Do it like this:
'GET /user' => array('before' => 'my_filter', 'do' => function()
{
//
})
Notice the route now has an array value with two keys: **before** and **do**. The **do** value is the method that will be executed by the route, while the **before** value contains the names of any filters that should be run before the method is executed.
Why stop with one filter? You can define multiple filters for a single route by separating the filter names with commas:
'POST /user' => array('before' => 'auth, csrf', 'do' => function() {})
Remember, if a "before" filter returns a value, that value will be considered the output of the request. For example, the built-in **auth** filter checks if the user has logged in to your application. If they haven't, a [Redirect](/docs/start/views#redirect) to the login page is sent to the browser. Isn't the simplicity refreshing?
Of course, adding filters to run after the request is just as easy:
'my_filter' => function($response) {}
'GET /user' => array('after' => 'my_filter', 'do' => function() {})
> **Note:** "After" filters receive the response returned by the route function that handled the request.
<a name="organize"></a>
## Organizing Routes
So, you're building the next monolithic web application and your **application/routes.php** file is getting a little cramped? Don't worry, we have you covered.
Here's what to do. First, create an **application/routes** directory. Great! You're almost there. Now, just add route files to **application/routes** corresponding to the base URIs of your application. So, a **photo.php** file within **application/routes** would handle all requests to URIs beginning with **/photo**. Similarly, a **user.php** file handles all requests to URIs beginning with **/user**. For example, check out this **user.php** file:
<?php
return array(
'GET /user/profile/(:num)' => function($id)
{
return View::make('user/profile');
}
);
The **application/routes.php** file will continue to be loaded on every request, so any "catch-all" routes can still be placed in that file. The **application/routes.php** file should also still contain the route for the root of your application.
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<?php
// --------------------------------------------------------------
// Define the framework paths.
// --------------------------------------------------------------
define('BASE_PATH', realpath('../').'/');
define('APP_PATH', realpath('../application').'/');
define('SYS_PATH', realpath('../system').'/');
define('PUBLIC_PATH', realpath('../public').'/');
define('PACKAGE_PATH', APP_PATH.'packages/');
// --------------------------------------------------------------
// Define the PHP file extension.
// --------------------------------------------------------------
define('EXT', '.php');
// --------------------------------------------------------------
// Load the classes used by the auto-loader.
// --------------------------------------------------------------
require SYS_PATH.'config'.EXT;
require SYS_PATH.'arr'.EXT;
// --------------------------------------------------------------
// Load the test utilities.
// --------------------------------------------------------------
require 'utils'.EXT;
// --------------------------------------------------------------
// Register the auto-loader.
// --------------------------------------------------------------
spl_autoload_register(require SYS_PATH.'loader'.EXT);
\ No newline at end of file
<phpunit colors="true" bootstrap="bootstrap.php">
<testsuites>
<testsuite name="Laravel Tests">
<directory>suite</directory>
</testsuite>
</testsuites>
</phpunit>
\ No newline at end of file
<?php
class ArrTest extends PHPUnit_Framework_TestCase {
public function testReturnsDefaultWhenItemNotPresentInArray()
{
$this->assertNull(System\Arr::get(array(), 'name'));
$this->assertEquals(System\Arr::get(array(), 'name', 'test'), 'test');
$this->assertEquals(System\Arr::get(array(), 'name', function() {return 'test';}), 'test');
}
public function testReturnsItemWhenPresentInArray()
{
$this->assertEquals(System\Arr::get(array('name' => 'test'), 'name'), 'test');
}
}
\ No newline at end of file
<?php
class InputTest extends PHPUnit_Framework_TestCase {
public static function setUpBeforeClass()
{
System\Input::$input = null;
}
public static function tearDownAfterClass()
{
System\Config::set('session.driver', '');
System\Session::$session = array();
}
public function setUp()
{
$_SERVER['REQUEST_METHOD'] = 'GET';
}
public function tearDown()
{
System\Input::$input = null;
}
/**
* @dataProvider inputByMethodProvider
*/
public function testInputShouldHydrateBasedOnRequestMethod($method, $data)
{
$_SERVER['REQUEST_METHOD'] = $method;
$_GET = $data;
$_POST = $data;
$this->assertEquals(System\Input::get(), $data);
}
public function inputByMethodProvider()
{
return array(
array('GET', array('method' => 'GET')),
array('POST', array('method' => 'POST')),
);
}
/**
* @dataProvider inputBySpoofedMethodProvider
*/
public function testInputShouldHydrateBasedOnSpoofedRequestMethod($method, $data)
{
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST = $data;
$this->assertEquals(System\Input::get(), $data);
}
public function inputBySpoofedMethodProvider()
{
return array(
array('PUT', array('request_method' => 'PUT', 'method' => 'PUT')),
array('DELETE', array('request_method' => 'DELETE', 'method' => 'DELETE')),
);
}
public function testHasMethodReturnsTrueIfItemIsPresentInInputData()
{
System\Input::$input = array('name' => 'taylor');
$this->assertTrue(System\Input::has('name'));
}
public function testHasMethodReturnsFalseIfItemIsNotPresentInInputData()
{
System\Input::$input = array();
$this->assertFalse(System\Input::has('name'));
}
public function testHasMethodReturnsFalseIfItemIsInInputButIsEmptyString()
{
System\Input::$input = array('name' => '');
$this->assertFalse(System\Input::has('name'));
}
public function testGetMethodReturnsItemByInputKey()
{
System\Input::$input = array('name' => 'taylor');
$this->assertEquals(System\Input::get('name'), 'taylor');
}
public function testGetMethodReturnsDefaultValueWhenItemDoesntExist()
{
System\Input::$input = array();
$this->assertNull(System\Input::get('name'));
$this->assertEquals(System\Input::get('name', 'test'), 'test');
$this->assertEquals(System\Input::get('name', function() {return 'test';}), 'test');
$this->assertTrue(is_array(System\Input::get()) and count(System\Input::get()) == 0);
}
public function testGetMethodReturnsEntireInputArrayWhenNoKeyGiven()
{
System\Input::$input = array('name' => 'taylor', 'age' => 25);
$this->assertEquals(System\Input::get(), System\Input::$input);
}
public function testFileMethodReturnsItemFromGlobalFilesArray()
{
$_FILES['test'] = array('name' => 'taylor');
$this->assertEquals(System\Input::file('test'), $_FILES['test']);
}
public function testFileMethodReturnsSpecificItemFromFileArrayWhenSpecified()
{
$_FILES['test'] = array('size' => 500);
$this->assertEquals(System\Input::file('test.size'), 500);
}
public function testAllMethodReturnsBothGetAndFileArrays()
{
$_GET['name'] = 'test';
$_FILES['picture'] = array();
$this->assertArrayHasKey('name', System\Input::all());
$this->assertArrayHasKey('picture', System\Input::all());
}
/**
* @expectedException Exception
*/
public function testOldMethodShouldThrowExceptionWhenSessionsArentEnabled()
{
System\Input::old();
}
/**
* @expectedException Exception
*/
public function testHadMethodShouldThrowExceptionWhenSessionsArentEnabled()
{
System\Input::has();
}
public function testOldMethodShouldReturnOldInputDataFromSession()
{
System\Config::set('session.driver', 'test');
System\Session::$session['data']['laravel_old_input'] = array('name' => 'taylor');
$this->assertEquals(System\Input::old('name'), 'taylor');
}
public function testOldMethodReturnsDefaultValueWhenItemDoesntExist()
{
System\Config::set('session.driver', 'test');
System\Session::$session['data']['laravel_old_input'] = array();
$this->assertNull(System\Input::old('name'));
$this->assertEquals(System\Input::old('name', 'test'), 'test');
$this->assertEquals(System\Input::old('name', function() {return 'test';}), 'test');
$this->assertTrue(is_array(System\Input::old()) and count(System\Input::old()) == 0);
}
public function testHadMethodReturnsTrueIfItemIsPresentInOldInputData()
{
System\Config::set('session.driver', 'test');
System\Session::$session['data']['laravel_old_input'] = array('name' => 'taylor');
$this->assertTrue(System\Input::had('name'));
}
public function testHadMethodReturnsFalseIfItemIsNotPresentInOldInputData()
{
System\Config::set('session.driver', 'test');
System\Session::$session['data']['laravel_old_input'] = array();
$this->assertFalse(System\Input::had('name'));
}
}
\ No newline at end of file
<?php
class RequestTest extends PHPUnit_Framework_TestCase {
public function setUp()
{
unset($_SERVER['PATH_INFO'], $_SERVER['REQUEST_METHOD']);
$route = new System\Route(null, null);
$route->callback = array('name' => 'test', 'do' => function() {});
System\Request::$route = $route;
}
public function tearDown()
{
System\Request::$route = null;
}
/**
* @expectedException Exception
*/
public function testUriMethodThrowsExceptionWhenCantDetermineUri()
{
System\Request::uri();
}
public function testUriMethodReturnsPathInfoWhenSet()
{
$_SERVER['PATH_INFO'] = 'test';
$_SERVER['REQUEST_METHOD'] = 'blah';
$this->assertEquals(System\Request::uri(), 'test');
}
/**
* @dataProvider rootUriProvider1
*/
public function testUriMethodReturnsSingleSlashOnRequestForRoot($uri)
{
Config::set('application.url', 'http://example.com');
Config::set('appliation.index', '');
$_SERVER['REQUEST_URI'] = $uri;
$this->assertEquals(System\Request::uri(), '/');
}
public function rootUriProvider1()
{
return array(
array(''),
array('/'),
array('/index.php'),
array('/index.php/'),
array('/index.php///'),
array('http://example.com'),
array('http://example.com/'),
);
}
/**
* @dataProvider rootUriProvider2
*/
public function testUriMethodReturnsSingleSlashOnRequestForFolderNestedRoot($uri)
{
Config::set('application.url', 'http://example.com/laravel/public');
Config::set('appliation.index', 'index.php');
$_SERVER['REQUEST_URI'] = $uri;
$this->assertEquals(System\Request::uri(), '/');
}
public function rootUriProvider2()
{
return array(
array('http://example.com/laravel/public'),
array('http://example.com/laravel/public/index.php'),
array('http://example.com/laravel/public/index.php/'),
array('http://example.com/laravel/public/index.php///'),
array(''),
array('/'),
array('/index.php'),
array('/index.php/'),
array('/index.php///'),
array('http://example.com'),
array('http://example.com/'),
);
}
/**
* @dataProvider segmentedUriProvider1
*/
public function testUriMethodReturnsSegmentForSingleSegmentUri($uri)
{
Config::set('application.url', 'http://example.com');
Config::set('appliation.index', '');
$_SERVER['REQUEST_URI'] = $uri;
$this->assertEquals(System\Request::uri(), 'user');
}
public function segmentedUriProvider1()
{
return array(
array('http://example.com/user'),
array('http://example.com/user/'),
array('http://example.com/user//'),
);
}
/**
* @dataProvider segmentedUriProvider2
*/
public function testUriMethodReturnsSegmentsForMultiSegmentUri($uri)
{
Config::set('application.url', 'http://example.com');
Config::set('appliation.index', '');
$_SERVER['REQUEST_URI'] = $uri;
$this->assertEquals(System\Request::uri(), 'user/something');
}
public function segmentedUriProvider2()
{
return array(
array('http://example.com/user/something'),
array('http://example.com/user/something/'),
array('http://example.com/user/something//'),
);
}
public function testMethodForNonSpoofedRequests()
{
$_SERVER['REQUEST_METHOD'] = 'GET';
$this->assertEquals(System\Request::method(), 'GET');
}
public function testMethodForSpoofedRequests()
{
$_SERVER['REQUEST_METHOD'] = 'GET';
$_POST['REQUEST_METHOD'] = 'PUT';
$this->assertEquals(System\Request::method(), 'PUT');
$_POST['REQUEST_METHOD'] = 'DELETE';
$this->assertEquals(System\Request::method(), 'DELETE');
}
public function testRouteIsReturnsFalseWhenNoSuchNamedRouteExists()
{
$route = new System\Route(null, null);
$route->callback = function() {};
System\Request::$route = $route;
$this->assertFalse(System\Request::route_is('test'));
$this->assertFalse(System\Request::route_is_test());
}
public function testRouteIsReturnsFalseWhenWrongRouteNameIsGiven()
{
$this->assertFalse(System\Request::route_is('something'));
$this->assertFalse(System\Request::route_is_something());
}
public function testRouteIsReturnsTrueWhenNamedRouteExists()
{
$this->assertTrue(System\Request::route_is('test'));
$this->assertTrue(System\Request::route_is_test());
}
}
\ No newline at end of file
<?php
class RouteFilerTest extends PHPUnit_Framework_TestCase {
public static function setUpBeforeClass()
{
$filters = array(
'test' => function() {return 'test';},
'vars' => function($var) {return $var;},
'vars2' => function($var1, $var2) {return $var1.$var2;},
);
System\Route\Filter::$filters = $filters;
}
public static function tearDownAfterClass()
{
System\Route\Filter::$filters = require APP_PATH.'filters'.EXT;
}
/**
* @expectedException Exception
*/
public function testCallingUndefinedFilterThrowsException()
{
System\Route\Filter::call('not-found');
}
public function testCallingFilterWithoutOverrideReturnsNull()
{
$this->assertNull(System\Route\Filter::call('test'));
}
public function testCallingFilterWithOverrideReturnsResult()
{
$this->assertEquals(System\Route\Filter::call('test', array(), true), 'test');
}
public function testCallingFilterWithParametersPassesParametersToFilter()
{
$this->assertEquals(System\Route\Filter::call('vars', array('test'), true), 'test');
$this->assertEquals(System\Route\Filter::call('vars2', array('test1', 'test2'), true), 'test1test2');
}
}
\ No newline at end of file
<?php
class RouteFinderTest extends PHPUnit_Framework_TestCase {
public static function setUpBeforeClass()
{
$routes = array();
$routes['GET /home'] = array('GET /home' => array('name' => 'home', 'do' => function() {}));
$routes['GET /user'] = array('GET /user' => array('name' => 'user', 'do' => function() {}));
System\Route\Finder::$routes = $routes;
}
public function testRouteFinderReturnsNullWhenRouteIsNotFound()
{
$this->assertNull(System\Route\Finder::find('doesnt-exist'));
}
public function testRouteFinderReturnsRouteWhenFoundInSingleRoutesFile()
{
$this->assertArrayHasKey('GET /home', System\Route\Finder::find('home'));
$this->assertArrayHasKey('GET /user', System\Route\Finder::find('user'));
}
public function testRouteFinderLoadsRoutesFromRouteDirectoryToFindRoutes()
{
System\Route\Finder::$routes = null;
$this->setupRoutesDirectory();
$this->assertArrayHasKey('GET /user', System\Route\Finder::find('user'));
Utils::rrmdir(APP_PATH.'routes');
}
private function setupRoutesDirectory()
{
mkdir(APP_PATH.'routes', 0777);
file_put_contents(APP_PATH.'routes/user.php', "<?php return array('GET /user' => array('name' => 'user', 'do' => function() {return '/user';})); ?>", LOCK_EX);
}
}
\ No newline at end of file
<?php
class RouteTest extends PHPUnit_Framework_TestCase {
public function testSimpleRouteCallbackReturnsResponseInstance()
{
$route = new System\Route('GET /', function() {return 'test';});
$this->assertInstanceOf('System\\Response', $route->call());
$this->assertEquals($route->call()->content, 'test');
}
public function testRouteCallPassesParametersToCallback()
{
$route = new System\Route('GET /', function($parameter) {return $parameter;}, array('test'));
$this->assertEquals($route->call()->content, 'test');
$route = new System\Route('GET /', function($parameter1, $parameter2) {return $parameter1.$parameter2;}, array('test1', 'test2'));
$this->assertEquals($route->call()->content, 'test1test2');
}
public function testRouteCallWithNullBeforeFilterReturnsRouteResponse()
{
$route = new System\Route('GET /', array('before' => 'test', 'do' => function() {return 'route';}));
System\Route\Filter::$filters = array('test' => function() {return null;});
$this->assertEquals($route->call()->content, 'route');
}
public function testRouteCallWithOverridingBeforeFilterReturnsFilterResponse()
{
$route = new System\Route('GET /', array('before' => 'test', 'do' => function() {return 'route';}));
System\Route\Filter::$filters = array('test' => function() {return 'filter';});
$this->assertEquals($route->call()->content, 'filter');
}
public function testRouteAfterFilterIsCalled()
{
$route = new System\Route('GET /', array('after' => 'test', 'do' => function() {return 'route';}));
System\Route\Filter::$filters = array('test' => function() {define('LARAVEL_TEST_AFTER_FILTER', 'ran');});
$route->call();
$this->assertTrue(defined('LARAVEL_TEST_AFTER_FILTER'));
}
public function testRouteAfterFilterDoesNotAffectResponse()
{
$route = new System\Route('GET /', array('after' => 'test', 'do' => function() {return 'route';}));
System\Route\Filter::$filters = array('test' => function() {return 'filter';});
$this->assertEquals($route->call()->content, 'route');
}
}
\ No newline at end of file
<?php
class RoutingTest extends PHPUnit_Framework_TestCase {
public static function setUpBeforeClass()
{
$routes = array();
$routes['GET /'] = array('name' => 'root', 'do' => function() {});
$routes['GET /home'] = array('name' => 'home', 'do' => function() {});
$routes['POST /home'] = array('name' => 'post-home', 'do' => function() {});
$routes['GET /user/(:num)'] = array('name' => 'user', 'do' => function() {});
$routes['GET /user/(:any)/(:num)/edit'] = array('name' => 'edit', 'do' => function() {});
$routes['GET /cart/(:num?)'] = array('name' => 'cart', 'do' => function() {});
$routes['GET /download/(:num?)/(:any?)'] = array('name' => 'download', 'do' => function() {});
System\Router::$routes = $routes;
}
public static function tearDownAfterClass()
{
System\Router::$routes = null;
}
public function tearDown()
{
Utils::rrmdir(APP_PATH.'routes');
}
public function testRouterReturnsNullWhenNotFound()
{
$this->assertNull(System\Router::route('GET', 'doesnt-exist'));
}
public function testRouterRoutesToRootWhenItIsRequest()
{
$this->assertEquals(System\Router::route('GET', '/')->callback['name'], 'root');
}
public function testRouterRoutesToProperRouteWhenSegmentsArePresent()
{
$this->assertEquals(System\Router::route('GET', 'home')->callback['name'], 'home');
$this->assertEquals(System\Router::route('GET', 'user/1')->callback['name'], 'user');
$this->assertEquals(System\Router::route('GET', 'user/taylor/25/edit')->callback['name'], 'edit');
$this->assertEquals(System\Router::route('POST', 'home')->callback['name'], 'post-home');
}
public function testRouterGivesRouteProperSegmentsWhenTheyArePresent()
{
$this->assertEquals(System\Router::route('GET', 'user/1')->parameters[0], 1);
$this->assertEquals(count(System\Router::route('GET', 'user/1')->parameters), 1);
$this->assertEquals(System\Router::route('GET', 'user/taylor/25/edit')->parameters[0], 'taylor');
$this->assertEquals(System\Router::route('GET', 'user/taylor/25/edit')->parameters[1], 25);
$this->assertEquals(count(System\Router::route('GET', 'user/taylor/25/edit')->parameters), 2);
}
public function testRouterRoutesToProperRouteWhenUsingOptionalSegments()
{
$this->assertEquals(System\Router::route('GET', 'cart')->callback['name'], 'cart');
$this->assertEquals(System\Router::route('GET', 'cart/1')->callback['name'], 'cart');
$this->assertEquals(System\Router::route('GET', 'download')->callback['name'], 'download');
$this->assertEquals(System\Router::route('GET', 'download/1')->callback['name'], 'download');
$this->assertEquals(System\Router::route('GET', 'download/1/a')->callback['name'], 'download');
}
public function testRouterGivesRouteProperOptionalSegmentsWhenTheyArePresent()
{
$this->assertTrue(is_array(System\Router::route('GET', 'cart')->parameters));
$this->assertEquals(count(System\Router::route('GET', 'cart')->parameters), 0);
$this->assertEquals(System\Router::route('GET', 'cart/1')->parameters[0], 1);
$this->assertEquals(count(System\Router::route('GET', 'download')->parameters), 0);
$this->assertEquals(System\Router::route('GET', 'download/1')->parameters[0], 1);
$this->assertEquals(count(System\Router::route('GET', 'download/1')->parameters), 1);
$this->assertEquals(System\Router::route('GET', 'download/1/a')->parameters[0], 1);
$this->assertEquals(System\Router::route('GET', 'download/1/a')->parameters[1], 'a');
$this->assertEquals(count(System\Router::route('GET', 'download/1/a')->parameters), 2);
}
public function testRouterReturnsNullWhenRouteNotFound()
{
$this->assertNull(System\Router::route('GET', 'user/taylor/taylor/edit'));
$this->assertNull(System\Router::route('GET', 'user/taylor'));
$this->assertNull(System\Router::route('GET', 'user/12-3'));
$this->assertNull(System\Router::route('GET', 'cart/a'));
$this->assertNull(System\Router::route('GET', 'cart/12-3'));
$this->assertNull(System\Router::route('GET', 'download/a'));
$this->assertNull(System\Router::route('GET', 'download/1a'));
$this->assertNull(System\Router::route('POST', 'user/taylor/25/edit'));
}
public function testRouteLoaderShouldReturnSingleRoutesFileWhenNoFolderIsPresent()
{
$routes = System\Router::load('test');
// Only the Laravel default route should be returned.
$this->assertArrayHasKey('GET /', $routes);
}
public function testRouteLoaderLoadsRouteFilesInRouteDirectoryByURI()
{
$this->setupRoutesDirectory();
$this->assertArrayHasKey('GET /user', System\Router::load('user'));
$this->assertArrayHasKey('GET /cart/edit', System\Router::load('cart'));
$this->assertArrayHasKey('GET /cart/edit', System\Router::load('cart/edit'));
}
public function testRouteLoaderLoadsBaseRoutesFileForEveryRequest()
{
$this->setupRoutesDirectory();
$this->assertArrayHasKey('GET /', System\Router::load('user'));
}
private function setupRoutesDirectory()
{
mkdir(APP_PATH.'routes', 0777);
file_put_contents(APP_PATH.'routes/user.php', "<?php return array('GET /user' => function() {return '/user';}); ?>", LOCK_EX);
file_put_contents(APP_PATH.'routes/cart.php', "<?php return array('GET /cart/edit' => function() {return '/cart/edit';}); ?>", LOCK_EX);
}
}
\ No newline at end of file
<?php
class ViewTest extends PHPUnit_Framework_TestCase {
public function testConstructorSetsViewNameAndData()
{
$view = new System\View('view', array('name' => 'test'));
$this->assertEquals($view->view, 'view');
$this->assertEquals($view->data, array('name' => 'test'));
$view = new System\View('view');
$this->assertEquals($view->data, array());
}
public function testMakeMethodReturnsNewViewInstance()
{
$this->assertInstanceOf('System\\View', System\View::make('test'));
}
public function testBindMethodAddsItemToViewData()
{
$view = System\View::make('test')->bind('name', 'test');
$this->assertEquals($view->data, array('name' => 'test'));
}
public function testBoundViewDataCanBeRetrievedThroughMagicMethods()
{
$view = System\View::make('test')->bind('name', 'test');
$this->assertTrue(isset($view->name));
$this->assertEquals($view->name, 'test');
unset($view->name);
$this->assertFalse(isset($view->name));
}
public function testGetMethodReturnsStringContentOfView()
{
$this->assertTrue(is_string(System\View::make('home/index')->get()));
}
/**
* @expectedException Exception
*/
public function testExceptionIsThrownWhenViewDoesntExist()
{
System\View::make('doesnt-exist')->get();
}
}
\ No newline at end of file
<?php
class Utils {
/**
* Recursively remove a directory.
*
* @param string $directory
* @return void
*/
public static function rrmdir($directory)
{
if (is_dir($directory))
{
$objects = scandir($directory);
foreach ($objects as $object)
{
if ($object != "." && $object != "..")
{
if (filetype($directory."/".$object) == "dir") static::rrmdir($directory."/".$object); else unlink($directory."/".$object);
}
}
reset($objects);
rmdir($directory);
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment