diff --git a/artisan/commands.md b/artisan/commands.md new file mode 100644 index 0000000..a918716 --- /dev/null +++ b/artisan/commands.md @@ -0,0 +1,102 @@ +# Artisan Commands + +## Contents + +- [Application Configuration](#application-configuration) +- [Sessions](#sessions) +- [Migrations](#migrations) +- [Bundles](#bundles) +- [Tasks](#tasks) +- [Unit Tests](#unit-tests) +- [Routing](#routing) +- [Application Keys](#keys) +- [CLI Options](#cli-options) + + +## Application Configuration [(More Information)](/docs/install#basic-configuration) + +Description | Command +------------- | ------------- +Generate a secure application key. An application key will not be generated unless the field in **config/application.php** is empty. | `php artisan key:generate` + + +## Database Sessions [(More Information)](/docs/session/config#database) + +Description | Command +------------- | ------------- +Create a session table | `php artisan session:table` + + +## Migrations [(More Information)](/docs/database/migrations) + +Description | Command +------------- | ------------- +Create the Laravel migration table | `php artisan migrate:install` +Creating a migration | `php artisan migrate:make create_users_table` +Creating a migration for a bundle | `php artisan migrate:make bundle::tablename` +Running outstanding migrations | `php artisan migrate` +Running outstanding migrations in the application | `php artisan migrate application` +Running all outstanding migrations in a bundle | `php artisan migrate bundle` +Rolling back the last migration operation | `php artisan migrate:rollback` +Roll back all migrations that have ever run | `php artisan migrate:reset` + + +## Bundles [(More Information)](/docs/bundles) + +Description | Command +------------- | ------------- +Install a bundle | `php artisan bundle:install eloquent` +Upgrade a bundle | `php artisan bundle:upgrade eloquent` +Upgrade all bundles | `php artisan bundle:upgrade` +Publish a bundle assets | `php artisan bundle:publish bundle_name` +Publish all bundles assets | `php artisan bundle:publish` + +
+> **Note:** After installing you need to [register the bundle](../bundles/#registering-bundles) + + +## Tasks [(More Information)](/docs/artisan/tasks) + +Description | Command +------------- | ------------- +Calling a task | `php artisan notify` +Calling a task and passing arguments | `php artisan notify taylor` +Calling a specific method on a task | `php artisan notify:urgent` +Running a task on a bundle | `php artisan admin::generate` +Running a specific method on a bundle | `php artisan admin::generate:list` + + +## Unit Tests [(More Information)](/docs/testing) + +Description | Command +------------- | ------------- +Running the application tests | `php artisan test` +Running the bundle tests | `php artisan test bundle-name` + + +## Routing [(More Information)](/docs/routing) + +Description | Command +------------- | ------------- +Calling a route | `php artisan route:call get api/user/1` + +
+> **Note:** You can replace get with post, put, delete, etc. + + +## Application Keys + +Description | Command +------------- | ------------- +Generate an application key | `php artisan key:generate` + +
+> **Note:** You can specify an alternate key length by adding an extra argument to the command. + + +## CLI Options + +Description | Command +------------- | ------------- +Setting the Laravel environment | `php artisan foo --env=local` +Setting the default database connection | `php artisan foo --db=sqlitename` diff --git a/artisan/tasks.md b/artisan/tasks.md new file mode 100644 index 0000000..fcdefc3 --- /dev/null +++ b/artisan/tasks.md @@ -0,0 +1,100 @@ +# Tasks + +## Contents + +- [The Basics](#the-basics) +- [Creating & Running Tasks](#creating-tasks) +- [Bundle Tasks](#bundle-tasks) +- [CLI Options](#cli-options) + + +## The Basics + +Laravel's command-line tool is called Artisan. Artisan can be used to run "tasks" such as migrations, cronjobs, unit-tests, or anything that want. + + +## Creating & Running Tasks + +To create a task create a new class in your **application/tasks** directory. The class name should be suffixed with "_Task", and should at least have a "run" method, like this: + +#### Creating a task class: + + class Notify_Task { + + public function run($arguments) + { + // Do awesome notifying... + } + + } + +Now you can call the "run" method of your task via the command-line. You can even pass arguments: + +#### Calling a task from the command line: + + php artisan notify + +#### Calling a task and passing arguments: + + php artisan notify taylor + +Remember, you can call specific methods on your task, so, let's add an "urgent" method to the notify task: + +#### Adding a method to the task: + + class Notify_Task { + + public function run($arguments) + { + // Do awesome notifying... + } + + public function urgent($arguments) + { + // This is urgent! + } + + } + +Now we can call our "urgent" method: + +#### Calling a specific method on a task: + + php artisan notify:urgent + + +## Bundle Tasks + +To create a task for your bundle just prefix the bundle name to the class name of your task. So, if your bundle was named "admin", a task might look like this: + +#### Creating a task class that belongs to a bundle: + + class Admin_Generate_Task { + + public function run($arguments) + { + // Generate the admin! + } + + } + +To run your task just use the usual Laravel double-colon syntax to indicate the bundle: + +#### Running a task belonging to a bundle: + + php artisan admin::generate + +#### Running a specific method on a task belonging to a bundle: + + php artisan admin::generate:list + + +## CLI Options + +#### Setting the Laravel environment: + + php artisan foo --env=local + +#### Setting the default database connection: + + php artisan foo --db=sqlite \ No newline at end of file diff --git a/auth/config.md b/auth/config.md index a9be4d6..dbeed52 100644 --- a/auth/config.md +++ b/auth/config.md @@ -1,30 +1,56 @@ -## 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 +# Auth Configuration + +## Contents + +- [The Basics](#the-basics) +- [The User Function](#user) +- [The Attempt Function](#attempt) +- [The Logout Function](#logout) + + +## The Basics + +Most interactive applications have the ability for users to login and logout. Laravel provides a simple class to help you validate user credentials and retrieve information about the current user of your application. + +To get started, let's look over the **application/config/auth.php** file. The authentication configuration contains three functions: **user**, **attempt**, and **logout**. Let's go over each one individually. + + +## The "User" Function + +The **user** function is called when Laravel needs to retrieve the currently logged in user of your application. When a user logs into your application, Laravel stores the ID of that user in the [session](/docs/session/config). So, on subsequent requests, we can use the ID stored in the session to retrieve the user's information from storage. However, applications use various data stores. For this reason, you are given complete flexibility regarding how to retrieve the user. + +Of course, a simple default configuration has been setup for you. Let's take a look: + + 'user' => function($id) + { + if ( ! is_null($id) and filter_var($id, FILTER_VALIDATE_INT) !== false) + { + return DB::table('users')->find($id); + } + } + +As you probably noticed, the user's ID is passed to the function. The default configuration utilizes the [fluent query builder](/docs/database/fluent) to retrieve and return the user from the database. Of course, you are free to use other methods of retrieving the user. If no user is found in storage for the given ID, the function should simply return **null**. + + +## The "Attempt" Function + +Anytime you need to validate the credentials of a user, the **attempt** function is called. When attempting to authenticate a user, you will typically retrieve the user out of storage, and check the hashed password against the given password. However, since applications may use various methods of hashing or even third-party login providers, you are free to implement the authentication however you wish. Again, a simple and sensible default has been provided: + + 'attempt' => function($username, $password) + { + $user = DB::table('users')->where_username($username)->first(); + + if ( ! is_null($user) and Hash::check($password, $user->password)) + { + return $user; + } + } + +Like the previous example, the fluent query builder is used to retrieve the user out of the database by the given username. If the user is found, the given password is hashed and compared against the hashed password stored on the table, and if the passwords match, the user model is returned. If the credentials are invalid or the user does not exist, **null** should be returned. + +> **Note:** Any object may be returned by this function as long as it has an **id** property. + + +## The "Logout" Function + +The **logout** function is called whenever a user is logged out of your application. This function gives you a convenient location to interact with any third-party authentication providers you may be using. \ No newline at end of file diff --git a/auth/usage.md b/auth/usage.md index 65c35aa..18ce431 100644 --- a/auth/usage.md +++ b/auth/usage.md @@ -1,81 +1,99 @@ -## 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). - - -### 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. - - -### 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!"; - } - -Sometimes you may need to login a user without checking their credentials, such as after a user first registers to use your application. It's easy using the **remember** method. Just pass your user object: - - Auth::remember($user); - - -### 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**. - - -### 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. - - -### Logging Out - -Ready to log the user out of your application? It's simple: - - Auth::logout(); - +# Authentication Usage + +## Contents + +- [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). + + +## Salting & Hashing + +If you are using the Auth class, you are strongly encouraged to hash and salt all passwords. Web development must be done responsibly. Salted, hashed passwords make a rainbow table attack against your user's passwords impractical. + +Salting and hashing passwords is done using the **Hash** class. The Hash class is uses 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!'; + } + + +## Logging In + +Logging a user into your application is simple using the **attempt** 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::attempt('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. + +By default a user's auth session will expire when their browser has been closed. You can enable Laravel's "remember me" functionality by passing **true** as the third parameter to the **attempt** method. + + if (Auth::attempt('example@gmail.com', 'password', true)) + ... + +You probably noticed this method name corresponds to the **attempt** function you [configured earlier](/docs/auth/config#attempt). Each time you call the **attempt** method on the **Auth** class, the **attempt** function in the configuration file will be called to check the user's credentials. + +> **Note:** To provide more flexiblity when working with third-party authentication providers, you are not required to pass a password into the **attempt** method. + +To determine if the user of your application is logged in, call either the **check** or **guest** methods: + + if (Auth::check()) + { + return "You're logged in!"; + } + + if (Auth::guest()) + { + return "You're not logged in!"; + } + +Use the **login** method to login a user without checking their credentials, such as after a user first registers to use your application. Just pass your user object or the user's ID: + + Auth::login($user); + + Auth::login(15); + + +## Protecting Routes + +It is common to limit access to certain routes only to logged in users. In Laravel this is accomplished using the [auth filter](/docs/routing#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/routing#named-routes). + +To protect a route, simply attach the **auth** filter: + + Route::get('admin', array('before' => 'auth', function() {}); + +> **Note:** You are free to edit the **auth** filter however you like. A default implementation is located in **application/routes.php**. + + +## Retrieving The Logged In User + +Once a user has logged in to your application, you can access the user model via the **user** method on the Auth class: + + return Auth::user()->email; + +This method calls the [**user** function](/docs/auth/config#user) in the configuration file. Also, you don't need to worry about performance when using this method. The user is only retrieved from storage the first time you use the method. + +> **Note:** If the user is not logged in, the **user** method will return NULL. + + +## Logging Out + +Ready to log the user out of your application? + + 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 diff --git a/bundles.md b/bundles.md new file mode 100644 index 0000000..2f72dbb --- /dev/null +++ b/bundles.md @@ -0,0 +1,214 @@ +# Bundles + +## Contents + +- [The Basics](#the-basics) +- [Creating Bundles](#creating-bundles) +- [Registering Bundles](#registering-bundles) +- [Bundles & Class Loading](#bundles-and-class-loading) +- [Starting Bundles](#starting-bundles) +- [Routing To Bundles](#routing-to-bundles) +- [Using Bundles](#using-bundles) +- [Bundle Assets](#bundle-assets) +- [Installing Bundles](#installing-bundles) +- [Upgrading Bundles](#upgrading-bundles) + + +## The Basics + +Bundles are the heart of the improvements that were made in Laravel 3.0. They are a simple way to group code into convenient "bundles". A bundle can have it's own views, configuration, routes, migrations, tasks, and more. A bundle could be everything from a database ORM to a robust authentication system. Modularity of this scope is an important aspect that has driven virtually all design decisions within Laravel. In many ways you can actually think of the application folder as the special default bundle with which Laravel is pre-programmed to load and use. + + +## Creating Bundles + +The first step in creating a bundle is to create a folder for the bundle within your **bundles** directory. For this example, let's create an "admin" bundle, which could house the administrator back-end to our application. The **application/start.php** file provides some basic configuration that helps to define how our application will run. Likewise we'll create a **start.php** file within our new bundle folder for the same purpose. It is run everytime the bundle is loaded. Let's create it: + +#### Creating a bundle start.php file: + + Bundle::path('admin').'models', + )); + +In this start file we've told the auto-loader that classes that are namespaced to "Admin" should be loaded out of our bundle's models directory. You can do anything you want in your start file, but typically it is used for registering classes with the auto-loader. **In fact, you aren't required to create a start file for your bundle.** + +Next, we'll look at how to register this bundle with our application! + + +## Registering Bundles + +Now that we have our admin bundle, we need to register it with Laravel. Pull open your **application/bundles.php** file. This is where you register all bundles used by your application. Let's add ours: + +#### Registering a simple bundle: + + return array('admin'), + +By convention, Laravel will assume that the Admin bundle is located at the root level of the bundle directory, but we can specify another location if we wish: + +#### Registering a bundle with a custom location: + + return array( + + 'admin' => array('location' => 'userscape/admin'), + + ); + +Now Laravel will look for our bundle in **bundles/userscape/admin**. + + +## Bundles & Class Loading + +Typically, a bundle's **start.php** file only contains auto-loader registrations. So, you may want to just skip **start.php** and declare your bundle's mappings right in its registration array. Here's how: + +#### Defining auto-loader mappings in a bundle registration: + + return array( + + 'admin' => array( + 'autoloads' => array( + 'map' => array( + 'Admin' => '(:bundle)/admin.php', + ), + 'namespaces' => array( + 'Admin' => '(:bundle)/lib', + ), + 'directories' => array( + '(:bundle)/models', + ), + ), + ), + + ); + +Notice that each of these options corresponds to a function on the Laravel [auto-loader](/docs/loading). In fact, the value of the option will automatically be passed to the corresponding function on the auto-loader. + +You may have also noticed the **(:bundle)** place-holder. For convenience, this will automatically be replaced with the path to the bundle. It's a piece of cake. + + +## Starting Bundles + +So our bundle is created and registered, but we can't use it yet. First, we need to start it: + +#### Starting a bundle: + + Bundle::start('admin'); + +This tells Laravel to run the **start.php** file for the bundle, which will register its classes in the auto-loader. The start method will also load the **routes.php** file for the bundle if it is present. + +> **Note:** The bundle will only be started once. Subsequent calls to the start method will be ignored. + +If you use a bundle throughout your application, you may want it to start on every request. If this is the case, you can configure the bundle to auto-start in your **application/bundles.php** file: + +#### Configuration a bundle to auto-start: + + return array( + + 'admin' => array('auto' => true), + + ); + +You do not always need to explicitly start a bundle. In fact, you can usually code as if the bundle was auto-started and Laravel will take care of the rest. For example, if you attempt to use a bundle views, configurations, languages, routes or filters, the bundle will automatically be started! + +Each time a bundle is started, it fires an event. You can listen for the starting of bundles like so: + +#### Listen for a bundle's start event: + + Event::listen('laravel.started: admin', function() + { + // The "admin" bundle has started... + }); + +It is also possible to "disable" a bundle so that it will never be started. + +#### Disabling a bundle so it can't be started: + + Bundle::disable('admin'); + + +## Routing To Bundles + +Refer to the documentation on [bundle routing](/docs/routing#bundle-routes) and [bundle controllers](/docs/controllers#bundle-controllers) for more information on routing and bundles. + + +## Using Bundles + +As mentioned previously, bundles can have views, configuration, language files and more. Laravel uses a double-colon syntax for loading these items. So, let's look at some examples: + +#### Loading a bundle view: + + return View::make('bundle::view'); + +#### Loading a bundle configuration item: + + return Config::get('bundle::file.option'); + +#### Loading a bundle language line: + + return Lang::line('bundle::file.line'); + +Sometimes you may need to gather more "meta" information about a bundle, such as whether it exists, its location, or perhaps its entire configuration array. Here's how: + +#### Determine whether a bundle exists: + + Bundle::exists('admin'); + +#### Retrieving the installation location of a bundle: + + $location = Bundle::path('admin'); + +#### Retrieving the configuration array for a bundle: + + $config = Bundle::get('admin'); + +#### Retrieving the names of all installed bundles: + + $names = Bundle::names(); + + +## Bundle Assets + +If your bundle contains views, it is likely you have assets such as JavaScript and images that need to be available in the **public** directory of the application. No problem. Just create **public** folder within your bundle and place all of your assets in this folder. + +Great! But, how do they get into the application's **public** folder. The Laravel "Artisan" command-line provides a simple command to copy all of your bundle's assets to the public directory. Here it is: + +#### Publish bundle assets into the public directory: + + php artisan bundle:publish + +This command will create a folder for the bundle's assets within the application's **public/bundles** directory. For example, if your bundle is named "admin", a **public/bundles/admin** folder will be created, which will contain all of the files in your bundle's public folder. + +For more information on conveniently getting the path to your bundle assets once they are in the public directory, refer to the documentation on [asset management](/docs/views/assets#bundle-assets). + + +## Installing Bundles + +Of course, you may always install bundles manually; however, the "Artisan" CLI provides an awesome method of installing and upgrading your bundle. The framework uses simple Zip extraction to install the bundle. Here's how it works. + +#### Installing a bundle via Artisan: + + php artisan bundle:install eloquent + +Great! Now that you're bundle is installed, you're ready to [register it](#registering-bundles) and [publish its assets](#bundle-assets). + +Need a list of available bundles? Check out the Laravel [bundle directory](http://bundles.laravel.com) + + +## Upgrading Bundles + +When you upgrade a bundle, Laravel will automatically remove the old bundle and install a fresh copy. + +#### Upgrading a bundle via Artisan: + + php artisan bundle:upgrade eloquent + +> **Note:** After upgrading the bundle, you may need to [re-publish its assets](#bundle-assets). + +**Important:** Since the bundle is totally removed on an upgrade, you must be aware of any changes you have made to the bundle code before upgrading. You may need to change some configuration options in a bundle. Instead of modifying the bundle code directly, use the bundle start events to set them. Place something like this in your **application/start.php** file. + +#### Listening for a bundle's start event: + + Event::listen('laravel.started: admin', function() + { + Config::set('admin::file.option', true); + }); \ No newline at end of file diff --git a/cache/config.md b/cache/config.md index 0045736..39f80c4 100644 --- a/cache/config.md +++ b/cache/config.md @@ -1,38 +1,79 @@ -## 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. - - -### 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), - ) - - -### 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 Configuration + +## Contents + +- [The Basics](#the-basics) +- [Database](#database) +- [Memcached](#memcached) +- [Redis](#redis) +- [Cache Keys](#keys) +- [In-Memory Cache](#memory) + + +## The Basics + +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? Laravel's caching makes it simple. + +Laravel provides five cache drivers out of the box: + +- File System +- Database +- Memcached +- APC +- Redis +- Memory (Arrays) + +By default, Laravel is configured to use the **file** system cache driver. It's ready to go out of the box with no configuration. The file system driver stores cached items as files in the **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 **storage/cache** directory is writeable. + + +## Database + +The database cache driver uses a given database table as a simple key-value store. To get started, first set the name of the database table in **application/config/cache.php**: + + 'database' => array('table' => 'laravel_cache'), + +Next, create the table on your database. The table should have three columns: + +- key (varchar) +- value (text) +- expiration (integer) + +That's it. Once your configuration and table is setup, you're ready to start caching! + + +## 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 you must set the **driver** in the **application/config/cache.php** file: + + 'driver' => 'memcached' + +Then, add your Memcached servers to the **servers** array: + + 'servers' => array( + array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100), + ) + + +## Redis + +[Redis](http://redis.io) is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain [strings](http://redis.io/topics/data-types#strings), [hashes](http://redis.io/topics/data-types#hashes), [lists](http://redis.io/topics/data-types#lists), [sets](http://redis.io/topics/data-types#sets), and [sorted sets](http://redis.io/topics/data-types#sorted-sets). + +Before using the Redis cache driver, you must [configure your Redis servers](/docs/database/redis#config). Now you can just set the **driver** in the **application/config/cache.php** file: + + 'driver' => 'redis' + + +### Cache Keys + +To avoid naming collisions with other applications using APC, Redis, 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' + + +### In-Memory Cache + +The "memory" cache driver does not actually cache anything to disk. It simply maintains an internal array of the cache data for the current request. This makes it perfect for unit testing your application in isolation from any storage mechanism. It should never be used as a "real" cache driver. \ No newline at end of file diff --git a/cache/usage.md b/cache/usage.md index 4464e95..adc2f2e 100644 --- a/cache/usage.md +++ b/cache/usage.md @@ -1,53 +1,59 @@ -## Cache Usage - -- [Storing Items](#put) -- [Retrieving Items](#get) -- [Removing Items](#forget) - - -### 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. - - -### 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'); - } - - -### Removing Items - -Need to get rid of a cached item? No problem. Just mention the name of the item to the **forget** method: - +# Cache Usage + +## Contents + +- [Storing Items](#put) +- [Retrieving Items](#get) +- [Removing Items](#forget) + + +## 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. + +You may also cache something "forever" if you do not want the cache to expire: + + Cache::forever('name', 'Taylor'); + +> **Note:** It is not necessary to serialize objects when storing them in the cache. + + +## 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 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'); + } + + +## 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 diff --git a/config.md b/config.md new file mode 100644 index 0000000..ae74138 --- /dev/null +++ b/config.md @@ -0,0 +1,34 @@ +# Runtime Configuration + +## Contents + +- [The Basics](#the-basics) +- [Retrieving Options](#retrieving-options) +- [Setting Options](#setting-options) + + +## The Basics + +Sometimes you may need to get and set configuration options at runtime. For this you'll use the **Config** class, which utilizes Laravel's "dot" syntax for accessing configuration files and items. + + +## Retrieving Options + +#### Retrieve a configuration option: + + $value = Config::get('application.url'); + +#### Return a default value if the option doesn't exist: + + $value = Config::get('application.timezone', 'UTC'); + +#### Retrieve an entire configuration array: + + $options = Config::get('database'); + + +## Setting Options + +#### Set a configuration option: + + Config::set('cache.driver', 'apc'); \ No newline at end of file diff --git a/contents.md b/contents.md index c48ce4b..25d78c8 100644 --- a/contents.md +++ b/contents.md @@ -1,62 +1,108 @@ -## 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) - - [Route Dependencies](/docs/start/routes#dependencies) - - [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) - - [Named Views](/docs/start/views#named-views) - - [View Composers](/docs/start/views#composers) - - [Managing Assets](/docs/start/views#assets) - - [Redirects](/docs/start/views#redirect) - - [Downloads](/docs/start/views#downloads) - - [Building URLs](/docs/start/views#urls) - - [Building HTML](/docs/start/views#html) - - [Pagination](/docs/start/views#pagination) - - [Errors](/docs/start/views#errors) -- [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) -- [Models, Libraries, & Packages](/docs/start/libraries) -- [Modules](/docs/start/modules) - -## Database +### General +- [Laravel Overview](/docs/home) +- [Installation & Setup](/docs/install) + - [Requirements](/docs/install#requirements) + - [Installation](/docs/install#installation) + - [Basic Configuration](/docs/install#basic-configuration) + - [Environments](/docs/install#environments) + - [Cleaner URLs](/docs/install#cleaner-urls) +- [Controllers](/docs/controllers) + - [The Basics](/docs/controllers#the-basics) + - [Controller Routing](/docs/controllers#controller-routing) + - [Bundle Controllers](/docs/controllers#bundle-controllers) + - [Action Filters](/docs/controllers#action-filters) + - [Nested Controllers](/docs/controllers#nested-controllers) + - [RESTful Controllers](/docs/controllers#restful-controllers) + - [Dependency Injection](/docs/controllers#dependency-injection) + - [Controller Factory](/docs/controllers#controller-factory) +- [Models & Libraries](/docs/models) +- [Views & Responses](/docs/views) + - [The Basics](/docs/views#basics) + - [Binding Data To Views](/docs/views#binding-data-to-views) + - [Nesting Views](/docs/views#nesting-views) + - [Named Views](/docs/views#named-views) + - [View Composers](/docs/views#view-composers) + - [Redirects](/docs/views#redirects) + - [Redirecting With Data](/docs/views#redirecting-with-flash-data) + - [Downloads](/docs/views#downloads) + - [Errors](/docs/views#errors) + - [Managing Assets](/docs/views/assets) + - [Templating](/docs/views/templating) + - [Pagination](/docs/views/pagination) + - [Building HTML](/docs/views/html) + - [Building Forms](/docs/views/forms) +- [Routing](/docs/routing) + - [The Basics](/docs/routing#the-basics) + - [Wildcards](/docs/routing#wildcards) + - [The 404 Event](/docs/routing#the-404-event) + - [Filters](/docs/routing#filters) + - [Global Filters](/docs/routing#global-filters) + - [Route Groups](/docs/routing#groups) + - [Named Routes](/docs/routing#named-routes) + - [HTTPS Routes](/docs/routing#https-routes) + - [Bundle Routing](/docs/routing#bundle-routing) + - [CLI Route Testing](/docs/routing#cli-route-testing) +- [Input & Cookies](/docs/input) + - [Input](/docs/input#input) + - [Files](/docs/input#files) + - [Old Input](/docs/input#old-input) + - [Redirecting With Old Input](/docs/input#redirecting-with-old-input) + - [Cookies](/docs/input#cookies) +- [Bundles](/docs/bundles) + - [The Basics](/docs/bundles#the-basics) + - [Creating Bundles](/docs/bundles#creating-bundles) + - [Registering Bundles](/docs/bundles#registering-bundles) + - [Bundles & Class Loading](/docs/bundles#bundles-and-class-loading) + - [Starting Bundles](/docs/bundles#starting-bundles) + - [Routing To Bundles](/docs/bundles#routing-to-bundles) + - [Using Bundles](/docs/bundles#using-bundles) + - [Bundle Assets](/docs/bundles#bundle-assets) + - [Installing Bundles](/docs/bundles#installing-bundles) + - [Upgrading Bundles](/docs/bundles#upgrading-bundles) +- [Class Auto Loading](/docs/loading) +- [Errors & Logging](/docs/logging) +- [Runtime Configuration](/docs/config) +- [Examining Requests](/docs/requests) +- [Generating URLs](/docs/urls) +- [Events](/docs/events) +- [Validation](/docs/validation) +- [Working With Files](/docs/files) +- [Working With Strings](/docs/strings) +- [Localization](/docs/localization) +- [Encryption](/docs/encryption) +- [IoC Container](/docs/ioc) +- [Unit Testing](/docs/testing) + +### Database - [Configuration](/docs/database/config) -- [Usage](/docs/database/usage) -- [Fluent Query Builder](/docs/database/query) +- [Raw Queries](/docs/database/raw) +- [Fluent Query Builder](/docs/database/fluent) - [Eloquent ORM](/docs/database/eloquent) +- [Schema Builder](/docs/database/schema) +- [Migrations](/docs/database/migrations) +- [Redis](/docs/database/redis) -## Caching +### Caching - [Configuration](/docs/cache/config) - [Usage](/docs/cache/usage) -## Sessions +### Sessions - [Configuration](/docs/session/config) - [Usage](/docs/session/usage) -## Authentication +### Authentication - [Configuration](/docs/auth/config) - [Usage](/docs/auth/usage) -## Other Topics +### Artisan CLI -- [Working With Files](/docs/other/file) -- [Working With Strings](/docs/other/text) -- [Localization](/docs/other/lang) -- [Encryption](/docs/other/crypt) -- [Benchmarking Code](/docs/other/benchmark) \ No newline at end of file +- [Tasks](/docs/artisan/tasks) + - [The Basics](/docs/artisan/tasks#the-basics) + - [Creating & Running Tasks](/docs/artisan/tasks#creating-tasks) + - [Bundle Tasks](/docs/artisan/tasks#bundle-tasks) + - [CLI Options](/docs/artisan/tasks#cli-options) +- [Commands](/docs/artisan/commands) \ No newline at end of file diff --git a/controllers.md b/controllers.md new file mode 100644 index 0000000..220c10a --- /dev/null +++ b/controllers.md @@ -0,0 +1,206 @@ +# Controllers + +## Contents + +- [The Basics](#the-basics) +- [Controller Routing](#controller-routing) +- [Bundle Controllers](#bundle-controllers) +- [Action Filters](#action-filters) +- [Nested Controllers](#nested-controllers) +- [Controller Layouts](#controller-layouts) +- [RESTful Controllers](#restful-controllers) +- [Dependency Injection](#dependency-injection) +- [Controller Factory](#controller-factory) + + +## The Basics + +Controllers are classes that are responsible for accepting user input and managing interactions between models, libraries, and views. Typically, they will ask a model for data, and then return a view that presents that data to the user. + +The usage of controllers is the most common method of implementing application logic in modern web-development. However, Laravel also empowers developers to implement their application logic within routing declarations. This is explored in detail in the [routing document](/docs/routing). New users are encourage to start with controllers. There is nothing that route-based application logic can do that controllers can't. + +Controller classes should be stored in **application/controllers** and should extend the Base\_Controller class. A Home\_Controller class is included with Laravel. + +#### Creating a simple controller: + + class Admin_Controller extends Base_Controller + { + + public function action_index() + { + // + } + + } + +**Actions** are the name of controller methods that are intended to be web-accessible. Actions should be prefixed with "action\_". All other methods, regardless of scope, will not be web-accessible. + +> **Note:** The Base\_Controller class extends the main Laravel Controller class, and gives you a convenient place to put methods that are common to many controllers. + + +## Controller Routing + +It is important to be aware that all routes in Laravel must be explicitly defined, including routes to controllers. + +This means that controller methods that have not been exposed through route registration **cannot** be accessed. It's possible to automatically expose all methods within a controller using controller route registration. Controller route registrations are typically defined in **application/routes.php**. + +Check [the routing page](/docs/routing#controller-routing) for more information on routing to controllers. + + +## Bundle Controllers + +Bundles are Laravel's modular package system. Bundles can easily configured to handle requests to your application. We'll be going over [bundles in more detail](/docs/bundles) in another document. + +Creating controllers that belong to bundles is almost identical to creating your application controllers. Just prefix the controller class name with the name of the bundle, so if your bundle is named "admin", your controller classes would look like this: + +#### Creating a bundle controller class: + + class Admin_Home_Controller extends Base_Controller + { + + public function action_index() + { + return "Hello Admin!"; + } + + } + +But, how do you register a bundle controller with the router? It's simple. Here's what it looks like: + +#### Registering a bundle's controller with the router: + + Route::controller('admin::home'); + +Great! Now we can access our "admin" bundle's home controller from the web! + +> **Note:** Throughout Laravel the double-colon syntax is used to denote bundles. More information on bundles can be found in the [bundle documentation](/docs/bundles). + + +## Action Filters + +Action filters are methods that can be run before or after a controller action. With Laravel you don't only have control over which filters are assigned to which actions. But, you can also choose which http verbs (post, get, put, and delete) will activate a filter. + +You can assign "before" and "after" filters to controller actions within the controller's constructor. + +#### Attaching a filter to all actions: + + $this->filter('before', 'auth'); + +In this example the 'auth' filter will be run before every action within this controller. The auth action comes out-of-the-box with Laravel and can be found in **application/routes.php**. The auth filter verifies that a user is logged in and redirects them to 'login' if they are not. + +#### Attaching a filter to only some actions: + + $this->filter('before', 'auth')->only(array('index', 'list')); + +In this example the auth filter will be run before the action_index() or action_list() methods are run. Users must be logged in before having access to these pages. However, no other actions within this controller require an authenticated session. + +#### Attaching a filter to all except a few actions: + + $this->filter('before', 'auth')->except(array('add', 'posts')); + +Much like the previous example, this declaration ensures that the auth filter is run on only some of this controller's actions. Instead of declaring to which actions the filter applies we are instead declaring the actions that will not require authenticated sessions. It can sometimes be safer to use the 'except' method as it's possible to add new actions to this controller and to forget to add them to only(). This could potentially lead your controller's action being unintentionally accessible by users who haven't been authenticated. + +#### Attaching a filter to run on POST: + + $this->filter('before', 'csrf')->on('post'); + +This example shows how a filter can be run only on a specific http verb. In this case we're running the csrf filter only when a form post is made. The csrf filter is designed to prevent form posts from other systems (spam bots for example) and comes by default with Laravel. You can find the csrf filter in **application/routes.php**. + +*Further Reading:* + +- *[Route Filters](/docs/routing#filters)* + + +## Nested Controllers + +Controllers may be located within any number of sub-directories within the main **application/controllers** folder. + +Define the controller class and store it in **controllers/admin/panel.php**. + + class Admin_Panel_Controller extends Base_Controller + { + + public function action_index() + { + // + } + + } + +#### Register the nested controller with the router using "dot" syntax: + + Route::controller('admin.panel'); + +> **Note:** When using nested controllers, always register your controllers from most nested to least nested in order to avoid shadowing controller routes. + +#### Access the "index" action of the controller: + + http://localhost/admin/panel + + +## Controller Layouts + +Full documentation on using layouts with Controllers [can be found on the Templating page](http://laravel.com/docs/views/templating). + + +## RESTful Controllers + +Instead of prefixing controller actions with "action_", you may prefix them with the HTTP verb they should respond to. + +#### Adding the RESTful property to the controller: + + class Home_Controller extends Base_Controller + { + + public $restful = true; + + } + +#### Building RESTful controller actions: + + class Home_Controller extends Base_Controller + { + + public $restful = true; + + public function get_index() + { + // + } + + public function post_index() + { + // + } + + } + +This is particularly useful when building CRUD methods as you can separate the logic which populates and renders a form from the logic that validates and stores the results. + + +## Dependency Injection + +If you are focusing on writing testable code, you will probably want to inject dependencies into the constructor of your controller. No problem. Just register your controller in the [IoC container](/docs/ioc). When registering the controller with the container, prefix the key with **controller**. So, in our **application/start.php** file, we could register our user controller like so: + + IoC::register('controller: user', function() + { + return new User_Controller; + }); + +When a request to a controller enters your application, Laravel will automatically determine if the controller is registered in the container, and if it is, will use the container to resolve an instance of the controller. + +> **Note:** Before diving into controller dependency injection, you may wish to read the documentation on Laravel's beautiful [IoC container](/docs/ioc). + + +## Controller Factory + +If you want even more control over the instantiation of your controllers, such as using a third-party IoC container, you'll need to use the Laravel controller factory. + +**Register an event to handle controller instantiation:** + + Event::listen(Controller::factory, function($controller) + { + return new $controller; + }); + +The event will receive the class name of the controller that needs to be resolved. All you need to do is return an instance of the controller. diff --git a/database/config.md b/database/config.md index 97dfa19..89767d4 100644 --- a/database/config.md +++ b/database/config.md @@ -1,24 +1,27 @@ -## Database Configuration +# Database Configuration + +## Contents - [Quick Start Using SQLite](#quick) -- [Configuring MySQL or PostgreSQL](#server) +- [Configuring Other Databases](#server) - [Setting The Default Connection Name](#default) -- [Connecting To Other Database Systems](#other) +- [Configuration By Environment](#environment) -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: +Laravel supports the following databases out of the box: - MySQL - PostgreSQL - SQLite +- SQL Server -All of the database configuration options live in the **application/config/db.php** file. Let's get started. +All of the database configuration options live in the **application/config/database.php** file. -### Quick Start Using SQLite +## 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. +[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/database** 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: +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/database.php** file: 'sqlite' => array( 'driver' => 'sqlite', @@ -30,40 +33,27 @@ If your application receives less than 100,000 hits per day, SQLite should be su > **Note:** Need a good SQLite manager? Check out this [Firefox extension](https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/). -### 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. +## Configuring Other Databases - 'mysql' => array( - 'driver' => 'mysql', - 'host' => 'localhost', - 'database' => 'database', - 'username' => 'root', - 'password' => 'password', - 'charset' => 'utf8', - ), +If you are using MySQL, SQL Server, or PostgreSQL, you will need to edit the configuration options in **application/config/database.php**. In the configuration file you can find sample configurations for each of these systems. Just change the options as necessary for your server and set the default connection name. -### Setting The Default Connection Name +## 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: +As you have probably noticed, each database connection defined in the **application/config/database.php** file has a name. By default, there are three connections defined: **sqlite**, **mysql**, **sqlsrv**, 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. - - -### Connecting To Other Database Systems +The default connection will always be used by the [fluent query builder](/docs/database/fluent). If you need to change the default connection during a request, use the **Config::set** method. -Need to using something besides MySQL, PostgreSQL, or SQLite? You can! Sort of... + +## Configuration By Environment -To make a PDO connection to an unsupported database, just add a **dsn** option to the connection configuration: +It's common to have database configuration files for each environment your app will run in. Set your [environment variable](/docs/install#environments) and then put a database config file in the appropriate location. For example on a local development machine you might have your environment set to **local**. You would then have two database.php files: - 'odbc' => array( - 'driver' => 'odbc', - 'dsn' => 'DRIVER={iSeries Access ODBC Driver};SYSTEM=x45624', - ), + application/config/database.php //default (production) config + application/config/local/database.php //local development config -Laravel will use the supplied driver and DSN to create a PDO connection. However, using [Eloquent](/docs/database/eloquent) or the [fluent query builder](/docs/database/query) may produce unexpected results. Of course, you may always access the raw PDO connection through the **DB::connection** method: +*Further Reading:* - $pdo = DB::connection('odbc'); \ No newline at end of file +- *[Environments](/docs/install#environments)* \ No newline at end of file diff --git a/database/eloquent.md b/database/eloquent.md index aedca70..687cf71 100644 --- a/database/eloquent.md +++ b/database/eloquent.md @@ -1,306 +1,470 @@ -## Eloquent ORM - -- [Conventions](#conventions) -- [Retrieving Models](#get) -- [Aggregates](#aggregates) -- [Inserting & Updating Models](#save) -- [Relationships](#relationships) -- [Eager Loading](#eager) - -An ORM is an [object-relational mapper](http://en.wikipedia.org/wiki/Object-relational_mapping), and Laravel has one that you will absolutely love to use. It is named "Eloquent" because it allows you to work with your database objects and relationships using an eloquent and expressive syntax. In general, you will define one Eloquent model for each table in your database. To get started, let's define a simple model: - - class User extends Eloquent {} - -Nice! Notice that our model extends the **Eloquent** class. This class will provide all of the functionality you need to start working eloquently with your database. - -> **Note:** Typically, Eloquent models live in the **application/models** directory. - - -### Conventions - -Eloquent makes a few basic assumptions about your database structure: - -- Each table should have a primary key named **id**. -- Each table name should be the plural form of its corresponding model name. - -Sometimes you may wish to use a table name other than the plural form of your model. No problem. Just add a static **table** property your model: - - class User extends Eloquent { - - public static $table = 'my_users'; - - } - - -### Retrieving Models - -Retrieving models using Eloquent is refreshingly simple. The most basic way to retrieve an Eloquent model is the static **find** method. This method will return a single model by primary key with properties corresponding to each column on the table: - - $user = User::find(1); - - echo $user->email; - -The find method will execute a query that looks something like this: - - SELECT * FROM "users" WHERE "id" = 1 - -Need to retrieve an entire table? Just use the static **all** method: - - $users = User::all(); - - foreach ($users as $user) - { - echo $user->email; - } - -Of course, retrieving an entire table isn't very helpful. Thankfully, **every method that is available through the fluent query builder is available in Eloquent**. Just begin querying your model with a static call to one of the [query builder](/docs/database/query) methods, and execute the query using the **get** or **first** method. The get method will return an array of models, while the first method will return a single model: - - $user = User::where('email', '=', $email)->first(); - - $user = User::where_email($email)->first(); - - $users = User::where_in('id', array(1, 2, 3))->or_where('email', '=', $email)->get(); - - $users = User::order_by('votes', 'desc')->take(10)->get(); - -> **Note:** If no results are found, the **first** method will return NULL. The **all** and **get** methods return an empty array. - - -### Aggregates - -Need to get a **MIN**, **MAX**, **AVG**, **SUM**, or **COUNT** value? Just pass the column to the appropriate method: - - $min = User::min('id'); - - $max = User::max('id'); - - $avg = User::avg('id'); - - $sum = User::sum('id'); - - $count = User::count(); - -Of course, you may wish to limit the query using a WHERE clause first: - - $count = User::where('id', '>', 10)->count(); - - -### Inserting & Updating Models - -Inserting Eloquent models into your tables couldn't be easier. First, instantiate a new model. Second, set its properties. Third, call the **save** method: - - $user = new User; - - $user->email = 'example@gmail.com'; - $user->password = 'secret'; - - $user->save(); - -Updating models is just as simple. Instead of instantiating a new model, retrieve one from your database. Then, set its properties and save: - - $user = User::find(1); - - $user->email = 'new_email@gmail.com'; - $user->password = 'new_secret'; - - $user->save(); - -Need to maintain creation and update timestamps on your database records? With Eloquent, you don't have to worry about it. Just add a static **timestamps** property to your model: - - class User extends Eloquent { - - public static $timestamps = true; - - } - -Next, add **created_at** and **updated_at** date columns to your table. Now, whenever you save the model, the creation and update timestamps will be set automatically. You're welcome. - -> **Note:** You can change the default timezone of your application in the **application/config/application.php** file. - - -### Relationships - -Unless you're doing it wrong, your database tables are probably related to one another. For instance, an order may belong to a user. Or, a post may have many comments. Eloquent makes defining relationships and retrieving related models simple and intuitive. Laravel supports three types of relationships: - -- [One-To-One](#one-to-one) -- [One-To-Many](#one-to-many) -- [Many-To-Many](#many-to-many) - -To define a relationship on an Eloquent model, you simply create a method that returns the result of either the **has\_one**, **has\_many**, **belongs\_to**, or **has\_and\_belongs\_to\_many** method. Let's examine each one in detail. - - -#### One-To-One - -A one-to-one relationship is the most basic form of relationship. For example, let's pretend a user has one phone. Simply describe this relationship to Eloquent: - - class User extends Eloquent { - - public function phone() - { - return $this->has_one('Phone'); - } - - } - -Notice that the name of the related model is passed to the **has_one** method. You can now retrieve the phone of a user through the **phone** method: - - $phone = User::find(1)->phone()->first(); - -Let's examine the SQL performed by this statement. Two queries will be performed: one to retrieve the user and one to retrieve the user's phone: - - SELECT * FROM "users" WHERE "id" = 1 - - SELECT * FROM "phones" WHERE "user_id" = 1 - -Note that Eloquent assumes the foreign key of the relationship will be **user\_id**. Most foreign keys will follow this **model\_id** convention; however, if you want to use a different column name as the foreign key, just pass it in the second parameter to the method: - - return $this->has_one('Phone', 'my_foreign_key'); - -Want to just retrieve the user's phone without calling the first method? No problem. Just use the **dynamic phone property**. Eloquent will automatically load the relationship for you, and is even smart enough to know whether to call the get (for one-to-many relationships) or first (for one-to-one relationships) method: - - $phone = User::find(1)->phone; - -What if you need to retrieve a phone's user? Since the foreign key (**user\_id**) is on the phones table, we should describe this relationship using the **belongs\_to** method. It makes sense, right? Phones belong to users. When using the **belongs\_to** method, the name of the relationship method should correspond to the foreign key (sans the **\_id**). Since the foreign key is **user\_id**, your relationship method should be named **user**: - - class Phone extends Eloquent { - - public function user() - { - return $this->belongs_to('User'); - } - - } - -Great! You can now access a User model through a Phone model using either your relationship method or dynamic property: - - echo Phone::find(1)->user()->first()->email; - - echo Phone::find(1)->user->email; - - -#### One-To-Many - -Assume a blog post has many comments. It's easy to define this relationship using the **has_many** method: - - class Post extends Eloquent { - - public function comments() - { - return $this->has_many('Comment'); - } - - } - -Now, simply access the post comments through the relationship method or dynamic property: - - $comments = Post::find(1)->comments()->get(); - - $comments = Post::find(1)->comments; - -Both of these statements will execute the following SQL: - - SELECT * FROM "posts" WHERE "id" = 1 - - SELECT * FROM "comments" WHERE "post_id" = 1 - -Want to join on a different foreign key? No problem. Just pass it in the second parameter to the method: - - return $this->has_many('Comment', 'my_foreign_key'); - -You may be wondering: _If the dynamic properties return the relationship and require less keystokes, why would I ever use the relationship methods?_ Actually, relationship methods are very powerful. They allow you to continue to chain query methods before retrieving the relationship. Check this out: - - echo Post::find(1)->comments()->order_by('votes', 'desc')->take(10)->get(); - - -#### Many-To-Many - -Many-to-many relationships are the most complicated of the three relationships. But don't worry, you can do this. For example, assume a User has many Roles, but a Role can also belong to many Users. Three database tables must be created to accomplish this relationship: a **users** table, a **roles** table, and a **roles_users** table. The structure for each table looks like this: - -**Users:** - - id - INTEGER - email - VARCHAR - -**Roles:** - - id - INTEGER - name - VARCHAR - -**Roles_Users:** - - user_id - INTEGER - role_id - INTEGER - -Now you're ready to define the relationship on your models using the **has\_and\_belongs\_to\_many** method: - - class User extends Eloquent { - - public function roles() - { - return $this->has_and_belongs_to_many('Role'); - } - - } - -Great! Now it's time to retrieve a user's roles: - - $roles = User::find(1)->roles()->get(); - -Or, as usual, you may retrieve the relationship through the dynamic roles property: - - $roles = User::find(1)->roles; - -As you may have noticed, the default name of the intermediate table is the plural names of the two related models arranged alphabetically and concatenated by an underscore. However, you are free to specify your own table name. Simply pass the table name in the second parameter to the **has\_and\_belongs\_to\_many** method: - - class User extends Eloquent { - - public function roles() - { - return $this->has_and_belongs_to_many('Role', 'user_roles'); - } - - } - - -### Eager Loading - -Eager loading exists to alleviate the N + 1 query problem. Exactly what is this problem? Well, pretend each Book belongs to an Author. We would describe this relationship like so: - - class Book extends Eloquent { - - public function author() - { - return $this->belongs_to('Author'); - } - - } - -Now, examine the following code: - - foreach (Book::all() as $book) - { - echo $book->author->name; - } - -How many queries will be executed? Well, one query will be executed to retrieve all of the books from the table. However, another query will be required for each book to retrieve the author. To display the author name for 25 books would require **26 queries**. See how the queries can add up fast? - -Thankfully, you can eager load the author models using the **with** method. Simply mention the **function name** of the relationship you wish to eager load: - - foreach (Book::with('author')->get() as $book) - { - echo $book->author->name; - } - -In this example, **only two queries will be executed**! - - SELECT * FROM "books" - - SELECT * FROM "authors" WHERE "id" IN (1, 2, 3, 4, 5, ...) - -Obviously, wise use of eager loading can dramatically increase the performance of your application. In the example above, eager loading cut the execution time in half. - -Need to eager load more than one relationship? It's easy: - - $books = Book::with('author', 'publisher')->get(); - -> **Note:** When eager loading, the call to the static **with** method must always be at the beginning of the query. \ No newline at end of file +# Eloquent ORM + +## Contents + +- [The Basics](#the-basics) +- [Conventions](#conventions) +- [Retrieving Models](#get) +- [Aggregates](#aggregates) +- [Inserting & Updating Models](#save) +- [Relationships](#relationships) +- [Inserting Related Models](#inserting-related-models) +- [Working With Pivot Tables](#pivot-tables) +- [Eager Loading](#eager) +- [Constraining Eager Loads](#constraining-eager-loads) +- [Setter & Getter Methods](#getter-and-setter-methods) +- [Mass-Assignment](#mass-assignment) + + +## The Basics + +An ORM is an [object-relational mapper](http://en.wikipedia.org/wiki/Object-relational_mapping), and Laravel has one that you will absolutely love to use. It is named "Eloquent" because it allows you to work with your database objects and relationships using an eloquent and expressive syntax. In general, you will define one Eloquent model for each table in your database. To get started, let's define a simple model: + + class User extends Eloquent {} + +Nice! Notice that our model extends the **Eloquent** class. This class will provide all of the functionality you need to start working eloquently with your database. + +> **Note:** Typically, Eloquent models live in the **application/models** directory. + + +## Conventions + +Eloquent makes a few basic assumptions about your database structure: + +- Each table should have a primary key named **id**. +- Each table name should be the plural form of its corresponding model name. + +Sometimes you may wish to use a table name other than the plural form of your model. No problem. Just add a static **table** property your model: + + class User extends Eloquent { + + public static $table = 'my_users'; + + } + + +## Retrieving Models + +Retrieving models using Eloquent is refreshingly simple. The most basic way to retrieve an Eloquent model is the static **find** method. This method will return a single model by primary key with properties corresponding to each column on the table: + + $user = User::find(1); + + echo $user->email; + +The find method will execute a query that looks something like this: + + SELECT * FROM "users" WHERE "id" = 1 + +Need to retrieve an entire table? Just use the static **all** method: + + $users = User::all(); + + foreach ($users as $user) + { + echo $user->email; + } + +Of course, retrieving an entire table isn't very helpful. Thankfully, **every method that is available through the fluent query builder is available in Eloquent**. Just begin querying your model with a static call to one of the [query builder](/docs/database/query) methods, and execute the query using the **get** or **first** method. The get method will return an array of models, while the first method will return a single model: + + $user = User::where('email', '=', $email)->first(); + + $user = User::where_email($email)->first(); + + $users = User::where_in('id', array(1, 2, 3))->or_where('email', '=', $email)->get(); + + $users = User::order_by('votes', 'desc')->take(10)->get(); + +> **Note:** If no results are found, the **first** method will return NULL. The **all** and **get** methods return an empty array. + + +## Aggregates + +Need to get a **MIN**, **MAX**, **AVG**, **SUM**, or **COUNT** value? Just pass the column to the appropriate method: + + $min = User::min('id'); + + $max = User::max('id'); + + $avg = User::avg('id'); + + $sum = User::sum('id'); + + $count = User::count(); + +Of course, you may wish to limit the query using a WHERE clause first: + + $count = User::where('id', '>', 10)->count(); + + +## Inserting & Updating Models + +Inserting Eloquent models into your tables couldn't be easier. First, instantiate a new model. Second, set its properties. Third, call the **save** method: + + $user = new User; + + $user->email = 'example@gmail.com'; + $user->password = 'secret'; + + $user->save(); + +Alternatively, you may use the **create** method, which will insert a new record into the database and return the model instance for the newly inserted record, or **false** if the insert failed. + + $user = User::create(array('email' => 'example@gmail.com')); + +Updating models is just as simple. Instead of instantiating a new model, retrieve one from your database. Then, set its properties and save: + + $user = User::find(1); + + $user->email = 'new_email@gmail.com'; + $user->password = 'new_secret'; + + $user->save(); + +Need to maintain creation and update timestamps on your database records? With Eloquent, you don't have to worry about it. Just add a static **timestamps** property to your model: + + class User extends Eloquent { + + public static $timestamps = true; + + } + +Next, add **created_at** and **updated_at** date columns to your table. Now, whenever you save the model, the creation and update timestamps will be set automatically. You're welcome. + +> **Note:** You can change the default timezone of your application in the **application/config/application.php** file. + + +## Relationships + +Unless you're doing it wrong, your database tables are probably related to one another. For instance, an order may belong to a user. Or, a post may have many comments. Eloquent makes defining relationships and retrieving related models simple and intuitive. Laravel supports three types of relationships: + +- [One-To-One](#one-to-one) +- [One-To-Many](#one-to-many) +- [Many-To-Many](#many-to-many) + +To define a relationship on an Eloquent model, you simply create a method that returns the result of either the **has\_one**, **has\_many**, **belongs\_to**, or **has\_many\_and\_belongs\_to** method. Let's examine each one in detail. + + +### One-To-One + +A one-to-one relationship is the most basic form of relationship. For example, let's pretend a user has one phone. Simply describe this relationship to Eloquent: + + class User extends Eloquent { + + public function phone() + { + return $this->has_one('Phone'); + } + + } + +Notice that the name of the related model is passed to the **has_one** method. You can now retrieve the phone of a user through the **phone** method: + + $phone = User::find(1)->phone()->first(); + +Let's examine the SQL performed by this statement. Two queries will be performed: one to retrieve the user and one to retrieve the user's phone: + + SELECT * FROM "users" WHERE "id" = 1 + + SELECT * FROM "phones" WHERE "user_id" = 1 + +Note that Eloquent assumes the foreign key of the relationship will be **user\_id**. Most foreign keys will follow this **model\_id** convention; however, if you want to use a different column name as the foreign key, just pass it in the second parameter to the method: + + return $this->has_one('Phone', 'my_foreign_key'); + +Want to just retrieve the user's phone without calling the first method? No problem. Just use the **dynamic phone property**. Eloquent will automatically load the relationship for you, and is even smart enough to know whether to call the get (for one-to-many relationships) or first (for one-to-one relationships) method: + + $phone = User::find(1)->phone; + +What if you need to retrieve a phone's user? Since the foreign key (**user\_id**) is on the phones table, we should describe this relationship using the **belongs\_to** method. It makes sense, right? Phones belong to users. When using the **belongs\_to** method, the name of the relationship method should correspond to the foreign key (sans the **\_id**). Since the foreign key is **user\_id**, your relationship method should be named **user**: + + class Phone extends Eloquent { + + public function user() + { + return $this->belongs_to('User'); + } + + } + +Great! You can now access a User model through a Phone model using either your relationship method or dynamic property: + + echo Phone::find(1)->user()->first()->email; + + echo Phone::find(1)->user->email; + + +### One-To-Many + +Assume a blog post has many comments. It's easy to define this relationship using the **has_many** method: + + class Post extends Eloquent { + + public function comments() + { + return $this->has_many('Comment'); + } + + } + +Now, simply access the post comments through the relationship method or dynamic property: + + $comments = Post::find(1)->comments()->get(); + + $comments = Post::find(1)->comments; + +Both of these statements will execute the following SQL: + + SELECT * FROM "posts" WHERE "id" = 1 + + SELECT * FROM "comments" WHERE "post_id" = 1 + +Want to join on a different foreign key? No problem. Just pass it in the second parameter to the method: + + return $this->has_many('Comment', 'my_foreign_key'); + +You may be wondering: _If the dynamic properties return the relationship and require less keystokes, why would I ever use the relationship methods?_ Actually, relationship methods are very powerful. They allow you to continue to chain query methods before retrieving the relationship. Check this out: + + echo Post::find(1)->comments()->order_by('votes', 'desc')->take(10)->get(); + + +### Many-To-Many + +Many-to-many relationships are the most complicated of the three relationships. In this example we have a User model which can have many Roles. But, a Role can also belong to many Users. Three database tables must be created to accomplish this relationship: a **users** table, a **roles** table, and a **role_user** table. We call the **role_user** table the "pivot table." + +The structure for each table looks like this: + +**Users:** + + id - INTEGER + email - VARCHAR + +**Roles:** + + id - INTEGER + name - VARCHAR + +**Roles_Users:** + + user_id - INTEGER + role_id - INTEGER + +Now you're ready to define the relationship on your models using the **has\_many\_and\_belongs\_to** method: + + class User extends Eloquent { + + public function roles() + { + return $this->has_many_and_belongs_to('Role'); + } + + } + +Great! Now it's time to retrieve a user's roles: + + $roles = User::find(1)->roles()->get(); + +Or, as usual, you may retrieve the relationship through the dynamic roles property: + + $roles = User::find(1)->roles; + +As you may have noticed, the default name of the pivot table is the singular names of the two related models arranged alphabetically and concatenated by an underscore. However, you are free to specify your own table name. Simply pass the table name in the second parameter to the **has\_and\_belongs\_to\_many** method: + + class User extends Eloquent { + + public function roles() + { + return $this->has_many_and_belongs_to('Role', 'user_roles'); + } + + } + + +## Inserting Related Models + +Let's assume you have a **Post** model that has many comments. Often you may want to insert a new comment for a given post. Instead of manually setting the **post_id** foreign key on your model, you may insert the new comment from it's owning Post model. Here's what it looks like: + + $comment = new Comment(array('message' => 'A new comment.')); + + $post = Post::find(1); + + $post->comments()->insert($comment); + +When inserting related models through their parent model, the foreign key will automatically be set. So, in this case, the "post_id" was automatically set to "1" on the newly inserted comment. + +This is even more helpful when working with many-to-many relationships. For example, consider a **User** model that has many roles. Likewise, the **Role** model may have many users. So, the pivot table for this relationship has "user_id" and "role_id" columns. Now, let's insert a new Role for a User: + + $role = new Role(array('title' => 'Admin')); + + $user = User::find(1); + + $user->roles()->insert($role); + +Now, when the Role is inserted, not only is the Role inserted into the "roles" table, but a record in the pivot table is also inserted for you. It couldn't be easier! + +However, you may often only want to insert a new record into the pivot table. For example, perhaps the role you wish to attach to the user already exists. Just use the attach method: + + $user->roles()->attach($role_id); + + +## Working With Pivot Tables + +As your probably know, many-to-many relationships require the presence of an intermediate table. In one example case we have a **User** model that has many roles. And, likewise, a **Role** model that has many users. So the intermediate table has "user_id" and "role_id" columns. + +These tables are called **pivot tables**. We can access the pivot table for the relationship like so: + + $user = User::find(1); + + $pivot = $user->roles()->pivot(); + +Once we have an instance of the pivot table, we can use it just like any other Eloquent model: + + foreach ($user->roles()->pivot()->get() as $row) + { + // + } + +You may also access a specific row in the pivot table that is associated with a given record. For example: + + $user = User::find(1); + + foreach ($user->roles as $role) + { + echo $role->pivot->created_at; + } + +Notice that each related **Role** model we retrieved is automatically assigned a **pivot** attribute. This attribute contains a model representing the intermediate table record associated with that related model. + +Sometimes you may wish to remove all of the record from the intermediate table for a given model relationship. For instance, perhaps you want to remove all of the assigned roles from a user. Here's how to do it: + + $user = User::find(1); + + $user->roles()->delete(); + +Note that this does not delete the roles from the "roles" table, but only removes the records from the pivot table which associated the roles with the given user. + +If you ever find yourself wanting to add additional data into the pivot table during an **insert** or **attach** you can do so by passing an array of data as the second parameter for both: + + $post->comments()->insert($comment, array('visible' => 1)); + + $user->roles()->attach($role_id, array('active' => 1)); + + +## Eager Loading + +Eager loading exists to alleviate the N + 1 query problem. Exactly what is this problem? Well, pretend each Book belongs to an Author. We would describe this relationship like so: + + class Book extends Eloquent { + + public function author() + { + return $this->belongs_to('Author'); + } + + } + +Now, examine the following code: + + foreach (Book::all() as $book) + { + echo $book->author->name; + } + +How many queries will be executed? Well, one query will be executed to retrieve all of the books from the table. However, another query will be required for each book to retrieve the author. To display the author name for 25 books would require **26 queries**. See how the queries can add up fast? + +Thankfully, you can eager load the author models using the **with** method. Simply mention the **function name** of the relationship you wish to eager load: + + foreach (Book::with('author')->get() as $book) + { + echo $book->author->name; + } + +In this example, **only two queries will be executed**! + + SELECT * FROM "books" + + SELECT * FROM "authors" WHERE "id" IN (1, 2, 3, 4, 5, ...) + +Obviously, wise use of eager loading can dramatically increase the performance of your application. In the example above, eager loading cut the execution time in half. + +Need to eager load more than one relationship? It's easy: + + $books = Book::with(array('author', 'publisher'))->get(); + +> **Note:** When eager loading, the call to the static **with** method must always be at the beginning of the query. + +You may even eager load nested relationships. For example, let's assume our **Author** model has a "contacts" relationship. We can eager load both of the relationships from our Book model like so: + + $books = Book::with(array('author', 'author.contacts'))->get(); + + +## Constraining Eager Loads + +Sometimes you may wish to eager load a relationship, but also specify a condition for the eager load. It's simple. Here's what it looks like: + + $users = User::with(array('posts' => function($query) + { + $query->where('title', 'like', '%first%'); + + }))->get(); + +In this example, we're eager loading the posts for the users, but only if the post's "title" column contains the word "first". + + +## Getter & Setter Methods + +Setters allow you to handle attribute assignment with custom methods. Define a setter by appending "set_" to the intended attribute's name. + + public function set_password($password) + { + $this->set_attribute('hashed_password', Hash::make($password)); + } + +Call a setter method as a variable (without parenthesis) using the name of the method without the "set_" prefix. + + $this->password = "my new password"; + +Getters are very similar. They can be used to modify attributes before they're returned. Define a getter by appending "get_" to the intended attribute's name. + + public function get_published_date() + { + return date('M j, Y', $this->get_attribute('published_at')); + } + +Call the getter method as a variable (without parenthesis) using the name of the method without the "get_" prefix. + + echo $this->published_date; + + +## Mass-Assignment + +Mass-assignment is the practice of passing an associative array to a model method which then fills the model's attributes with the values from the array. Mass-assignment can be done by passing an array to the model's constructor: + + $user = new User(array( + 'username' => 'first last', + 'password' => 'disgaea' + )); + + $user->save(); + +Or, mass-assignment may be accomplished using the **fill** method. + + $user = new User; + + $user->fill(array( + 'username' => 'first last', + 'password' => 'disgaea' + )); + + $user->save(); + +By default, all attribute key/value pairs will be stored during mass-assignment. However, it is possible to create a whitelist of attributes that will be set. If the accessible attribute whitelist is set then no attributes other than those specified will be set during mass-assignment. + +You can specify accessible attributes by assigning the **$accessible** static array. Each element contains the name of a whitelisted attribute. + + public static $accessible = array('email', 'password', 'name'); + +Alternatively, you may use the **accessible** method from your model: + + User::accessible(array('email', 'password', 'name')); + +> **Note:** Utmost caution should be taken when mass-assigning using user-input. Technical oversights could cause serious security vulnerabilities. \ No newline at end of file diff --git a/database/fluent.md b/database/fluent.md new file mode 100644 index 0000000..6ab3447 --- /dev/null +++ b/database/fluent.md @@ -0,0 +1,270 @@ +# Fluent Query Builder + +## Contents + +- [The Basics](#the-basics) +- [Retrieving Records](#get) +- [Building Where Clauses](#where) +- [Nested Where Clauses](#nested-where) +- [Dynamic Where Clauses](#dynamic) +- [Table Joins](#joins) +- [Ordering Results](#ordering) +- [Skip & Take](#limit) +- [Aggregates](#aggregates) +- [Expressions](#expressions) +- [Inserting Records](#insert) +- [Updating Records](#update) +- [Deleting Records](#delete) + +## The Basics + +The Fluent Query Builder is Laravel's powerful fluent interface for building SQL queries and working with your database. All queries use prepared statements and are protected against SQL injection. + +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. + + +## Retrieving Records + +#### Retrieving an array of records from the database: + + $users = DB::table('users')->get(); + +> **Note:** The **get** method returns an array of objects with properties corresponding to the column on the table. + +#### Retrieving a single record from the database: + + $user = DB::table('users')->first(); + +#### Retrieving a single record by its primary key: + + $user = DB::table('users')->find($id); + +> **Note:** If no results are found, the **first** method will return NULL. The **get** method will return an empty array. + +#### Retrieving the value of a single column from the database: + + $email = DB::table('users')->where('id', '=', 1)->only('email'); + +#### Only selecting certain columns from the database: + + $user = DB::table('users')->get(array('id', 'email as user_email')); + +#### Selecting distinct results from the database: + + $user = DB::table('users')->distinct()->get(); + + +## Building Where Clauses + +### where and or\_where + +There are a variety of methods to assist you in building where clauses. 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(); + +As you may have assumed, the **where** method will add to the query using an AND condition, while the **or_where** method will use an OR condition. + +### 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(); + + +## Nested Where Clauses + +You may discover the need to group portions of a WHERE clause within parentheses. Just pass a Closure as parameter to the **where** or **or_where** methods: + + $users = DB::table('users') + ->where('id', '=', 1) + ->or_where(function($query) + { + $query->where('age', '>', 25); + $query->where('votes' '>', 100); + }) + ->get(); + +The example above would generate a query that looks like: + + SELECT * FROM "users" WHERE "id" = ? OR ("age" > ? AND "votes" > ?) + + +## Dynamic Where Clauses + +Dynamic where methods are great way to increase the readability of your code. Here are some examples: + + $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'); + + + +## 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')); + +You may also specify multiple conditions for an **ON** clause by passing a Closure as the second parameter of the join: + + DB::table('users') + ->join('phone', function($join) + { + $join->on('users.id', '=', 'phone.user_id'); + $join->or_on('users.id', '=', 'phone.contact_id'); + }) + ->get(array('users.email', 'phone.numer')); + + +## 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(); + + +## 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(); + + +## 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(); + + +## Expressions + +Sometimes you may need to set the value of a column to a SQL function such as **NOW()**. Usually a reference to now() would automatically be quoted and escaped. To prevent this use the **raw** method on the **DB** class. Here's what it looks like: + + DB::table('users')->update(array('updated_at' => DB::raw('NOW()'))); + +The **raw** method tells the query to inject the contents of the expression into the query as a string rather than a bound parameter. For example, you can also use expressions to increment column values: + + DB::table('users')->update(array('votes' => DB::raw('votes + 1'))); + +Of course, convenient methods are provided for **increment** and **decrement**: + + DB::table('users')->increment('votes'); + + DB::table('users')->decrement('votes'); + + +## Inserting Records + +The insert method expects an array of values to insert. The insert method will 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". + + +## Updating Records + +To update records 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')); + + +## 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 diff --git a/database/migrations.md b/database/migrations.md new file mode 100644 index 0000000..8c09563 --- /dev/null +++ b/database/migrations.md @@ -0,0 +1,72 @@ +# Migrations + +## Contents + +- [The Basics](#the-basics) +- [Prepping Your Database](#prepping-your-database) +- [Creating Migrations](#creating-migrations) +- [Running Migrations](#running-migrations) +- [Rolling Back](#rolling-back) + + +## The Basics + +Think of migrations as a type of version control for your database. Let's say your working on a team, and you all have local databases for development. Good ole' Eric makes a change to the database and checks in his code that uses the new column. You pull in the code, and your application breaks because you don't have the new column. What do you do? Migrations are the answer. Let's dig in deeper to find out how to use them! + + +## Prepping Your Database + +Before you can run migrations, we need to do some work on your database. Laravel uses a special table to keep track of which migrations have already run. To create this table, just use the Artisan command-line: + +**Creating the Laravel migrations table:** + + php artisan migrate:install + + +## Creating Migrations + +You can easily create migrations through Laravel's "Artisan" CLI. It looks like this: + +**Creating a migration** + + php artisan migrate:make create_users_table + +Now, check your **application/migrations** folder. You should see your brand new migration! Notice that it also contains a timestamp. This allows Laravel to run your migrations in the correct order. + +You may also create migrations for a bundle. + +**Creating a migration for a bundle:** + + php artisan migrate:make bundle::create_users_table + +*Further Reading:* + +- [Schema Builder](/docs/database/schema) + + +## Running Migrations + +**Running all outstanding migrations in application and bundles:** + + php artisan migrate + +**Running all outstanding migrations in the application:** + + php artisan migrate application + +**Running all outstanding migrations in a bundle:** + + php artisan migrate bundle + + +## Rolling Back + +When you roll back a migration, Laravel rolls back the entire migration "operation". So, if the last migration command ran 122 migrations, all 122 migrations would be rolled back. + +**Rolling back the last migration operation:** + + php artisan migrate:rollback + +**Roll back all migrations that have ever run:** + + php artisan migrate:reset \ No newline at end of file diff --git a/database/query.md b/database/query.md deleted file mode 100644 index 70dda78..0000000 --- a/database/query.md +++ /dev/null @@ -1,216 +0,0 @@ -## 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. - - -### 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. - - -### 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(); - - -### 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? - - -### 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')); - - -### 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(); - - -### 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(); - - -### 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(); - - -### 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". - - -### 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')); - - -### 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 diff --git a/database/raw.md b/database/raw.md new file mode 100644 index 0000000..e029f73 --- /dev/null +++ b/database/raw.md @@ -0,0 +1,58 @@ +# Raw Queries + +## Contents + +- [The Basics](#the-basics) +- [Other Query Methods](#other-query-methods) +- [PDO Connections](#pdo-connections) + + +## The Basics + +The **query** method is used to execute arbitrary, raw SQL against your database connection. + +#### Selecting records from the database: + + $users = DB::query('select * from users'); + +#### Selecting records from the database using bindings: + + $users = DB::query('select * from users where name = ?', array('test')); + +#### Inserting a record into the database + + $success = DB::query('insert into users values (?, ?)', $bindings); + +#### Updating table records and getting the number of affected rows: + + $affected = DB::query('update users set name = ?', $bindings); + +#### Deleting from a table and getting the number of affected rows: + + $affected = DB::query('delete from users where id = ?', array(1)); + + +## Other Query Methods + +Laravel provides a few other methods to make querying your database simple. Here's an overview: + +#### Running a SELECT query and returning the first result: + + $user = DB::first('select * from users where id = 1'); + +#### Running a SELECT query and getting the value of a single column: + + $email = DB::only('select email from users where id = 1'); + +> **Note:** If more than one record matches for **DB::only()**, just the first result will be returned. + + +## PDO Connections + +Sometimes you may wish to access the raw PDO connection behind the Laravel Connection object. + +#### Get the raw PDO connection for a database: + + $pdo = DB::connection('sqlite')->pdo; + +> **Note:** If no connection name is specified, the **default** connection will be returned. \ No newline at end of file diff --git a/database/redis.md b/database/redis.md new file mode 100644 index 0000000..8abdd5c --- /dev/null +++ b/database/redis.md @@ -0,0 +1,58 @@ +# Redis + +## Contents + +- [The Basics](#the-basics) +- [Configuration](#config) +- [Usage](#usage) + + +## The Basics + +[Redis](http://redis.io) is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain [strings](http://redis.io/topics/data-types#strings), [hashes](http://redis.io/topics/data-types#hashes), [lists](http://redis.io/topics/data-types#lists), [sets](http://redis.io/topics/data-types#sets), and [sorted sets](http://redis.io/topics/data-types#sorted-sets). + + +## Configuration + +The Redis configuration for your application lives in the **application/config/database.php** file. Within this file, you will see a **redis** array containing the Redis servers used by your application: + + 'redis' => array( + + 'default' => array('host' => '127.0.0.1', 'port' => 6379), + + ), + +The default server configuration should suffice for development. However, you are free to modify this array based on your environment. Simply give each Redis server a name, and specify the host and port used by the server. + + +## Usage + +You may get a Redis instance by calling the **db** method on the **Redis** class: + + $redis = Redis::db(); + +This will give you an instance of the **default** Redis server. You may pass the server name to the **db** method to get a specific server as defined in your Redis configuration: + + $redis = Redis::db('redis_2'); + +Great! Now that we have an instance of the Redis client, we may issue any of the [Redis commands](http://redis.io/commands) to the instance. Laravel uses magic methods to pass the commands to the Redis server: + + $redis->set('name', 'Taylor'); + + $name = $redis->get('name'); + + $values = $redis->lrange('names', 5, 10); + +Notice the arguments to the comment are simply passed into the magic method. Of course, you are not required to use the magic methods, you may also pass commands to the server using the **run** method: + + $values = $redis->run('lrange', array(5, 10)); + +Just want to execute commands on the default Redis server? You can just use static magic methods on the Redis class: + + Redis::set('name', 'Taylor'); + + $name = Redis::get('name'); + + $values = Redis::lrange('names', 5, 10); + +> **Note:** Redis [cache](/docs/cache/config#redis) and [session](/docs/session/config#redis) drivers are included with Laravel. \ No newline at end of file diff --git a/database/schema.md b/database/schema.md new file mode 100644 index 0000000..61592c7 --- /dev/null +++ b/database/schema.md @@ -0,0 +1,142 @@ +# Schema Builder + +## Contents + +- [The Basics](#the-basics) +- [Creating & Dropping Tables](#creating-dropping-tables) +- [Adding Columns](#adding-columns) +- [Dropping Columns](#dropping-columns) +- [Adding Indexes](#adding-indexes) +- [Dropping Indexes](#dropping-indexes) +- [Foreign Keys](#foreign-keys) + + +## The Basics + +The Schema Bulder provides methods for creating and modifying your database tables. Using a fluent syntax, you can work with your tables without using any vendor specific SQL. + +*Further Reading:* + +- [Migrations](/docs/database/migrations) + + +## Creating & Dropping Tables + +The **Schema** class is used to create and modify tables. Let's jump right into an example: + +#### Creating a simple database table: + + Schema::create('users', function($table) + { + $table->increments('id'); + }); + +Let's go over this example. The **create** method tells the Schema builder that this is a new table, so it should be created. In the second argument, we passed a Closure which receives a Table instance. Using this Table object, we can fluently add and drop columns and indexes on the table. + +#### Dropping a table from the database: + + Schema::drop('users'); + +Sometimes you may need to specify the database connection on which the schema operation should be performed. + +#### Specifying the connection to run the operation on: + + Schema::create('users', function($table) + { + $table->on('connection'); + }); + + +## Adding Columns + +The fluent table builder's methods allow you to add columns without using vendor specific SQL. Let's go over it's methods: + +Command | Description +------------- | ------------- +`$table->increments('id');` | Incrementing ID to the table +`$table->string('email');` | VARCHAR equivalent column +`$table->string('name', 100);` | VARCHAR equivalent with a length +`$table->integer('votes');` | INTEGER equivalent to the table +`$table->float('amount');` | FLOAT equivalent to the table +`$table->boolean('confirmed');` | BOOLEAN equivalent to the table +`$table->date('created_at');` | DATE equivalent to the table +`$table->timestamp('added_on');` | TIMESTAMP equivalent to the table +`$table->timestamps();` | Adds **created\_at** and **updated\_at** columns +`$table->text('description');` | TEXT equivalent to the table +`$table->blob('data');` | BLOB equivalent to the table +`->nullable()` | Designate that the column allows NULL values +`->default($value)` | Specify a default value on a column + +> **Note:** Laravel's "boolean" type maps to a small integer column on all database systems. + +#### Example of creating a table and adding columns + + Schema::table('users', function($table) + { + $table->create(); + $table->increments('id'); + $table->string('username'); + $table->string('email'); + $table->string('phone')->nullable(); + $table->text('about'); + $table->timestamps(); + }); + + +## Dropping Columns + +#### Dropping a column from a database table: + + $table->drop_column('name'); + +#### Dropping several columns from a database table: + + $table->drop_column(array('name', 'email')); + + +## Adding Indexes + +The Schema builder supports several types of indexes. There are two ways to add the indexes. Each type of index has its method; however, you can also fluently define an index on the same line as a column addition. Let's take a look: + +#### Fluently creating a string column with an index: + + $table->string('email')->unique(); + +If defining the indexes on a separate line is more your style, here are example of using each of the index methods: + +Command | Description +------------- | ------------- +`$table->primary('id');` | Adding a primary key +`$table->primary(array('fname', 'lname'));` | Adding composite keys +`$table->unique('email');` | Adding a unique index +`$table->fulltext('description');` | Adding a full-text index +`$table->index('state');` | Adding a basic index + + +## Dropping Indexes + +To drop indexes you must specify the index's name. Laravel assigns a reasonable name to all indexes. Simply concatenate the table name and the names of the columns in the index, then append the type of the index. Let's take a look at some examples: + +Command | Description +------------- | ------------- +`$table->drop_primary('users_id_primary');` | Dropping a primary key from the "users" table +`$table->drop_unique('users_email_unique');` | Dropping a unique index from the "users" table +`$table->drop_fulltext('profile_description_fulltext');` | Dropping a full-text index from the "profile" table +`$table->drop_index('geo_state_index');` | Dropping a basic index from the "geo" table + + +## Foreign Keys + +You may easily add foreign key constraints to your table using Schema's fluent interface. For example, let's assume you have a **user_id** on a **posts** table, which references the **id** column of the **users** table. Here's how to add a foreign key constraint for the column: + + $table->foreign('user_id')->references('id')->on('users'); + +You may also specify options for the "on delete" and "on update" actions of the foreign key: + + $table->foreign('user_id')->references('id')->on('users')->on_delete('restrict'); + + $table->foreign('user_id')->references('id')->on('users')->on_update('cascade'); + +You may also easily drop a foreign key constraint. The default foreign key names follow the [same convention](#dropping-indexes) as the other indexes created by the Schema builder. Here's an example: + + $table->drop_foreign('posts_user_id_foreign'); \ No newline at end of file diff --git a/database/usage.md b/database/usage.md deleted file mode 100644 index ffa8d0c..0000000 --- a/database/usage.md +++ /dev/null @@ -1,37 +0,0 @@ -## 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. - -When you need to get only one record from a table, use the **first** method. The method will return a single stdClass instance, or NULL if no records are found: - - $user = DB::first('select * from users where id = 1'); - -### 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 diff --git a/encryption.md b/encryption.md new file mode 100644 index 0000000..9d7e6ce --- /dev/null +++ b/encryption.md @@ -0,0 +1,30 @@ +# Encryption + +## Contents + +- [The Basics](#the-basics) +- [Encrypting A String](#encrypt) +- [Decrypting A String](#decrypt) + + +## The Basics + +Laravel's **Crypter** class provides a simple interface for handling secure, two-way encryption. By default, the Crypter class provides strong AES-256 encryption and decryption out of the box via the Mcrypt PHP extension. + +> **Note:** Don't forget to install the Mcrypt PHP extension on your server. + + +## Encrypting A String + +#### Encrypting a given string: + + $encrypted = Crypter::encrypt($value); + + +## Decrypting A String + +#### Decrypting a string: + + $decrypted = Crypter::decrypt($encrypted); + +> **Note:** It's incredibly important to point out that the decrypt method will only decrypt strings that were encrypted using **your** application key. \ No newline at end of file diff --git a/events.md b/events.md new file mode 100644 index 0000000..dc74745 --- /dev/null +++ b/events.md @@ -0,0 +1,73 @@ +# Events + +## Contents + +- [The Basics](#the-basics) +- [Firing Events](#firing-events) +- [Listening To Events](#listening-to-events) +- [Laravel Events](#laravel-events) + + +## The Basics + +Events can provide a great away to build de-coupled applications, and allow plug-ins to tap into the core of your application without modifying its code. + + +## Firing Events + +To fire an event, just tell the **Event** class the name of the event you want to fire: + +#### Firing an event: + + $responses = Event::fire('loaded'); + +Notice that we assigned the result of the **fire** method to a variable. This method will return an array containing the responses of all the event's listeners. + +Sometimes you may want to fire an event, but just get the first response. Here's how: + +#### Firing an event and retrieving the first response: + + $response = Event::first('loaded'); + +> **Note:** The **first** method will still fire all of the handlers listening to the event, but will only return the first response. + +The **Event::until** method will execute the event handlers until the first non-null response is returned. + +#### Firing an event until the first non-null response: + + $response = Event::until('loaded'); + + +## Listening To Events + +So, what good are events if nobody is listening? Register an event handler that will be called when an event fires: + +#### Registering an event handler: + + Event::listen('loaded', function() + { + // I'm executed on the "loaded" event! + }); + +The Closure we provided to the method will be executed each time the "loaded" event is fired. + + +## Laravel Events + +There are several events that are fired by the Laravel core. Here they are: + +#### Event fired when a bundle is started: + + Event::listen('laravel.started: bundle', function() {}); + +#### Event fired when a database query is executed: + + Event::listen('laravel.query', function($sql, $bindings, $time) {}); + +#### Event fired right before response is sent to browser: + + Event::listen('laravel.done', function($response) {}); + +#### Event fired when a messaged is logged using the Log class: + + Event::listen('laravel.log', function($type, $message) {}); \ No newline at end of file diff --git a/files.md b/files.md new file mode 100644 index 0000000..a0febad --- /dev/null +++ b/files.md @@ -0,0 +1,84 @@ +# Working With Files + +## Contents + +- [Reading Files](#get) +- [Writing Files](#put) +- [File Uploads](#upload) +- [File Extensions](#ext) +- [Checking File Types](#is) +- [Getting MIME Types](#mime) +- [Copying Directories](#cpdir) +- [Removing Directories](#rmdir) + + +## Reading Files + +#### Getting the contents of a file: + + $contents = File::get('path/to/file'); + + +## Writing Files + +#### Writing to a file: + + File::put('path/to/file', 'file contents'); + +#### Appending to a file: + + File::append('path/to/file', 'appended file content'); + + +## File Uploads + +#### Moving a $_FILE to a permanent location: + + Input::upload('picture', 'path/to/pictures/newfile.ext'); + +> **Note:** You can easily validate file uploads using the [Validator class](/docs/validation). + + +## File Extensions + +#### Getting the extension from a filename: + + File::extension('picture.png'); + + +## Checking File Types + +#### Determining if a file is given type: + + 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. + +> **Note:** You may pass any of the extensions defined in the **application/config/mimes.php** file to the **is** method. +> **Note:** The Fileinfo PHP extension is required for this functionality. More information can be found on the [PHP Fileinfo page](http://php.net/manual/en/book.fileinfo.php). + + +## Getting MIME Types + +#### Getting the MIME type associated with an extension: + + echo File::mime('gif'); + +> **Note:** This method simply returns the MIME type defined for the extension in the **application/config/mimes.php** file. + + +## Copying Directories + +#### Recursively copy a directory to a given location: + + File::cpdir($directory, $destination); + + +## Removing Directories + +#### Recursively delete a directory: + + File::rmdir($directory); \ No newline at end of file diff --git a/home.md b/home.md new file mode 100644 index 0000000..5545a49 --- /dev/null +++ b/home.md @@ -0,0 +1,59 @@ +# Laravel Documentation + +- [The Basics](#the-basics) +- [Who Will Enjoy Laravel?](#who-will-enjoy-laravel) +- [What Makes Laravel Different?](#laravel-is-different) +- [Application Structure](#application-structure) +- [Laravel's Community](#laravel-community) +- [License Information](#laravel-license) + + +## The Basics + +Welcome to the Laravel documentation. These documents were designed to function both as a getting-started guide and as a feature reference. Even though you may jump into any section and start learning, we recommend reading the documentation in order as it allows us to progressively establish concepts that will be used in later documents. + + +## Who Will Enjoy Laravel? + +Laravel is a powerful framework that emphasizes flexibility and expressiveness. Users new to Laravel will enjoy the same ease of development that is found in the most popular and lightweight PHP frameworks. More experienced users will appreciate the opportunity to modularize their code in ways that are not possible with other frameworks. Laravel's flexibility will allow your organization to update and mold the application over time as is needed and its expressiveness will allow you and your team to develop code that is both concise and easily read. + + + +## What Makes Laravel Different? + +There are many ways in which Laravel differentiates itself from other frameworks. Here are a few examples that we think make good bullet points: + +- **Bundles** are Laravel's modular packaging system. [The Laravel Bundle Repository](http://bundles.laravel.com/) is already populated with quite a few features that can be easily added to your application. You can either download a bundle repository to your bundles directory or use the "Artisan" command-line tool to automatically install them. +- **The Eloquent ORM** is the most advanced PHP ActiveRecord implementation available. With the capacity to easily apply constraints to both relationships and nested eager-loading you'll have complete control over your data with all of the conveniences of ActiveRecord. Eloquent natively supports all of the methods from Laravel's Fluent query-builder. +- **Application Logic** can be implemented within your application either using controllers (which many web-developers are already familiar with) or directly into route declarations using syntax similar to the Sinatra framework. Laravel is designed with the philosophy of giving a developer the flexibility that they need to create everything from very small sites to massive enterprise applications. +- **Reverse Routing** allows you to create links to named routes. When creating links just use the route's name and Laravel will automatically insert the correct URI. This allows you to change your routes at a later time and Laravel will update all of the relevant links site-wide. +- **Restful Controllers** are an optional way to separate your GET and POST request logic. In a login example your controller's get_login() action would serve up the form and your controller's post_login() action would accept the posted form, validate, and either redirect to the login form with an error message or redirect your user to their dashboard. +- **Class Auto Loading** keeps you from having to maintain an autoloader configuration and from loading unnecessary components when they won't be used. Want to use a library or model? Don't bother loading it, just use it. Laravel will handle the rest. +- **View Composers** are blocks of code that can be run when a view is loaded. A good example of this would be a blog side-navigation view that contains a list of random blog posts. Your composer would contain the logic to load the blog posts so that all you have to do i load the view and it's all ready for you. This keeps you from having to make sure that your controllers load the a bunch of data from your models for views that are unrelated to that method's page content. +- **The IoC container** (Inversion of Control) gives you a method for generating new objects and optionally instantiating and referencing singletons. IoC means that you'll rarely ever need to bootstrap any external libraries. It also means that you can access these objects from anywhere in your code without needing to deal with an inflexible monolithic structure. +- **Migrations** are version control for your database schemas and they are directly integrated into Laravel. You can both generate and run migrations using the "Artisan" command-line utility. Once another member makes schema changes you can update your local copy from the repository and run migrations. Now you're up to date, too! +- **Unit-Testing** is an important part of Laravel. Laravel itself sports hundreds of tests to help ensure that new changes don't unexpectedly break anything. This is one of the reasons why Laravel is widely considered to have some of the most stable releases in the industry. Laravel also makes it easy for you to write unit-tests for your own code. You can then run tests with the "Artisan" command-line utility. +- **Automatic Pagination** prevents your application logic from being cluttered up with a bunch of pagination configuration. Instead of pulling in the current page, getting a count of db records, and selected your data using a limit/offset just call 'paginate' and tell Laravel where to output the paging links in your view. Laravel automatically does the rest. Laravel's pagination system was designed to be easy to implement and easy to change. It's also important to note that just because Laravel can handle these things automatically doesn't mean that you can't call and configure these systems manually if you prefer. + +These are just a few ways in which Laravel differentiates itself from other PHP frameworks. All of these features and many more are discussed thoroughly in this documentation. + + +## Application Structure + +Laravel's directory structure is designed to be familiar to users of other popular PHP frameworks. Web applications of any shape or size can easily be created using this structure similarly to the way that they would be created in other frameworks. + +However due to Laravel's unique architecture, it is possible for developers to create their own infrastructure that is specifically designed for their application. This may be most beneficial to large projects such as content-management-systems. This kind of architectural flexibility is unique to Laravel. + +Throughout the documentation we'll specify the default locations for declarations where appropriate. + + +## Laravel's Community + +Laravel is lucky to be supported by rapidly growing, friendly and enthusiastic community. The [Laravel Forums](http://forums.laravel.com) are a great place to find help, make a suggestion, or just see what other people are saying. + +Many of us hang out every day in the #laravel IRC channel on FreeNode. [Here's a forum post explaining how you can join us.](http://forums.laravel.com/viewtopic.php?id=671) Hanging out in the IRC channel is a really great way to learn more about web-development using Laravel. You're welcome to ask questions, answer other people's questions, or just hang out and learn from other people's questions being answered. We love Laravel and would love to talk to you about it, so don't be a stranger! + + +## License Information + +Laravel is open-sourced software licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php). \ No newline at end of file diff --git a/input.md b/input.md new file mode 100644 index 0000000..fb35e0e --- /dev/null +++ b/input.md @@ -0,0 +1,124 @@ +# Input & Cookies + +## Contents + +- [Input](#input) +- [Files](#files) +- [Old Input](#old-input) +- [Redirecting With Old Input](#redirecting-with-old-input) +- [Cookies](#cookies) + + +## Input + +The **Input** class handles input that comes into your application via GET, POST, PUT, or DELETE requests. Here are some examples of how to access input data using the Input class: + +#### Retrieve a value from the input array: + + $email = Input::get('email'); + +> **Note:** The "get" method is used for all request types (GET, POST, PUT, and DELETE), not just GET requests. + +#### Retrieve all input from the input array: + + $input = Input::get(); + +#### Retrieve all input including the $_FILES array: + + $input = Input::all(); + +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: + +#### Returning a default value if the requested input item doesn't exist: + + $name = Input::get('name', 'Fred'); + +#### Using a Closure to return a default value: + + $name = Input::get('name', function() {return 'Fred';}); + +#### Determining if the input contains a given item: + + if (Input::has('name')) ... + +> **Note:** The "has" method will return *false* if the input item is an empty string. + + +## Files + +#### Retrieving all items from the $_FILES array: + + $files = Input::file(); + +#### Retrieving an item from the $_FILES array: + + $picture = Input::file('picture'); + +#### Retrieving a specific item from a $_FILES array: + + $size = Input::file('picture.size'); + + +## Old Input + +You'll commonly need to re-populate forms after invalid form submissions. Laravel's Input class was designed with this problem in mind. Here's an example of how you can easily retrieve the input from the previous request. First, you need to flash the input data to the session: + +#### Flashing input to the session: + + Input::flash(); + +#### Flashing selected input to the session: + + Input::flash('only', array('username', 'email')); + + Input::flash('except', array('password', 'credit_card')); + +#### Retrieving a flashed input item from the previous request: + + $name = Input::old('name'); + +> **Note:** You must specify a session driver before using the "old" method. + +*Further Reading:* + +- *[Sessions](/docs/session/config)* + + +## Redirecting With Old Input + +Now that you know how to flash input to the session. Here's a shortcut that you can use when redirecting that prevents you from having to micro-manage your old input in that way: + +#### Flashing input from a Redirect instance: + + return Redirect::to('login')->with_input(); + +#### Flashing selected input from a Redirect instance: + + return Redirect::to('login')->with_input('only', array('username')); + + return Redirect::to('login')->with_input('except', array('password')); + + +## Cookies + +Laravel provides a nice wrapper around the $_COOKIE array. However, there are a few things you should be aware of before using it. First, all Laravel cookies contain a "signature hash". This allows the framework to verify that the cookie has not been modified on the client. Secondly, when setting cookies, the cookies are not immediately sent to the browser, but are pooled until the end of the request and then sent together. This means that you will not be able to both set a cookie and retrieve the value that you set in the same request. + +#### Retrieving a cookie value: + + $name = Cookie::get('name'); + +#### Returning a default value if the requested cookie doesn't exist: + + $name = Cookie::get('name', 'Fred'); + +#### Setting a cookie that lasts for 60 minutes: + + Cookie::put('name', 'Fred', 60); + +#### Creating a "permanent" cookie that lasts five years: + + Cookie::forever('name', 'Fred'); + +#### Deleting a cookie: + + Cookie::forget('name'); \ No newline at end of file diff --git a/install.md b/install.md new file mode 100644 index 0000000..3f462e8 --- /dev/null +++ b/install.md @@ -0,0 +1,101 @@ +# Installation & Setup + +## Contents + +- [Requirements](#requirements) +- [Installation](#installation) +- [Basic Configuration](#basic-configuration) +- [Environments](#environments) +- [Cleaner URLs](#cleaner-urls) + + +## Requirements + +- Apache, nginx, or another compatible web server. +- Laravel takes advantage of the powerful features that have become available in PHP 5.3. Consequently, PHP 5.3 is a requirement. +- Laravel uses the [FileInfo library](http://php.net/manual/en/book.fileinfo.php) to detect files' mime-types. This is included by default with PHP 5.3. However, Windows users may need to add a line to their php.ini file before the Fileinfo module is enabled. For more information check out the [installation / configuration details on PHP.net](http://php.net/manual/en/fileinfo.installation.php). +- Laravel uses the [Mcrypt library](http://php.net/manual/en/book.mcrypt.php) for encryption and hash generation. Mcrypt typically comes pre-installed. If you can't find Mcrypt in the output of phpinfo() then check the vendor site of your LAMP installation or check out the [installation / configuration details on PHP.net](http://php.net/manual/en/book.mcrypt.php). + + +## Installation + +1. [Download Laravel](http://laravel.com/download) +2. Extract the Laravel archive and upload the contents to your web server. +3. Set the value of the **key** option in the **config/application.php** file to a random, 32 character string. +4. 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! + +### Extra Goodies + +Installing the following goodies will help you take full advantage of Laravel, but they are not required: + +- SQLite, MySQL, PostgreSQL, or SQL Server PDO drivers. +- Memcached or APC. + +### Problems? + +If you are having problems installing, try the following: + +- 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. + + +## Basic Configuration + +All of the configuration provided are located in your applications config/ directory. We recommend that you read through these files just to get a basic understanding of the options available to you. Pay special attention to the **application/config/application.php** file as it contains the basic configuration options for your application. + +It's **extremely** important that you change the **application key** option before working on your site. This key is used throughout the framework for encryption, hashing, etc. It lives in the **config/application.php** file and should be set to a random, 32 character string. A standards-compliant application key can be automatically generated using the Artisan command-line utility. More information can be found in the [Artisan command index](/docs/artisan/commands). + +> **Note:** If you are using mod_rewrite, you should set the index option to an empty string. + + +## Environments + +Most likely, the configuration options you need for local development are not the same as the options you need on your production server. Laravel's default environment handling mechanism is the **LARAVEL_ENV** environment variable. To get started, set the environment variable in your **httpd.conf** file: + + SetEnv LARAVEL_ENV local + +> **Note:** Using a web server other than Apache? Check your server's documentation to learn how to set environment variables. + +Next, create an **application/config/local** directory. Any files and options you place in this directory will override the options in the base **application/config** directory. For example, you may wish to create an **application.php** file within your new **local** configuration directory: + + return array( + + 'url' => 'http://localhost/laravel/public', + + ); + +In this example, the local **URL** option will override the **URL** option in **application/config/application.php**. Notice that you only need to specify the options you wish to override. + +If you do not have access to your server's configuration files, you may manually set the **LARAVEL_ENV** variable at the top of Laravel's **paths.php** file: + + $_SERVER['LARAVEL_ENV'] = 'local'; + + +## 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: + + + RewriteEngine on + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + + RewriteRule ^(.*)$ index.php/$1 [L] + + +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. \ No newline at end of file diff --git a/ioc.md b/ioc.md new file mode 100644 index 0000000..bd39317 --- /dev/null +++ b/ioc.md @@ -0,0 +1,49 @@ +# IoC Container + +- [Definition](/docs/ioc#definition) +- [Registering Objects](/docs/ioc#register) +- [Resolving Objects](/docs/ioc#resolve) + + +## Definition + +An IoC container is simply a way of managing the creation of objects. You can use it to define the creation of complex objects, allowing you to resolve them throughout your application using a single line of code. You may also use it to "inject" dependencies into your classes and controllers. + +IoC containers help make your application more flexible and testable. Since you may register alternate implementations of an interface with the container, you may isolate the code you are testing from external dependencies using [stubs and mocks](http://martinfowler.com/articles/mocksArentStubs.html). + + +## Registering Objects + +#### Registering a resolver in the IoC container: + + IoC::register('mailer', function() + { + $transport = Swift_MailTransport::newInstance(); + + return Swift_Mailer::newInstance($transport); + }); + + +Great! Now we have registered a resolver for SwiftMailer in our container. But, what if we don't want the container to create a new mailer instance every time we need one? Maybe we just want the container to return the same instance after the intial instance is created. Just tell the container the object should be a singleton: + +#### Registering a singleton in the container: + + IoC::singleton('mailer', function() + { + // + }); + +You may also register an existing object instance as a singleton in the container. + +#### Registering an existing instance in the container: + + IoC::instance('mailer', $instance); + + +## Resolving Objects + +Now that we have SwiftMailer registered in the container, we can resolve it using the **resolve** method on the **IoC** class: + + $mailer = IoC::resolve('mailer'); + +> **Note:** You may also [register controllers in the container](/docs/controllers#dependency-injection). \ No newline at end of file diff --git a/loading.md b/loading.md new file mode 100644 index 0000000..72919d4 --- /dev/null +++ b/loading.md @@ -0,0 +1,58 @@ +# Class Auto Loading + +## Contents + +- [The Basics](#the-basics) +- [Registering Directories](#directories) +- [Registering Mappings](#mappings) +- [Registering Namespaces](#namespaces) + + +## The Basics + +Auto-loading allows you to lazily load class files when they are needed without explicitly *requiring* or *including* them. So, only the classes you actually need are loaded for any given request to your application, and you can just jump right in and start using any class without loading it's related file. + +By default, the **models** and **libraries** directories are registered with the auto-loader in the **application/start.php** file. The loader uses a class to file name loading convention, where all file names are lower-cased. So for instance, a "User" class within the models directory should have a file name of "user.php". You may also nest classes within sub-directories. Just namespace the classes to match the directory structure. So, a "Entities\User" class would have a file name of "entities/user.php" within the models directory. + + +## Registering Directories + +As noted above, the models and libraries directories are registered with the auto-loader by default; however, you may register any directories you like to use the same class to file name loading conventions: + +#### Registering directories with the auto-loader: + + Autoloader::directories(array( + path('app').'entities', + path('app').'repositories', + )); + + +## Registering Mappings + +Sometimes you may wish to manually map a class to its related file. This is the most performant way of loading classes: + +#### Registering a class to file mapping with the auto-loader: + + Autoloader::map(array( + 'User' => path('app').'models/user.php', + 'Contact' => path('app').'models/contact.php', + )); + + +## Registering Namespaces + +Many third-party libraries use the PSR-0 standard for their structure. PSR-0 states that class names should match their file names, and directory structure is indicated by namespaces. If you are using a PSR-0 library, just register it's root namespace and directory with the auto-loader: + +#### Registering a namespace with the auto-loader: + + Autoloader::namespaces(array( + 'Doctrine' => path('libraries').'Doctrine', + )); + +Before namespaces were available in PHP, many projects used underscores to indicate directory structure. If you are using one of these legacy libraries, you can still easily register it with the auto-loader. For example, if you are using SwiftMailer, you may have noticed all classes begin with "Swift_". So, we'll register "Swift" with the auto-loader as the root of an underscored project. + +#### Registering an "underscored" library with the auto-loader: + + Autoloader::underscored(array( + 'Swift' => path('libraries').'SwiftMailer', + )); \ No newline at end of file diff --git a/other/lang.md b/localization.md similarity index 60% rename from other/lang.md rename to localization.md index 388af0e..e194163 100644 --- a/other/lang.md +++ b/localization.md @@ -1,17 +1,21 @@ -## Localization +# Localization -- [The Basics](#basics) +## Contents + +- [The Basics](#the-basics) - [Retrieving A Language Line](#get) - [Place Holders & Replacements](#replace) - -### The Basics + +## 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. +All of the language files for your application live under the **application/language** directory. Within the **application/language** 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 **language** 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: +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/language/en** directory, you could create a **marketing.php** file that looks like this: + +#### Creating a language file: return array( @@ -19,7 +23,7 @@ Each language directory may contain many different language files. Each language ); -Next, you should create a corresponding **marketing.php** file within the **application/lang/sp** directory. The file would look something like this: +Next, you should create a corresponding **marketing.php** file within the **application/language/sp** directory. The file would look something like this: return array( @@ -30,33 +34,37 @@ Next, you should create a corresponding **marketing.php** file within the **appl Nice! Now you know how to get started setting up your language files and directories. Let's keep localizing! -### Retrieving A Language Line +## 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: +#### Retrieving a language line: 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. +#### Retrieving a language line using the "__" helper: -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: + echo __('marketing.welcome'); - 'language' => 'en' +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. Need to retrieve the line in a language other than your default? Not a problem. Just mention the language to the **get** method: +#### Getting a language line in a given language: + echo Lang::line('marketing.welcome')->get('sp'); -### Place Holders & Replacements +## 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: +#### Creating a language line with place-holders: + 'welcome' => 'Welcome to our website, :name!' -Then, simply pass an array of place-holder replacements as the second parameter to the **line** method: +#### Retrieving a language line with replacements: echo Lang::line('marketing.welcome', array('name' => 'Taylor'))->get(); -This statement will return a nice, heart-warming welcome message: +#### Retrieving a language line with replacements using "__": - Welcome to our website, Taylor! \ No newline at end of file + echo __('marketing.welcome', array('name' => 'Taylor')); \ No newline at end of file diff --git a/logging.md b/logging.md new file mode 100644 index 0000000..cc8de73 --- /dev/null +++ b/logging.md @@ -0,0 +1,40 @@ +# Errors & Logging + +## Contents + +- [Basic Configuration](#basic-configuration) +- [Logging](#logging) +- [The Logger Class](#the-logger-class) + + +## Basic Configuration + +All of the configuration options regarding errors and logging live in the **application/config/error.php** file. Let's jump right in. + +### Ignored Errors + +The **ignore** option contains an array of [PHP error levels](http://php.net/manual/en/errorfunc.constants.php) that should be ignored by Laravel. By "ignored", we mean that we won't stop execution of the script on these errors. However, they will be logged when logging is enabled. + +### Error Detail + +The **detail** option indicates if the framework should display the error message and stack trace when an error occurs. For development, you will want this to be **true**. However, in a production environment, set this to **false**. When disabled, the view located in **application/views/error/500.php** will be displayed, which contains a generic error message. + + +## Logging + +To enable logging, set the **log** option in the error configuration to "true". When enabled, the Closure defined by the **logger** configuration item will be executed when an error occurs. This gives you total flexibility in how the error should be logged. You can even e-mail the errors to your development team! + +By default, logs are stored in the **storage/logs** direcetory, and a new log file is created for each day. This keeps your log files from getting crowded with too many messages. + + +## The Logger Class + +Sometimes you may wish to use Laravel's **Log** class for debugging, or just to log informational messages. Here's how to use it: + +#### Writing a message to the logs: + + Log::write('info', 'This is just an informational message!'); + +#### Using magic methods to specify the log message type: + + Log::info('This is just an informational message!'); \ No newline at end of file diff --git a/models.md b/models.md new file mode 100644 index 0000000..962efa1 --- /dev/null +++ b/models.md @@ -0,0 +1,116 @@ +# Models & Libraries + +## Contents + +- [Models](#models) +- [Libraries](#libraries) +- [Auto-Loading](#auto-loading) +- [Best Practices](#best-practices) + + +## Models + +Models are the heart of your application. Your application logic (controllers / routes) and views (html) are just the mediums with which users interact with your models. The most typical type of logic contained within a model is [Business Logic](http://en.wikipedia.org/wiki/Business_logic). + +*Some examples of functionality that would exist within a model are:* + +- Database Interactions +- File I/O +- Interactions with Web Services + +For instance, perhaps you are writing a blog. You will likely want to have a "Post" model. Users may want to comment on posts so you'd also have a "Comment" model. If users are going to be commenting then we'll also need a "User" model. Get the idea? + + +## Libraries + +Libraries are classes that perform tasks that aren't specific to your application. For instance, consider a PDF generation library that converts HTML. That task, although complicated, is not specific to your application, so it is considered a "library". + +Creating a library is as easy as creating a class and storing it in the libraries folder. In the following example, we will create a simple library with a method that echos the text that is passed to it. We create the **printer.php** file in the libraries folder with the following code. + + +## Auto Loading + +Libraries and Models are very easy to use thanks to the Laravel auto-loader. To learn more about the auto-loader check out the documentation on [Auto-Loading](/docs/loading). + + +## Best Practices + +We've all head the mantra: "controllers should be thin!" But, how do we apply that in real life? It's possible that part of the problem is the word "model". What does it even mean? Is it even a useful term? Many associate "model" with "database", which leads to having very bloated controllers, with light models that access the database. Let's explore some alternatives. + +What if we just totally scrapped the "models" directory? Let's name it something more useful. In fact, let's just give it the same as our application. Perhaps our satellite tracking site is named "Trackler", so let's create a "trackler" directory within the application folder. + +Great! Next, let's break our classes into "entities", "services", and "repositories". So, we'll create each of those three directories within our "trackler" folder. Let's explore each one: + +### Entities + +Think of entities as the data containers of your application. They primarily just contain properties. So, in our application, we may have a "Location" entity which has "latitude" and "longitude" properties. It could look something like this: + + latitude = $latitude; + $this->longitude = $longitude; + } + + } + +Looking good. Now that we have an entity, let's explore our other two folders. + +### Services + +Services contain the *processes* of your application. So, let's keep using our Trackler example. Our application might have a form on which a user may enter their GPS location. However, we need to validate that the coordinates are correctly formatted. We need to *validate* the *location entity*. So, within our "services" directory, we could create a "validators" folder with the following class: + + -### 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. - - -### 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'); - - -### 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 diff --git a/other/crypt.md b/other/crypt.md deleted file mode 100644 index 45a52c9..0000000 --- a/other/crypt.md +++ /dev/null @@ -1,36 +0,0 @@ -## Encryption - -- [The Basics](#basics) -- [Encrypting A String](#encrypt) -- [Decrypting A String](#decrypt) - - -### The Basics - -Need to do secure, two-way encryption? Laravel has you covered with the **Crypter** class. By default, the Crypter 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. - - -### Encrypting A String - -Encrypting a string is a breeze. Just pass it to the **encrypt** method on a Crypter instance: - - Crypter::make()->encrypt($value); - -Do you feel like James Bond yet? - - -### Decrypting A String - -So you're ready to decrypt a string? It's simple. Just use the **decrypt** method on a Crypter instance: - - Crypter::make()->decrypt($encrypted_value); - -> **Note:** The decrypt method will only decrypt strings that were encrypted using **your** application key. \ No newline at end of file diff --git a/other/file.md b/other/file.md deleted file mode 100644 index ee0e0ee..0000000 --- a/other/file.md +++ /dev/null @@ -1,69 +0,0 @@ -## Working With Files - -- [Reading Files](#get) -- [Writing Files](#put) -- [File Uploads](#upload) -- [File Extensions](#ext) -- [Checking File Types](#is) -- [Getting MIME Types](#mime) - - -### 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'); - - -### 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'); - - -### 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). - - -### File Extensions - -Need to get the extension of a file? Just pass the filename to the **extension** method: - - File::extension('picture.png'); - - -### 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. - - -### 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 diff --git a/other/text.md b/other/text.md deleted file mode 100644 index 7cafafc..0000000 --- a/other/text.md +++ /dev/null @@ -1,44 +0,0 @@ -## Working With Strings - -- [The Basics](#basics) -- [Capitalization, Etc.](#capitalization) -- [Generating Random Strings](#random) -- [Singular & Plural](#inflector) - - -### The Basics - -Laravel provides two great classes for working with text and strings: **Str** and **Inflector**. Let's learn what each of them will do for us. - - -### Capitalization, Etc. - -The **Str** class also provides three convenient methods for manipulating string capitalization: **upper**, **lower**, and **title**. These are more intelligent versions of the PHP [strtoupper](http://php.net/manual/en/function.strtoupper.php), [strtolower](http://php.net/manual/en/function.strtolower.php), and [ucwords](http://php.net/manual/en/function.ucwords.php) methods. More intelligent because they can handle UTF-8 input if the [multi-byte string](http://php.net/manual/en/book.mbstring.php) PHP extension is installed on your web server. To use them, just pass a string to the method: - - echo Str::lower('I am a string.'); - - echo Str::upper('I am a string.'); - - echo Str::title('I am a string.'); - - -### Generating Random Strings - -Need a random string? Just tell the **random** method on the **Str** class how many characters you need and the method will return a random, alpha-numeric string: - - echo Str::random(32); - - -### Singular & Plural - -The **Inflector** class provides simple methods for retrieving the singular and plural forms of words. It's no dummy, either. For example, "child" becomes "children" and "tooth" becomes "teeth". To get the plural form of a word, just mention the word to the **plural** method: - - echo Inflector::plural('friend'); - -To get the singular form of a word, use the **singular** method: - - echo Inflector::singular('friends'); - -But, what if you are doing something like displaying the total number of comments on a blog post? You only want the plural form of "comment" if there is more than one. **Laravel** has you covered with the **plural_if** method. If the count passed to the method is greater than one, the plural form of the word will be returned. Otherwise, the word will be returned unchanged. - - echo Inflector::plural_if('comment', $count); \ No newline at end of file diff --git a/requests.md b/requests.md new file mode 100644 index 0000000..8498b3e --- /dev/null +++ b/requests.md @@ -0,0 +1,77 @@ +# Examining Requests + +## Contents + +- [Working With The URI](#working-with-the-uri) +- [Other Request Helpers](#other-request-helpers) + + +## Working With The URI + +#### Getting the current URI for the request: + + echo URI::current(); + +#### Getting a specific segment from the URI: + + echo URI::segment(1); + +#### Returning a default value if the segment doesn't exist: + + echo URI::segment(10, 'Foo'); + +#### Getting the full request URI, including query string: + + echo URI::full(); + +Sometimes you may need to determine if the current URI is a given string, or begins with a given string. Here's an example of how you can use the is() method to accomplish this: + +#### Determine if the URI is "home": + + if (URI::is('home')) + { + // The current URI is "home"! + } + +#### Determine if the current URI begins with "docs/": + + if URI::is('docs/*')) + { + // The current URI begins with "docs/"! + } + + +## Other Request Helpers + +#### Getting the current request method: + + echo Request::method(); + +#### Accessing the $_SERVER global array: + + echo Request::server('http_referer'); + +#### Retrieving the requester's IP address: + + echo Request::ip(); + +#### Determining if the current request is using HTTPS: + + if (Request::secure()) + { + // This request is over HTTPS! + } + +#### Determing if the current request is an AJAX request: + + if (Request::ajax()) + { + // This request is using AJAX! + } + +#### Determining if the current requst is via the Artisan CLI: + + if (Request::cli()) + { + // This request came from the CLI! + } \ No newline at end of file diff --git a/routing.md b/routing.md new file mode 100644 index 0000000..93d900e --- /dev/null +++ b/routing.md @@ -0,0 +1,317 @@ +# Routing + +## Contents + +- [The Basics](#the-basics) +- [Wildcards](#wildcards) +- [The 404 Event](#the-404-event) +- [Filters](#filters) +- [Pattern Filters](#pattern-filters) +- [Global Filters](#global-filters) +- [Route Groups](#route-groups) +- [Named Routes](#named-routes) +- [HTTPS Routes](#https-routes) +- [Bundle Routes](#bundle-routes) +- [Controller Routing](#controller-routing) +- [CLI Route Testing](#cli-route-testing) + + +## The Basics + +Laravel uses the latest features of PHP 5.3 to make routing simple and expressive. It's important that building everything from APIs to complex web applications is as easy as possible. Routes are typically defined in **application/routes.php**. + +Unlike many other frameworks with Laravel it's possible to embed application logic in two ways. While controllers are the most common way to implement application logic it's also possible to embed your logic directly into routes. This is **especially** nice for small sites that contain only a few pages as you don't have to create a bunch of controllers just to expose half a dozen methods or put a handful of unrelated methods into the same controller and then have to manually designate routes that point to them. + +In the following example the first parameter is the route that you're "registering" with the router. The second parameter is the function containing the logic for that route. Routes are defined without a front-slash. The only exception to this is the default route which is represented with **only** a front-slash. + +> **Note:** Routes are evaluated in the order that they are registered, so register any "catch-all" routes at the bottom of your **routes.php** file. + +#### Registering a route that responds to "GET /": + + Route::get('/', function() + { + return "Hello World!"; + }); + +#### Registering a route that is valid for any HTTP verb (GET, POST, PUT, and DELETE): + + Route::any('/', function() + { + return "Hello World!"; + }); + +#### Registering routes for other request methods: + + Route::post('user', function() + { + // + }); + + Route::put('user/(:num)', function($id) + { + // + }); + + Route::delete('user/(:num)', function($id) + { + // + }); + +**Registering a single URI for multiple HTTP verbs:** + + Router::register(array('GET', 'POST'), $uri, $callback); + + +## Wildcards + +#### Forcing a URI segment to be any digit: + + Route::get('user/(:num)', function($id) + { + // + }); + +#### Allowing a URI segment to be any alpha-numeric string: + + Route::get('post/(:any)', function($title) + { + // + }); + +#### Allowing a URI segment to be optional: + + Route::get('page/(:any?)', function($page = 'index') + { + // + }); + + +## The 404 Event + +If a request enters your application but does not match any existing route, the 404 event will be raised. You can find the default event handler in your **application/routes.php** file. + +#### The default 404 event handler: + + Event::listen('404', function() + { + return Response::error('404'); + }); + +You are free to change this to fit the needs of your application! + +*Futher Reading:* + +- *[Events](/docs/events)* + + +## Filters + +Route filters may be run before or after a route is executed. If a "before" filter returns a value, that value is considered the response to the request and the route is not executed, which is convenient when implementing authentication filters, etc. Filters are typically defined in **application/routes.php**. + +#### Registering a filter: + + Route::filter('filter', function() + { + return Redirect::to('home'); + }); + +#### Attaching a filter to a route: + + Route::get('blocked', array('before' => 'filter', function() + { + return View::make('blocked'); + })); + +#### Attaching an "after" filter to a route: + + Route::get('download', array('after' => 'log', function() + { + // + })); + +#### Attaching multiple filters to a route: + + Route::get('create', array('before' => 'auth|csrf', function() + { + // + })); + +#### Passing parameters to filters: + + Route::get('panel', array('before' => 'role:admin', function() + { + // + })); + + +## Pattern Filters + +Sometimes you may want to attach a filter to all requests that begin with a given URI. For example, you may want to attach the "auth" filter to all requests with URIs that begin with "admin". Here's how to do it: + +#### Defining a URI pattern based filter: + + Route::filter('pattern: admin/*', 'auth'); + + +## Global Filters + +Laravel has two "global" filters that run **before** and **after** every request to your application. You can find them both in the **application/routes.php** file. These filters make great places to start common bundles or add global assets. + +> **Note:** The **after** filter receives the **Response** object for the current request. + + +## Route Groups + +Route groups allow you to attach a set of attributes to a group of routes, allowing you to keep your code neat and tidy. + + Route::group(array('before' => 'auth'), function() + { + Route::get('panel', function() + { + // + }); + + Route::get('dashboard', function() + { + // + }); + }); + + +## Named Routes + +Constantly generating URLs or redirects using a route's URI can cause problems when routes are later changed. Assigning the route a name gives you a convenient way to refer to the route throughout your application. When a route change occurs the generated links will point to the new route with no further configuration needed. + +#### Registering a named route: + + Route::get('/', array('as' => 'home', function() + { + return "Hello World"; + })); + +#### Generating a URL to a named route: + + $url = URL::to_route('home'); + +#### Redirecting to the named route: + + return Redirect::to_route('home'); + +Once you have named a route, you may easily check if the route handling the current request has a given name. + +#### Determine if the route handling the request has a given name: + + if (Request::route()->is('home')) + { + // The "home" route is handling the request! + } + + +## HTTPS Routes + +When defining routes, you may use the "https" attribute to indicate that the HTTPS protocol should be used when generating a URL or Redirect to that route. + +#### Defining an HTTPS route: + + Route::get('login', array('https' => true, function() + { + return View::make('login'); + })); + +#### Using the "secure" short-cut method: + + Route::secure('GET', 'login', function() + { + return View::make('login'); + }); + + +## Bundle Routes + +Bundles are Laravel's modular package system. Bundles can easily be configured to handle requests to your application. We'll be going over [bundles in more detail](/docs/bundles) in another document. For now, read through this section and just be aware that not only can routes be used to expose functionality in bundles, but they can also be registered from within bundles. + +Let's open the **application/bundles.php** file and add something: + +#### Registering a bundle to handle routes: + + return array( + + 'admin' => array('handles' => 'admin'), + + ); + +Notice the new **handles** option in our bundle configuration array? This tells Laravel to load the Admin bundle on any requests where the URI begins with "admin". + +Now you're ready to register some routes for your bundle, so create a **routes.php** file within the root directory of your bundle and add the following: + +#### Registering a root route for a bundle: + + Route::get('(:bundle)', function() + { + return 'Welcome to the Admin bundle!'; + }); + +Let's explore this example. Notice the **(:bundle)** place-holder? That will be replaced with the value of the **handles** clause that you used to register your bundle. This keeps your code [D.R.Y.](http://en.wikipedia.org/wiki/Don't_repeat_yourself) and allows those who use your bundle to change it's root URI without breaking your routes! Nice, right? + +Of course, you can use the **(:bundle)** place-holder for all of your routes, not just your root route. + +#### Registering bundle routes: + + Route::get('(:bundle)/panel', function() + { + return "I handle requests to admin/panel!"; + }); + + +## Controller Routing + +Controllers provide another way to manage your application logic. If you're unfamiliar with controllers you may want to [read about controllers](/docs/controllers) and return to this section. + +It is important to be aware that all routes in Laravel must be explicitly defined, including routes to controllers. This means that controller methods that have not been exposed through route registration **cannot** be accessed. It's possible to automatically expose all methods within a controller using controller route registration. Controller route registrations are typically defined in **application/routes.php**. + +Most likely, you just want to register all of the controllers in your application's "controllers" directory. You can do it in one simple statement. Here's how: + +#### Register all controllers for the application: + + Route::controller(Controller::detect()); + +The **Controller::detect** method simply returns an array of all of the controllers defined for the application. + +If you wish to automatically detect the controllers in a bundle, just pass the bundle name to the method. If no bundle is specified, the application folder's controller directory will be searched. + +#### Register all controllers for the "admin" bundle: + + Route::controller(Controller::detect('admin')); + +#### Registering the "home" controller with the Router: + + Route::controller('home'); + +#### Registering several controllers with the router: + + Route::controller(array('dashboard.panel', 'admin')); + +Once a controller is registered, you may access its methods using a simple URI convention: + + http://localhost/controller/method/arguments + +This convention is similar to that employed by CodeIgniter and other popular frameworks, where the first segment is the controller name, the second is the method, and the remaining segments are passed to the method as arguments. If no method segment is present, the "index" method will be used. + +This routing convention may not be desirable for every situation, so you may also explicitly route URIs to controller actions using a simple, intuitive syntax. + +#### Registering a route that points to a controller action: + + Route::get('welcome', 'home@index'); + +#### Registering a filtered route that points to a controller action: + + Route::get('welcome', array('after' => 'log', 'uses' => 'home@index')); + + +## CLI Route Testing + +You may test your routes using Laravel's "Artisan" CLI. Simple specify the request method and URI you want to use. The route response will be var_dump'd back to the CLI. + +#### Calling a route via the Artisan CLI: + + php artisan route:call get api/user/1 \ No newline at end of file diff --git a/session/config.md b/session/config.md index 1904d40..094148c 100644 --- a/session/config.md +++ b/session/config.md @@ -1,70 +1,109 @@ - -## 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 - - -### 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. - - -### 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' - - -### 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 Configuration + +## Contents + +- [The Basics](#the-basics) +- [Cookie Sessions](#cookie) +- [File System Sessions](#file) +- [Database Sessions](#database) +- [Memcached Sessions](#memcached) +- [Redis Sessions](#redis) +- [In-Memory Sessions](#memory) + + +## The Basics + +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. + +> **Note:** Before using sessions, make sure an application key has been specified in the **application/config/application.php** file. + +Six session drivers are available out of the box: + +- Cookie +- File System +- Database +- Memcached +- Redis +- Memory (Arrays) + + +## Cookie Sessions + +Cookie based sessions provide a light-weight and fast mechanism for storing session information. They are also secure. Each cookie is encrypted using strong AES-256 encryption. However, cookies have a four kilobyte storage limit, so you may wish to use another driver if you are storing a lot of data in the session. + +To get started using cookie sessions, just set the driver option in the **application/config/session.php** file: + + 'driver' => 'cookie' + + +## 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 **storage/sessions** directory, so make sure it's writeable. + + +## Database Sessions + +To start using database sessions, you will first need to [configure your database connection](/docs/database/config). + +Next, you will need to create a session table. Below are some SQL statements to help you get started. However, you may also use Laravel's "Artisan" command-line to generate the table for you! + +### Artisan + + php artisan session:table + +### 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' + +All you need to do now is set the driver in the **application/config/session.php** file: + + 'driver' => 'database' + + +## Memcached Sessions + +Before using Memcached sessions, you must [configure your Memcached servers](/docs/database/config#memcached). + +Just set the driver in the **application/config/session.php** file: + + 'driver' => 'memcached' + + +## Redis Sessions + +Before using Redis sessions, you must [configure your Redis servers](/docs/database/redis#config). + +Just set the driver in the **application/config/session.php** file: + + 'driver' => 'redis' + + +## In-Memory Sessions + +The "memory" session driver just uses a simple array to store your session data for the current request. This driver is perfect for unit testing your application since nothing is written to disk. It shouldn't ever be used as a "real" session driver. \ No newline at end of file diff --git a/session/usage.md b/session/usage.md index 5e76a7d..5f9aad5 100644 --- a/session/usage.md +++ b/session/usage.md @@ -1,59 +1,61 @@ -## Session Usage - -- [Storing Items](#put) -- [Retrieving Items](#get) -- [Removing Items](#forget) -- [Regeneration](#regeneration) - - -### 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!'); - - -### 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'); - } - - -### 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(); - - -### 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 Usage + +## Contents + +- [Storing Items](#put) +- [Retrieving Items](#get) +- [Removing Items](#forget) +- [Regeneration](#regeneration) + + +## Storing Items + +To store items in the session 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. + +The **flash** method stores an item in the session that will expire after the next request. It's useful for storing temporary data like status or error messages: + + Session::flash('status', 'Welcome Back!'); + + +## Retrieving Items + +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'); + } + + +## Removing Items + +To remove an item from the session use 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(); + + +## 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 diff --git a/start/config.md b/start/config.md deleted file mode 100644 index aef0144..0000000 --- a/start/config.md +++ /dev/null @@ -1,102 +0,0 @@ -## Basic Configuration - -- [Quick Start](#quick) -- [Environments](#environments) -- [Cleaner URLs](#clean) -- [Errors & Logging](#errors) - - -### 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. - - -### Environments - -Most likely, the configuration options you need for local development are not the same as the options you need on your production server. Laravel provides a convenient way to manage these differences using the **LARAVEL_ENV** environment variable. To get started, set the environment variable in your **httpd.conf** file: - - SetEnv LARAVEL_ENV local - -> **Note:** Using a web server other than Apache? Check your server's documentation to learn how to set environment variables. - -Great! Next, create an **application/config/local** directory. Any files and options you place in this directory will override the options in the base **application/config** directory. For example, you may wish to create an **application.php** file within your new **local** configuration directory: - - return array( - - 'url' => 'http://localhost/laravel/public', - - ); - -In this example, the local **URL** option will override the **URL** option in **application/config/application.php**. Notice that you only need to specify the options you wish to override. Remember, development doesn't have to be a pain. - -If you do not have access to your server's configuration files, you may manually set the **LARAVEL_ENV** variable at the top of your **public/index.php** file: - - $_SERVER['LARAVEL_ENV'] = 'local'; - - -### 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: - - - RewriteEngine on - - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - - RewriteRule ^(.*)$ index.php/$1 [L] - - -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. - - -### Errors & Logging - -- [404 Errors](#error-404) -- [Error Detail](#error-detail) -- [Logging](#error-logging) - - -#### 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. - - -#### 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. - - -#### 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 diff --git a/start/install.md b/start/install.md deleted file mode 100644 index 57cd732..0000000 --- a/start/install.md +++ /dev/null @@ -1,27 +0,0 @@ -## Requirements & Installation - -### Requirements - -- Apache, nginx, or another compatible web server. -- PHP 5.3+. - -### Installation - -1. [Download Laravel](http://laravel.com/download) -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 diff --git a/start/interaction.md b/start/interaction.md deleted file mode 100644 index 1431282..0000000 --- a/start/interaction.md +++ /dev/null @@ -1,232 +0,0 @@ -## 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. - - -## 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(); - - -## 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'); - } - - -## 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'); - - -## 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. - - -### 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'); - - -### 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. - - -### 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. - - -### 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! - - -### 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: - - - -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! - - -### 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')); - - -### 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 diff --git a/start/libraries.md b/start/libraries.md deleted file mode 100644 index c8236fc..0000000 --- a/start/libraries.md +++ /dev/null @@ -1,55 +0,0 @@ -## Models, Libraries, & Packages - -- [Models](#models) -- [Libraries](#libraries) -- [Packages](#packages) - - -## Models - -Models are the meat of your application, and they live in the **application/models** directory. A model is simply a class. Nothing more. It should contain business logic related to your application. Models may also be [Eloquent models](/docs/database/eloquent), which allow you to work with your database elegantly and beautifully. Models are auto-loaded by Laravel, so there is no need to **require** them before using them. - - -## Libraries - -Libraries can be considered the "helper" classes of your application. Usually, they are classes that do not contain logic specific to your application; however, they are important to its functionality. For example, a Twitter library may be used to fetch your recent tweets and display them on a view. Fetching Tweets from Twitter isn't specific to your application, but it is still important. Place your generic, helper libraries in the **application/libraries** directory. Like models, libraries are also auto-loaded by Laravel. - - -## Packages - -- [The Basics](#package-basics) -- [Auto-Loading Packages](#package-auto) -- [Registering Load Paths](#package-register) - - -### The Basics - -Packages and libraries have many things in common. Often, they provide functionality that is not specific to your application. However, packages are generally not written specifically for Laravel. For example, the wonderful e-mailing package [SwiftMailer](http//swiftmailer.org) is not written just for Laravel, but it can be used in a variety of frameworks, including Laravel. All packages live in the **packages** directory. - -Often, it is necessary for packages to be bootstrapped. For example, the package may need to register its own auto-loader. Not a problem. The **package** class provides an easy way to load packages. If a **bootstrap.php** file is present in the package root directory, it will be run. - - Package::load('swift-mailer'); - -Need to load more than one package? Just pass an array to the **load** method: - - Package::load(array('swift-mailer', 'facebook')); - -> **Note:** Package classes are not auto-loaded by Laravel. Each package is responsible for registering its own auto-loader. - - -### Auto-Loading Packages - -Sometimes you may want to load a package for every request to your application. No problem. Just add the package to the **packages** option in the **application/config/application.php** file: - - 'packages' => array('swift-mailer') - -Alternatively, you can use the [**needs** keyword on a route](/docs/start/routes#dependencies). - - -### Registering Load Paths - -Have you written a package and want its classes to be auto-loaded by Laravel? Checkout the **register** method on the **Loader** class. All it needs is a directory: - - Loader::register('path/to/package/root'); - -Once a directory has been registered, the Laravel auto-loader will search the directory for classes in exactly the same way it searches the application **models** and **libraries** directories. \ No newline at end of file diff --git a/start/modules.md b/start/modules.md deleted file mode 100644 index 5ac5d41..0000000 --- a/start/modules.md +++ /dev/null @@ -1,67 +0,0 @@ -## Modules - -- [The Basics](#basics) -- [Setting Up A Module](#setup) -- [Module Views](#views) -- [Module Models & Libraries](#libraries) -- [Module Configuration & Language](#config) - - -### The Basics - -Modules are an amazing way to organize your application. All modules live in the **modules** directory. Picture each module as a sort of sub-application living within your main Laravel application. A module can have its own libraries, models, routes, views, composers, filters, language files, and configuration. Ready to learn how to use them? Let's jump in. - - -### Setting Up A Module - -To setup a module, create a directory in the **modules** directory. For example, you might create an **admin** directory under the **modules** directory. Great! The **admin** module will respond to all requests to your application beginning with **/admin**. Sound familiar? That's because it is similar to [using a route folder](/docs/start/routes#organize). - -So, within your **modules/admin** directory, create a **routes.php** file with the following route: - - 'GET /admin' => function() - { - return 'Hello Admins!'; - } - -Next, in your **application/config/application.php** file, add **admin** to the array of active modules: - - 'modules' => array('admin') - -Now, browse to this URL in your web browser. See "Hello Admins!"? Wonderful. You're learning fast. - -> **Note:** Module route filters work just like application route filters. Just create a **filters.php** file within your module directory. - - -### Module Views - -To create a view that will be used by your module, simply create a **views** directory within your module directory. Once you have created a view, you can get an instance of it like this: - - $view = View::make('module::view.name'); - -Notice the module qualifier followed by two colons? This tells Laravel which module the view belongs to. Of course, if the view is in the **application/views** directory, you do need to specify the module name. So, for example, if this view belongs to your **admin** module, you could create it like so: - - $view = View::make('admin::view.name'); - -> **Note:** Module composers work just like application composers. Just make a **composers.php** file within your module directory. - - -### Module Models & Libraries - -Using models and libraries within modules is very similar to using them within your application. However, module models and libraries must be namespaced using the module name. So, if you have a **User** model within your **admin** model, it should be namespaced like so: - - namespace Admin; - - class User {} - -Once you have created the model, you may use it anywhere within your application: - - $user = new Admin\User; - - -### Module Configuration and Language - -You can create module configuration and language files just like you create their application counterparts. To load them, use double-colon module qualifier, just like you load module views: - - Config::get('module::option.name'); - - Lang::line('module::language.line')->get(); \ No newline at end of file diff --git a/start/routes.md b/start/routes.md deleted file mode 100644 index 7b6f9af..0000000 --- a/start/routes.md +++ /dev/null @@ -1,151 +0,0 @@ -## 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) -- [Route Dependencies](/docs/start/routes#dependencies) -- [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. - - -## 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. - - -## 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) {} - - -## 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', function() {}) - -Notice the route now has an array value with a **name** key. 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? - - -## 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', function() - { - // - }) - -Notice the route now has an array value with a **before** key. 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', 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', function() {}) - -> **Note:** "After" filters receive the response returned by the route function that handled the request. - - -## Route Dependencies - -Often, a route needs to use a package to do its job. For instance, perhaps it needs to use the [SwiftMailer](http://swiftmailer.org) package to send some e-mails. One option is to load the package within your route like this: - - 'GET /' => function() - { - Package::load('swift-mailer'); - } - -However, cluttering up your routes with package loading can get frusterating. Instead, tell Laravel what your route **needs**: - - 'GET /' => array('needs' => 'swift-mailer', function() - { - // - }) - -Now, the **swift-mailer** package will be loaded each time this route is called. Need to load more than one package? No problem: - - 'GET /' => array('needs' => 'swift-mailer, facebook', function() - { - // - }) - - -## 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: - - 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. - -Need even more organization? You are free to create sub-directories in the **application/routes** directory. For example, an **application/routes/user/admin.php** file would handle all requests to URIs beginning with **user/admin**. \ No newline at end of file diff --git a/start/validation.md b/start/validation.md deleted file mode 100644 index 7949cf9..0000000 --- a/start/validation.md +++ /dev/null @@ -1,368 +0,0 @@ -## Validation - -- [The Basics](#basics) -- [Validation Rules](#rules) -- [Retrieving Error Messages](#errors) -- [Specifying Custom Error Messages](#messages) -- [Creating Custom Validation Rules](#custom) - - -### The Basics - -Almost every interactive web application needs to validate data. For instance, a registration form probably requires the password to be confirmed. Maybe the e-mail address must be unique. Validating data can be a cumbersome process. Thankfully, it isn't in Laravel. The **Validator** class provides as awesome array of validation helpers to make validating your data a breeze. - -To get started, let's imagine we have the following array: - - $array = array('name' => 'Taylor', 'email' => 'example@gmail.com'); - -Next, we're ready to define [validation rules](#rules) for our array: - - $rules = array( - 'name' => array('required', 'max:50'), - 'email' => array('required', 'email', 'unique:users'), - ); - -If you don't like using arrays, you may also delimit rules using a pipe character: - - $rules = array( - 'name' => 'required|max:50', - 'email' => 'required|email|unique:users', - ); - -Great! Now we're ready to make a **Validator** instance and validate our array: - - $validator = Validator::make($array, $rules); - - if ( ! $validator->valid()) - { - return $validator->errors; - } - -Via the **errors** property, you can access a simple error collector class that makes working with your error messages a breeze. Of course, default error messages have been setup for all validation rules. The default messages live in the **application/lang/en/validation.php** file. - -Now you are familiar with the basic usage of the Validator class. You're ready to dig in and learn about the rules you can use to validate your data! - - -### Validation Rules - -- [Required](#rule-required) -- [Alpha, Alpha Numeric, & Alpha Dash](#rule-alphas) -- [Size](#rule-size) -- [Numericality](#rule-numeric) -- [Inclusion & Exclusion](#rule-inclusion) -- [Confirmation](#rule-confirmed) -- [Acceptance](#rule-accepted) -- [Uniqueness](#rule-unique) -- [E-Mail Addresses](#rule-email) -- [URLs](#rule-urls) -- [Uploads](#rule-uploads) - - -#### Required - -The **required** rule validates that an attribute is present in the array and is not an empty string: - - $rules = array( - 'name' => 'required', - ); - - -#### Alpha, Alpha Numeric, & Alpha Dash - -The **alpha** rule validates that an attribute consists solely of letters: - - $rules = array( - 'name' => 'alpha', - ); - -The **alpha_num** rule validates that an attribute consists solely of letters and numbers: - - $rules = array( - 'username' => 'alpha_num', - ); - -The **alpha_dash** rule validates that an attribute consists solely of letters, numbers, dashes, and underscores: - - $rules = array( - 'username' => 'alpha_dash', - ); - - -#### Size - -The **size** rule validates that an attribute is of a given length, or, if the attribute is numeric, is a given value: - - $rules = array( - 'name' => 'size:10', - ); - -The **between** rule validates that an attribute is between a given minimum and maximum: - - $rules = array( - 'payment' => 'between:10,50', - ); - -> **Note:** All minimum and maximum checks are inclusive. - -The **min** rule validates that an attribute is greater than or equal to a given value: - - $rules = array( - 'payment' => 'min:10', - ); - -The **max** rule validates that an attribute is less than or equal to a given value: - - $rules = array( - 'payment' => 'max:50', - ); - - -#### Numericality - -The **numeric** rule validates that an attribute is (surprise!) numeric: - - $rules = array( - 'payment' => 'numeric', - ); - -The **integer** rule validates that an attribute is an integer: - - $rules = array( - 'payment' => 'integer', - ); - - -#### Inclusion & Exclusion - -The **in** rule validates that an attribute is contained in a list of values: - - $rules = array( - 'size' => 'in:small,medium,large', - ); - -The **not_in** rule validates that an attribute is not contained in a list of values: - - $rules = array( - 'language' => 'not_in:cobol,assembler', - ); - - -#### Confirmation - -The **confirmed** rule validates that, for a given attribute, a matching **attribute_confirmation** attribute exists. For example, given the following rule: - - $rules = array( - 'password' => 'confirmed', - ); - -The Validator will make sure that the **password** attribute matches the **password_confirmation** attribute in the array being validated. - - -#### Acceptance - -The **accepted** rule validates that an attribute is equal to **yes** or **1**. This rule is helpful for validating checkbox form fields such as "terms of service". - - $rules = array( - 'terms' => 'accepted', - ); - - -#### Uniqueness - -The **unique** rule validates the uniqueness of an attribute on a given database table: - - $rules = array( - 'email' => 'unique:users', - ); - -In the example above, the **email** attribute will be checked for uniqueness on the **users** table. Need to verify uniqueness on a column name other than the attribute name? No problem: - - $rules = array( - 'email' => 'unique:users,email_address', - ); - - -#### E-Mail Addresses - -The **email** rule validates that an attribute contains a correctly formatted e-mail address: - - $rules = array( - 'email' => 'email', - ); - - -#### URLs - -The **url** rule validates that an attribute contains a correctly formatted URL: - - $rules = array( - 'link' => 'url', - ); - -The **active_url** rule uses the PHP **checkdnsrr** function to verify that a URL is active: - - $rules = array( - 'link' => 'active_url', - ); - - -#### Uploads - -The **mimes** rule validates that an uploaded file has a given MIME type. This rule uses the PHP Fileinfo extension to read the contents of the file and determine the actual MIME type. Any extension defined in the **application/config/mimes.php** file may be passed to this rule as a parameter: - - $rules = array( - 'picture' => 'mimes:jpg,gif', - ); - - $validator = Validator::make(Input::file(), $rules); - -Need to validate form data and upload data at the same time? Use the **all** method on the **Input** class to get form and upload data in one array: - - $validator = Validator::make(Input::all(), $rules); - -The **image** rule validates that an uploaded file has a **jpg**, **gif**, **bmp**, or **png** MIME type: - - $rules = array( - 'picture' => 'image', - ); - -You may also validate the size of an upload using the **max** rule. Simply specify the maximum number of **kilobytes** the upload may be: - - $rules = array( - 'picture' => 'image|max:100', - ); - - -### Retrieving Error Messages - -Laravel makes working with your error messages a cinch using a simple error collector class. After calling the **valid** or **invalid** method on a **Validator** instance, you may access the errors via the **errors** property: - - if ( ! $validator->valid()) - { - return $validator->errors; - } - -The error collector has the following simple functions for retrieving your error messages: **has**, **first**, **get**, and **all**. - -The **has** method will check if an error message exists for a given attribute: - - if ($validator->errors->has('email')) - { - // The e-mail attribute has errors... - } - -The **first** method will return the first error message for a given attribute: - - echo $validator->errors->first('email'); - -Sometimes you may need to format the error message by wrapping it in HTML. No problem. Along with the **:message** place-holder, pass the format as the second parameter to the method: - - echo $validator->errors->first('email', '

:message

'); - -The **get** method returns an array containing all of the error messages for a given attribute: - - return $validator->errors->get('email'); - - return $validator->errors->get('email', '

:message

'); - -The **all** method returns an array containing all error messages for all attributes: - - return $validator->errors->all(); - - return $validator->errors->all('

:message

'); - - -### Specifying Custom Error Messages - -Want to use an error message other than the default? Maybe you even want to use a custom error message for a given attribute and rule. Either way, the **Validator** class makes it easy. - -Simply create an array of custom messages to pass to the Validator instance: - - $messages = array( - 'required' => 'The :attribute field is required.', - ); - - $validator = Validator::make(Input::get(), $rules, $messages); - -Great! Now our custom message will be used anytime a **required** validation check fails. But, what is this **:attribute** stuff in our message? To make your life easier, the Validator class will replace the **:attribute** place-holder with the actual name of the attribute! It will even remove underscores from the attribute name. - -You may also use the **:size**, **:min**, **:max**, and **:values** place-holders when constructing your error messages: - - $messages = array( - 'size' => 'The :attribute must be exactly :size.', - 'between' => 'The :attribute must be between :min - :max.', - 'in' => 'The :attribute must be one of the following types: :values', - ); - -So, what if you need to specify a custom **required** message, but only for the **email** attribute? No problem. Just specify the message using an **attribute_rule** naming convention: - - $messages = array( - 'email_required' => 'We need to know your e-mail address!', - ); - -In the example above, the custom required message will be used for the **email** attribute, while the default message will be used for all other attributes. - - -### Creating Custom Validation Rules - -Need to create your own validation rules? You will love how easy it is! First, create a class that extends **System\Validator** and place it in your **application/libraries** directory: - - 'required|awesome', - ); - -Of course, you will need to define an error message for your new rule. You can do this either in an ad-hoc messages array: - - $messages = array( - 'awesome' => 'The attribute value must be awesome!', - ); - - $validator = Validator::make(Input::get(), $rules, $messages); - -Or by adding an entry for your rule in the **application/lang/en/validation.php** file: - - 'awesome' => 'The attribute value must be awesome!', - -As mentioned above, you may even specify and receive a list of parameters in your custom validator: - - // When building your rules array... - - $rules = array( - 'username' => 'required|awesome:yes', - ); - - // In your custom validator... - - class Validator extends System\Validator { - - public function validate_awesome($attribute, $parameters) - { - return $attribute == $parameters[0]; - } - - } - -In this case, the **parameters** argument of your validation rule would receive an array containing one element: "yes". \ No newline at end of file diff --git a/start/views.md b/start/views.md deleted file mode 100644 index 1a62e8d..0000000 --- a/start/views.md +++ /dev/null @@ -1,585 +0,0 @@ -## Views & Responses - -- [Creating Views](/docs/start/views#create) -- [Binding Data To Views](/docs/start/views#bind) -- [Nesting Views Within Views](/docs/start/views#nest) -- [Named Views](/docs/start/views#named-views) -- [View Composers](/docs/start/views#composers) -- [Managing Assets](/docs/start/views#assets) -- [Redirects](/docs/start/views#redirect) -- [Downloads](/docs/start/views#downloads) -- [Building URLs](/docs/start/views#urls) -- [Building HTML](/docs/start/views#html) -- [Pagination](/docs/start/views#pagination) -- [Errors](/docs/start/views#errors) - - -## Creating Views - -Typically, a route function returns a **View**. Views consist of plain ole' HTML and are stored in your **application/views** directory. - -A very simple view file could look like this: - - - Welcome to my website! - - -Assuming this view lives in **application/views/simple.php**, we could return it from a route like so: - - 'GET /home' => function() - { - return View::make('simple'); - } - -When building a large application, you may want to organize your views into sub-directories. That's a great idea! Assuming a view lives in **application/views/user/login.php**, we could return it like so: - - 'GET /home' => function() - { - return View::make('user/login'); - } - -It's that simple. Of course, you are not required to return a View. Strings are also welcome: - - 'GET /home' => function() - { - return json_encode('This is my response!'); - } - - -## Binding Data To Views - -You can pass data to a view by "binding" the data to a variable. This is done using the **bind** method on the View: - - 'GET /home' => function() - { - return View::make('simple')->bind('email', 'example@gmail.com'); - } - -In the example above, the first parameter is the **name** of the view variable. The second parameter is the **value** that will be assigned to the variable. - -Now, in our view, we can access the e-mail address like so: - - - - - -Of course, we can bind as many variables as we wish: - - 'GET /home' => function() - { - return View::make('simple') - ->bind('name', 'Taylor') - ->bind('email', 'example@gmail.com'); - } - -You may also bind view data by simply setting properties on a view instance: - - 'GET /home' => function() - { - $view = View::make('user/login'); - - $view->name = 'Taylor'; - $view->email = 'example@gmail.com'; - - return $view; - } - - -## Nesting Views Within Views - -Want to nest views inside of views? There are two ways to do it, and they are both easy. First, you can bind the view to a variable: - - 'GET /home' => function() - { - $view = View::make('user/login'); - - $view->content = View::make('partials/content'); - $view->footer = View::make('partials/footer'); - - return $view; - } - -Nested calls to **View::make** can get a little ugly. For that reason, Laravel provides a simple **partial** method: - - View::make('layout/default')->partial('content', 'partials/home'); - -The **partial** method is very similar to the **bind** method; however, you simply pass a view name in the second parameter to the method. The view will created and bound to the variable for you. - -Need to bind data to a partial? No problem. Pass the data in the third parameter to the method: - - View::make('layout/default') - ->partial('content', 'partials/home', array('name' => 'Taylor')); - -In some situations, you may need to get the string content of a view from within another view. It's easy using the **get** method: - - - get(); ?> - get(); ?> - - - -## Named Views - -Named views make your code more expressive and beautiful. Using them is simple. All of your named views are defined in the **application/composers.php** file. By default, a name has been defined for the **home/index** view: - - 'home.index' => array('name' => 'home', function($view) - { - // - }) - -Notice the **name** value in the array? This defines the "home" named view as being associated with the **application/views/home/index.php** file. Now, you can use the **View::of** dynamic method to create named view instances using simple, expressive syntax: - - return View::of_home(); - -Of course, you may pass bindings into the **of** method: - - return View::of_home(array('email' => 'example@gmail.com')); - -Since the **of** method returns an instance of the **View** class, you may use any of the View class methods: - - return View::of_home()->bind('email', $email); - -Using named views makes templating a breeze: - - return View::of_layout()->bind('content', $content); - - -## View Composers - -View composers will free you from repetitive, brittle code, and help keep your application beautiful and maintainable. All view composers are defined in the **application/composers.php** file. Each time a view is created, its composer will be called. The composer can bind data to the view, register its assets, or even gather common data needed for the view. When the composer is finished working with the view, it should return the view instance. Here's an example composer: - - return array( - - 'layouts.default' => function($view) - { - Asset::add('jquery', 'js/jquery.js'); - Asset::add('jquery-ui', 'js/jquery-ui.js', 'jquery'); - - $view->partial('header', 'partials/header'); - $view->partial('footer', 'partials/footer'); - - return $view; - } - - ); - -Great! We have defined a composer for the **layouts/default** view. Now, every time the view is created, this composer will be called. As you can see, the composer is registering some common assets, as well as binding partial views to the layout. Of course, we can create an instance of the view using the same syntax we're used to: - - return View::make('layouts.default'); - -There is no need to specify you want to use the composer. It will be called automatically when the view is created. The composer helps keep your code clean by allowing you to declare assets and common partials for views in a single location. Your code will be cleaner than ever. Enjoy the elegance. - - -## Managing Assets - -The **Asset** class provides a simple, elegant way to manage the CSS and JavaScript used by your application. Registering an asset is simple. Just call the **add** method on the **Asset** class: - - Asset::add('jquery', 'js/jquery.js'); - -Wonderful. The **add** method accepts three parameters. The first is the name of the asset, the second is the path to the asset relative to the **public** directory, and the third is a list of asset dependencies (more on that later). Notice that we did not tell the method if we were registering JavaScript or CSS. The **add** method will use the file extension to determine the type of file we are registering. - -When you are ready to place the links to the registered assets on your view, you may use the **styles** or **scripts** methods: - - - - - - -Sometimes you may need to specify that an asset has dependencies. This means that the asset requires other assets to be declared in your view before it can be declared. Managing asset dependencies couldn't be easier in Laravel. Remember the "names" you gave to your assets? You can pass them as the third parameter to the **add** method to declare dependencies: - - Asset::add('jquery-ui', 'js/jquery-ui.js', 'jquery'); - -Great! In this example, we are registering the **jquery-ui** asset, as well as specifying that it is dependent on the **jquery** asset. Now, when you place the asset links on your views, the jQuery asset will always be declared before the jQuery UI asset. Need to declare more than one dependency? No problem: - - Asset::add('jquery-ui', 'js/jquery-ui.js', array('first', 'second')); - -To increase response time, it is common to place JavaScript at the bottom of HTML documents. But, what if you also need to place some assets in the head of your document? No problem. The asset class provides a simple way to manage asset **containers**. Simple call the **container** method on the Asset class and mention the container name. Once you have a container instance, you are free to add any assets you wish to the container using the same syntax you are used to: - - Asset::container('footer')->add('example', 'js/example.js'); - -Getting the links to your container assets is just as simple: - - echo Asset::container('footer')->scripts(); - - -## Redirects - -### Redirect Using URIs - -You will often need to redirect the browser to another location within your application. The **Redirect** class makes this a piece of cake. Here's how to do it: - - 'GET /redirect' => function() - { - return Redirect::to('user/profile'); - } - -Of course, you can also redirect to the root of your application: - - return Redirect::to('/'); - -Need to redirect to a URI that should be accessed over HTTPS? Check out the **to_secure** method: - - return Redirect::to_secure('user/profile'); - -You can even redirect the browser to a location outside of your application: - - return Redirect::to('http://www.google.com/'); - - -### Redirect Using Named Routes - -So far we've created redirects by specifying a URI to redirect to. But, what if the URI to the user's profile changes? It would be better to create a redirect based on the [route name](/docs/start/routes#named). Let's learn how to do it. Assuming the user profile route is named **profile**, you can redirect to the route using a dynamic, static method call like this: - - return Redirect::to_profile(); - -Need to redirect to a route that should be accessed over HTTPS? No problem: - - return Redirect::to_secure_profile(); - -That's great! But, what if the route URI looks like this: - - 'GET /user/profile/(:any)/(:any)' => array('name' => 'profile', 'do' => function() - { - // - }) - -You need to redirect to the named route, but you also need to replace the **(:any)** place-holders in the URI with actual values. It sounds complicated, but Laravel makes it a breeze. Just pass the parameters to the method in an array: - - return Redirect::to_profile(array('taylor', 'otwell')); - -The statement above will redirect the user to the following URL: - - http://example.com/index.php/user/profile/taylor/otwell - - -### Redirect With Flash Data - -After a user creates an account or signs into your application, it is common to display a welcome or status message. But, how can you set the status message so it is available for the next request? The **Response** and **Redirect** classes make it simple using the **with** method. This method will add a value to the Session flash data, which will be available for the next request: - - return Redirect::to('user/profile')->with('status', 'Welcome Back!'); - -> **Note:** For more information regarding Sessions and flash data, check out the [Session documentation](/docs/session/config). - - -## Downloads - -Perhaps you just want to force the web browser to download a file? Check out the **download** method on the **File** class: - - 'GET /file' => function() - { - return File::download('path/to/your/file.jpg'); - } - -In the example above, the image will be downloaded as "file.jpg", however, you can easily specify a different filename for the download in the second parameter to the method: - - 'GET /file' => function() - { - return File::download('path/to/your/file.jpg', 'photo.jpg'); - } - - -## Building URLs - -- [Generating URLs Using URIs](#uri-urls) -- [Generating URLs Using Named Routes](#named-urls) -- [URL Slugs](#url-slugs) - -While developing your application, you will probably need to generate a large number of URLs. Hard-coding your URLs can cause headaches if you switch domains or application locations. Nobody wants to dig through every view in their application to change URLs. Thankfully, the **URL** class provides some simple methods that allow you to easily generate URLs for your application. - - -### Generating URLs Using URIs - -To generate a URL for your application, use the **to** method on the URL class: - - echo URL::to(); - -The statement above will simply return the URL specified in your **application/config/application.php** file. - -However, this method can also append a specified string to the end of your application URL: - - echo URL::to('user/profile'); - -Now the statement will generate a URL something like this: - - http://example.com/index.php/user/login - -Need to generate a HTTPS URL? No problem. Check out the **to\_secure** method: - - echo URL::to_secure('user/profile'); - -Often, you will need to generate URLs to assets such as images, scripts, or styles. You don't want "index.php" inserted into these URLs. So, use the **to_asset** method: - - echo URL::to_asset('img/picture.jpg'); - - -### Generating URLs To Named Routes - -Alright, you have learned how to generate URLs from URIs, but what about from named routes? You can do it by making a dynamic, static method call to the URL class. The syntax is beautiful: - - echo URL::to_profile(); - -Have a route that needs to be accessed over HTTPS? No problem: - - echo URL::to_secure_profile(); - -Could it get any easier? Now, imagine a route that is defined like this: - - 'GET /user/profile/(:any)/(:any)' => array('name' => 'profile', 'do' => function() - { - // - }) - -To generate a URL for the route, you need to replace the **(:any)** place-holders with actual values. It's easy. Just pass the parameters to the method in an array: - - echo URL::to_profile(array('taylor', 'otwell')); - -The method above will generate the following URL: - - http://example.com/index.php/user/profile/taylor/otwell - -If you don't want to use dynamic methods, you can simply call the **to_route** method: - - echo URL::to_route('profile', array('taylor', 'otwell')); - - -### URL Slugs - -When writing an application like a blog, it is often necessary to generate URL "slugs". Slugs are URL friendly strings of text that represent something like a blog post title. Generating slugs is a piece of cake using the **slug** method: - - echo URL::slug('My blog post title!'); - -The statement above will return the following string: - - my-blog-post-title - -Want to use a different separator character? Just mention it to the method: - - echo URL::slug('My blog post title!', '_'); - - -## Building HTML - -- [Entities](#html-entities) -- [JavaScript & Style Sheets](#html-styles) -- [Links](#html-links) -- [Links To Named Routes](#html-route-links) -- [Mail-To Links](#html-mailto) -- [Images](#html-images) -- [Lists](#html-lists) - -Need some convenient methods that make writing HTML a little less painful? Introducing the **HTML** class. Enjoy. - - -### Entities - -When displaying user input in your Views, it is important to convert all characters which have signifance in HTML to their "entity" representation. - -For example, the < symbol should be converted to its entity representation. Converting HTML characters to their entity representation helps protect your application from cross-site scripting. Thankfully, using the **entities** method on the HTML class, it's easy to add this layer of protection to your Views: - - echo HTML::entities(''); - - -### JavaScript & Style Sheets - -What trendy web application doesn't use JavaScript? Generating a reference to a JavaScript file is as simple using the **script** method. - - echo HTML::script('js/scrollTo.js'); - -Referencing cascading style sheets is just as simple. Check out the **style method**: - - echo HTML::style('css/common.css'); - -Need to specify a media type on your style sheet? No problem. Just pass it in the second parameter to the method: - - echo HTML::style('css/common.css', 'print'); - -> **Note:** All scripts and stylesheets should live in the **public** directory of your application. - - -### Links - -Generating links couldn't be easier. Just mention the URL and title to the **link** method: - - echo HTML::link('user/profile', 'User Profile'); - -Need to generate a link to a URL that should be accessed over HTTPS? Use the **secure_link** method: - - echo HTML::secure_link('user/profile', 'User Profile'); - -Of course, you may generate links to locations outside of your application: - - echo HTML::link('http://www.google.com/', 'Search the Intrawebs!'); - -Any other attributes that should be applied to the link may be passed in the third parameter to the method: - - echo HTML::link('http://www.google.com/', 'Search the Intrawebs!', array('id' => 'google')); - - -### Links To Named Routes - -If you are using [named routes](#routes-named), you use intuitive, expressive syntax to create links to those routes via dynamic methods: - - echo HTML::link_to_login('Login'); - -Or, if you need an HTTPS link: - - echo HTML::link_to_secure_login('Login'); - -Now let's assume the **login** route is defined like this: - - 'GET /login/(:any)' => array('name' => 'login', 'do' => function() {}) - -To generate a link to the route, you need to replace the **(:any)** place-holder with an actual value. It's easy. Just pass the parameters to the method in an array: - - echo HTML::link_to_login(array('user')); - -This statement will generate a link to the following URL: - - http://example.com/login/user - - -### Mail-To Links - -It's great to allow your users to get in touch with you, but you don't want to be bombarded by spam. Laravel doesn't want you to be either. The **mailto** method allows you to create a safe mail-to link that obfuscates your e-mail address: - - echo HTML::mailto('example@gmail.com'); - -Want the link text to be something besides your e-mail address? No problem. Just mention it to the method: - - echo HTML::mailto('example@gmail.com', 'E-Mail Me!'); - -Need to obfuscate an e-mail address but don't want to generate an entire mail-to link? Simply pass the e-mail address to the **email** method: - - echo HTML::email('example@gmail.com'); - - -### Images - -Since you're building a creative application, you will need to include some images. The **image** method makes simple. Just pass the URL and Alt text to the method: - - echo HTML::image('img/smile.jpg', 'A Smiling Face'); - -Like the link method, any other attributes that should be applied to the image may be passed in the third parameter to the method: - - echo HTML::image('img/smile.jpg', 'A Smiling Face', array('id' => 'smile')); - - -### Lists - -Generating HTML lists doesn't have to be a headache. Check out the **ol** method. All it needs is an array of items: - - echo HTML::ol(array('Get Peanut Butter', 'Get Chocolate', 'Feast')); - -As usual, you may specify any other attributes that should be applied to the list: - - echo HTML::ol(array('Get Peanut Butter', 'Get Chocolate', 'Feast'), array('class' => 'awesome')); - -Need an un-ordered list? No problem. Just use the **ul** method: - - echo HTML::ul(array('Ubuntu', 'Snow Leopard', 'Windows')); - - -## Pagination - -Just looking at pagination libraries probably makes you cringe. It doesn't have to. Laravel makes pagination enjoyable. Really. - -> **Note:** Before learning about pagination, you should probably read up on [Eloquent models](/docs/database/eloquent). - -To learn about pagination, we'll use an "User" Eloquent model. First, let's define a **per_page** static property on our model. This will tell Laravel how many users to show per page when paginating lists of users: - - class User extends Eloquent { - - public static $per_page = 10; - - } - -Great! Now you're ready to get paginated results from the database. It couldn't be any easier. Just use the **paginate** method: - - $users = User::where('posts', '>', 100)->paginate(); - -The **paginate** method will return an instance of the **Paginator** class. Notice you didn't have to specify the current page or the total amount of users. Laravel makes your life easier by figuring that stuff out for you. The results of your query can be accessed via the **results** property on the Paginator instance: - - $results = $users->results; - -Need to paginate results using the [Fluent query builder](/docs/database/query)? Simply pass the number of items to show per page into the **paginate** method: - - $users = DB::table('users')->where('votes', '>' 100)->paginate(10); - -You can even specify which columns to retrieve. Just pass an array of column names as the second parameter to the method: - - $users = DB::table('users') - ->where('votes', '>' 100) - ->paginate(10, array('id', 'email')); - -Alright, now you are ready to display the results on a View: - - results as $user): ?> -

name; ?>

- - -Ready to create the pagination links? Simply call the **links** method on the Paginator instance: - - echo $users->links(); - -The links method will create an intelligent, sliding list of page links that looks something like this: - - Previous 1 2 ... 24 25 26 27 28 29 30 ... 78 79 Next - -Feeling more minimal? You can create simple "Previous" and "Next" links using the **previous** and **next** methods on the Paginator instance: - - previous().' | '.$users->next(); ?> - -The URLs created by the Pagination class look something like this: - - http://example.com/something?page=2 - -Sometimes, you may wish to add more items to the query string, such as the column you are sorting by. It's a breeze. Use the **append** method on your Paginator instance: - - append(array('sort' => 'votes'))->links(); - -Great! Now the URLs will look like this: - - http://example.com/something?page=2&sort=votes - -Need to style your links? No problem. All pagination link elements can be style using CSS classes. Here is an example of the HTML elements generated by the **links** method: - - - -When you are on the first page of results, the "Previous" link will be disabled. Likewise, the "Next" link will be disabled when you are on the last page of results. The generated HTML will look like this: - - Previous - - -## Errors - -Sometimes you may need to return an error response, such as the **404** or **500** views. It can be done like this: - - return Response::make(View::make('error/404'), 404); - -But, that's a little cumbersome. Instead, use the **error** method on the **Response** class. Just mention the error you want to return: - - return Response::error('404'); - -> **Note:** The error passed the **error** method must have a corresponding view in the **application/views/error** directory. \ No newline at end of file diff --git a/strings.md b/strings.md new file mode 100644 index 0000000..002d914 --- /dev/null +++ b/strings.md @@ -0,0 +1,71 @@ +# Working With Strings + +## Contents + +- [Capitalization, Etc.](#capitalization) +- [Word & Character Limiting](#limits) +- [Generating Random Strings](#random) +- [Singular & Plural](#singular-and-plural) +- [Slugs](#slugs) + + +## Capitalization, Etc. + +The **Str** class also provides three convenient methods for manipulating string capitalization: **upper**, **lower**, and **title**. These are more intelligent versions of the PHP [strtoupper](http://php.net/manual/en/function.strtoupper.php), [strtolower](http://php.net/manual/en/function.strtolower.php), and [ucwords](http://php.net/manual/en/function.ucwords.php) methods. More intelligent because they can handle UTF-8 input if the [multi-byte string](http://php.net/manual/en/book.mbstring.php) PHP extension is installed on your web server. To use them, just pass a string to the method: + + echo Str::lower('I am a string.'); + + echo Str::upper('I am a string.'); + + echo Str::title('I am a string.'); + + +## Word & Character Limiting + +#### Limiting the number of characters in a string: + + echo Str::limit($string, 10); + +#### Limiting the number of words in a string: + + echo Str::words($string, 10); + + +## Generating Random Strings + +#### Generating a random string of alpha-numeric characters: + + echo Str::random(32); + +#### Generating a random string of alphabetic characters: + + echo Str::random(32, 'alpha'); + + +## Singular & Plural + +The String class is capable of transforming your strings from singular to plural, and vice versa. + +#### Getting the plural form of a word: + + echo Str::plural('user'); + +#### Getting the singular form of a word: + + echo Str::singular('users'); + +#### Getting the plural form if given value is greater than one: + + echo Str::plural('comment', count($comments)); + + +## Slugs + +#### Generating a URL friendly slug: + + return Str::slug('My First Blog Post!'); + +#### Generating a URL friendly slug using a given separator: + + return Str::slug('My First Blog Post!', '_'); + diff --git a/testing.md b/testing.md new file mode 100644 index 0000000..a7d958c --- /dev/null +++ b/testing.md @@ -0,0 +1,68 @@ +# Unit Testing + +## Contents + +- [The Basics](#the-basics) +- [Creating Test Classes](#creating-test-classes) +- [Running Tests](#running-tests) +- [Calling Controllers From Tests](#calling-controllers-from-tests) + + +## The Basics + +Unit Testing allows you to test your code and verify that it is working correctly. In fact, many advocate that you should even write your tests before you write your code! Laravel provides beautiful integration with the popular [PHPUnit](http://www.phpunit.de/manual/current/en/) testing library, making it easy to get started writing your tests. In fact, the Laravel framework itself has hundreds of unit tests! + + +## Creating Test Classes + +All of your application's tests live in the **application/tests** directory. In this directory, you will find a basic **example.test.php** file. Pop it open and look at the class it contains: + + assertTrue(true); + } + + } + +Take special note of the **.test.php** file suffix. This tells Laravel that it should include this class as a test case when running your test. Any files in the test directory that are not named with this suffix will not be considered a test case. + +If you are writing tests for a bundle, just place them in a **tests** directory within the bundle. Laravel will take care of the rest! + +For more information regarding creating test cases, check out the [PHPUnit documentation](http://www.phpunit.de/manual/current/en/). + + +## Running Tests + +To run your tests, you can use Laravel's Artisan command-line utility: + +#### Running the application's tests via the Artisan CLI: + + php artisan test + +#### Running the unit tests for a bundle: + + php artisan test bundle-name + + +## Calling Controllers From Tests + +Here's an example of how you can call your controllers from your tests: + +#### Calling a controller from a test: + + $response = Controller::call('home@index', $parameters); + +#### Resolving an instance of a controller from a test: + + $controller = Controller::resolve('application', 'home@index'); + +> **Note:** The controller's action filters will still run when using Controller::call to execute controller actions. \ No newline at end of file diff --git a/urls.md b/urls.md new file mode 100644 index 0000000..4263712 --- /dev/null +++ b/urls.md @@ -0,0 +1,98 @@ +# Generating URLs + +## Contents + +- [The Basics](#the-basics) +- [URLs To Routes](#urls-to-routes) +- [URLs To Controller Actions](#urls-to-controller-actions) +- [URLs To Assets](#urls-to-assets) +- [URL Helpers](#url-helpers) + + +## The Basics + +#### Retrieving the application's base URL: + + $url = URL::base(); + +#### Generating a URL relative to the base URL: + + $url = URL::to('user/profile'); + +#### Generating a HTTPS URL: + + $url = URL::to_secure('user/login'); + +#### Retrieving the current URL: + + $url = URL::current(); + +#### Retrieving the current URL including query string: + + $url = URL::full(); + + +## URLs To Routes + +#### Generating a URL to a named route: + + $url = URL::to_route('profile'); + +Sometimes you may need to generate a URL to a named route, but also need to specify the values that should be used instead of the route's URI wildcards. It's easy to replace the wildcards with proper values: + +#### Generating a URL to a named route with wildcard values: + + $url = URL::to_route('profile', array($username)); + +*Further Reading:* + +- [Named Routes](/docs/routing#named-routes) + + +## URLs To Controller Actions + +#### Generating a URL to a controller action: + + $url = URL::to_action('user@profile'); + +#### Generating a URL to an action with wildcard values: + + $url = URL::to_action('user@profile', array($username)); + + +## URLs To Assets + +URLs generated for assets will not contain the "application.index" configuration option. + +#### Generating a URL to an asset: + + $url = URL::to_asset('js/jquery.js'); + + +## URL Helpers + +There are several global functions for generating URLs designed to make your life easier and your code cleaner: + +#### Generating a URL relative to the base URL: + + $url = url('http://github.com/user/profile'); + +#### Generating a URL to an asset: + + $url = asset('js/jquery.js'); + +#### Generating a URL to a named route: + + $url = route('profile'); + +#### Generating a URL to a named route with wildcard values: + + $url = route('profile', array($username)); + +#### Generating a URL to a controller action: + + $url = action('user@profile'); + +#### Generating a URL to an action with wildcard values: + + $url = action('user@profile', array($username)); \ No newline at end of file diff --git a/validation.md b/validation.md new file mode 100644 index 0000000..1c932ae --- /dev/null +++ b/validation.md @@ -0,0 +1,431 @@ +# Validation + +## Contents + +- [The Basics](#the-basics) +- [Validation Rules](#validation-rules) +- [Retrieving Error Message](#retrieving-error-messages) +- [Validation Walkthrough](#validation-walkthrough) +- [Custom Error Messages](#custom-error-messages) +- [Custom Validation Rules](#custom-validation-rules) + + +## The Basics + +Almost every interactive web application needs to validate data. For instance, a registration form probably requires the password to be confirmed. Maybe the e-mail address must be unique. Validating data can be a cumbersome process. Thankfully, it isn't in Laravel. The Validator class provides as awesome array of validation helpers to make validating your data a breeze. Let's walk through an example: + +#### Get an array of data you want to validate: + + $input = Input::all(); + +#### Define the validation rules for your data: + + $rules = array( + 'name' => 'required|max:50', + 'email' => 'required|email|unique:users', + ); + +#### Create a Validator instance and validate the data: + + $validation = Validator::make($input, $rules); + + if ($validation->fails()) + { + return $validation->errors; + } + +With the *errors* property, you can access a simple message collector class that makes working with your error messages a piece of cake. Of course, default error messages have been setup for all validation rules. The default messages live at **language/en/validation.php**. + +Now you are familiar with the basic usage of the Validator class. You're ready to dig in and learn about the rules you can use to validate your data! + + +## Validation Rules + +- [Required](#rule-required) +- [Alpha, Alpha Numeric, & Alpha Dash](#rule-alpha) +- [Size](#rule-size) +- [Numeric](#rule-numeric) +- [Inclusion & Exclusion](#rule-in) +- [Confirmation](#rule-confirmation) +- [Acceptance](#rule-acceptance) +- [Same & Different](#same-and-different) +- [Regular Expression Match](#regex-match) +- [Uniqueness & Existence](#rule-unique) +- [Dates](#dates) +- [E-Mail Addresses](#rule-email) +- [URLs](#rule-url) +- [Uploads](#rule-uploads) + + +### Required + +#### Validate that an attribute is present and is not an empty string: + + 'name' => 'required' + + +### Alpha, Alpha Numeric, & Alpha Dash + +#### Validate that an attribute consists solely of letters: + + 'name' => 'alpha' + +#### Validate that an attribute consists of letters and numbers: + + 'username' => 'alpha_num' + +#### Validate that an attribute only contains letters, numbers, dashes, or underscores: + + 'username' => 'alpha_dash' + + +### Size + +#### Validate that an attribute is a given length, or, if an attribute is numeric, is a given value: + + 'name' => 'size:10' + +#### Validate that an attribute size is within a given range: + + 'payment' => 'between:10,50' + +> **Note:** All minimum and maximum checks are inclusive. + +#### Validate that an attribute is at least a given size: + + 'payment' => 'min:10' + +#### Validate that an attribute is no greater than a given size: + + 'payment' => 'max:50' + + +### Numeric + +#### Validate that an attribute is numeric: + + 'payment' => 'numeric' + +#### Validate that an attribute is an integer: + + 'payment' => 'integer' + + +### Inclusion & Exclusion + +#### Validate that an attribute is contained in a list of values: + + 'size' => 'in:small,medium,large' + +#### Validate that an attribute is not contained in a list of values: + + 'language' => 'not_in:cobol,assembler' + + +### Confirmation + +The *confirmed* rule validates that, for a given attribute, a matching *attribute_confirmation* attribute exists. + +#### Validate that an attribute is confirmed: + + 'password' => 'confirmed' + +Given this example, the Validator will make sure that the *password* attribute matches the *password_confirmation* attribute in the array being validated. + + +### Acceptance + +The *accepted* rule validates that an attribute is equal to *yes* or *1*. This rule is helpful for validating checkbox form fields such as "terms of service". + +#### Validate that an attribute is accepted: + + 'terms' => 'accepted' + + +## Same & Different + +#### Validate that an attribute matches another attribute: + + 'token1' => 'same:token2' + +#### Validate that two attributes have different values: + + 'password' => 'different:old_password', + + +### Regular Expression Match + +The *match* rule validates that an attribute matches a given regular expression. + +#### Validate that an attribute matches a regular expression: + + 'username' => 'match:/[a-z]+/'; + + +### Uniqueness & Existence + +#### Validate that an attribute is unique on a given database table: + + 'email' => 'unique:users' + +In the example above, the *email* attribute will be checked for uniqueness on the *users* table. Need to verify uniqueness on a column name other than the attribute name? No problem: + +#### Specify a custom column name for the unique rule: + + 'email' => 'unique:users,email_address' + +Many times, when updating a record, you want to use the unique rule, but exclude the row being updated. For example, when updating a user's profile, you may allow them to change their e-mail address. But, when the *unique* rule runs, you want it to skip the given user since they may not have changed their address, thus causing the *unique* rule to fail. It's easy: + +#### Forcing the unique rule to ignore a given ID: + + 'email' => 'unique:users,email_address,10' + +#### Validate that an attribute exists on a given database table: + + 'state' => 'exists:states' + +#### Specify a custom column name for the exists rule: + + 'state' => 'exists:states,abbreviation' + + +### Dates + +#### Validate that a date attribute is before a given date: + + 'birthdate' => 'before:1986-05-28'; + +#### Validate that a date attribute is after a given date: + + 'birthdate' => 'after:1986-05-28'; + +> **Note:** The **before** and **after** validation rules use the **strtotime** PHP function to convert your date to something the rule can understand. + + +### E-Mail Addresses + +#### Validate that an attribute is an e-mail address: + + 'address' => 'email' + +> **Note:** This rule uses the PHP built-in *filter_var* method. + + +### URLs + +#### Validate that an attribute is a URL: + + 'link' => 'url' + +#### Validate that an attribute is an active URL: + + 'link' => 'active_url' + +> **Note:** The *active_url* rule uses *checkdnsr* to verify the URL is active. + + +### Uploads + +The *mimes* rule validates that an uploaded file has a given MIME type. This rule uses the PHP Fileinfo extension to read the contents of the file and determine the actual MIME type. Any extension defined in the *config/mimes.php* file may be passed to this rule as a parameter: + +#### Validate that a file is one of the given types: + + 'picture' => 'mimes:jpg,gif' + +> **Note:** When validating files, be sure to use Input::file() or Input::all() to gather the input. + +#### Validate that a file is an image: + + 'picture' => 'image' + +#### Validate that a file is no more than a given size in kilobytes: + + 'picture' => 'image|max:100' + + +## Retrieving Error Messages + +Laravel makes working with your error messages a cinch using a simple error collector class. After calling the *passes* or *fails* method on a Validator instance, you may access the errors via the *errors* property. The error collector has several simple functions for retrieving your messages: + +#### Determine if an attribute has an error message: + + if ($validation->errors->has('email')) + { + // The e-mail attribute has errors... + } + +#### Retrieve the first error message for an attribute: + + echo $validation->errors->first('email'); + +Sometimes you may need to format the error message by wrapping it in HTML. No problem. Along with the :message place-holder, pass the format as the second parameter to the method. + +#### Format an error message: + + echo $validation->errors->first('email', '

:message

'); + +#### Get all of the error messages for a given attribute: + + $messages = $validation->errors->get('email'); + +#### Format all of the error messages for an attribute: + + $messages = $validation->errors->get('email', '

:message

'); + +#### Get all of the error messages for all attributes: + + $messages = $validation->errors->all(); + +#### Format all of the error messages for all attributes: + + $messages = $validation->errors->all('

:message

'); + + +## Validation Walkthrough + +Once you have performed your validation, you need an easy way to get the errors back to the view. Laravel makes it amazingly simple. Let's walk through a typical scenario. We'll define two routes: + + Route::get('register', function() + { + return View::make('user.register'); + }); + + Route::post('register', function() + { + $rules = array(...); + + $validation = Validator::make(Input::all(), $rules); + + if ($validation->fails()) + { + return Redirect::to('register')->with_errors($validation); + } + }); + +Great! So, we have two simple registration routes. One to handle displaying the form, and one to handle the posting of the form. In the POST route, we run some validation over the input. If the validation fails, we redirect back to the registration form and flash the validation errors to the session so they will be available for us to display. + +**But, notice we are not explicitly binding the errors to the view in our GET route**. However, an errors variable will still be available in the view. Laravel intelligently determines if errors exist in the session, and if they do, binds them to the view for you. If no errors exist in the session, an empty message container will still be bound to the view. In your views, this allows you to always assume you have a message container available via the errors variable. We love making your life easier. + + +## Custom Error Messages + +Want to use an error message other than the default? Maybe you even want to use a custom error message for a given attribute and rule. Either way, the Validator class makes it easy. + +#### Create an array of custom messages for the Validator: + + $messages = array( + 'required' => 'The :attribute field is required.', + ); + + $validation = Validator::make(Input::get(), $rules, $messages); + +Great! Now our custom message will be used anytime a required validation check fails. But, what is this **:attribute** stuff in our message? To make your life easier, the Validator class will replace the **:attribute** place-holder with the actual name of the attribute! It will even remove underscores from the attribute name. + +You may also use the **:other**, **:size**, **:min**, **:max**, and **:values** place-holders when constructing your error messages: + +#### Other validation message place-holders: + + $messages = array( + 'same' => 'The :attribute and :other must match.', + 'size' => 'The :attribute must be exactly :size.', + 'between' => 'The :attribute must be between :min - :max.', + 'in' => 'The :attribute must be one of the following types: :values', + ); + +So, what if you need to specify a custom required message, but only for the email attribute? No problem. Just specify the message using an **attribute_rule** naming convention: + +#### Specifying a custom error message for a given attribute: + + $messages = array( + 'email_required' => 'We need to know your e-mail address!', + ); + +In the example above, the custom required message will be used for the email attribute, while the default message will be used for all other attributes. + +However, if you are using many custom error messages, specifying inline may become cumbersome and messy. For that reason, you can specify your custom messages in the **custom** array within the validation language file: + +#### Adding custom error messages to the validation langauge file: + + 'custom' => array( + 'email_required' => 'We need to know your e-mail address!', + ) + + +## Custom Validation Rules + +Laravel provides a number of powerful validation rules. However, it's very likely that you'll need to eventually create some of your own. There are two simple methods for creating validation rules. Both are solid so use whichever you think best fits your project. + +#### Registering a custom validation rule: + + Validator::register('awesome', function($attribute, $value, $parameters) + { + return $value == 'awesome'; + }); + +In this example we're registering a new validation rule with the validator. The rule receives three arguments. The first is the name of the attribute being validated, the second is the value of the attribute being validated, and the third is an array of parameters that were specified for the rule. + +Here is how your custom validation rule looks when called: + + $rules = array( + 'username' => 'required|awesome', + ); + +Of course, you will need to define an error message for your new rule. You can do this either in an ad-hoc messages array: + + $messages = array( + 'awesome' => 'The attribute value must be awesome!', + ); + + $validator = Validator::make(Input::get(), $rules, $messages); + +Or by adding an entry for your rule in the **language/en/validation.php** file: + + 'awesome' => 'The attribute value must be awesome!', + +As mentioned above, you may even specify and receive a list of parameters in your custom rule: + + // When building your rules array... + + $rules = array( + 'username' => 'required|awesome:yes', + ); + + // In your custom rule... + + Validator::register('awesome', function($attribute, $value, $parameters) + { + return $value == $parameters[0]; + } + +In this case, the parameters argument of your validation rule would receive an array containing one element: "yes". + +Another method for creating and storing custom validation rules is to extend the Validator class itself. By extending the class you create a new version of the validator that has all of the pre-existing functionality combined with your own custom additions. You can even choose to replace some of the default methods if you'd like. Let's look at an example: + +First, create a class that extends **Laravel\Validator** and place it in your **application/libraries** directory: + +#### Defining a custom validator class: + + +## Registering Assets + +The **Asset** class provides a simple way to manage the CSS and JavaScript used by your application. To register an asset just call the **add** method on the **Asset** class: + +#### Registering an asset: + + Asset::add('jquery', 'js/jquery.js'); + +The **add** method accepts three parameters. The first is the name of the asset, the second is the path to the asset relative to the **public** directory, and the third is a list of asset dependencies (more on that later). Notice that we did not tell the method if we were registering JavaScript or CSS. The **add** method will use the file extension to determine the type of file we are registering. + + +## Dumping Assets + +When you are ready to place the links to the registered assets on your view, you may use the **styles** or **scripts** methods: + +#### Dumping assets into a view: + + + + + + + +## Asset Dependencies + +Sometimes you may need to specify that an asset has dependencies. This means that the asset requires other assets to be declared in your view before it can be declared. Managing asset dependencies couldn't be easier in Laravel. Remember the "names" you gave to your assets? You can pass them as the third parameter to the **add** method to declare dependencies: + +#### Registering a bundle that has dependencies: + + Asset::add('jquery-ui', 'js/jquery-ui.js', 'jquery'); + +In this example, we are registering the **jquery-ui** asset, as well as specifying that it is dependent on the **jquery** asset. Now, when you place the asset links on your views, the jQuery asset will always be declared before the jQuery UI asset. Need to declare more than one dependency? No problem: + +#### Registering an asset that has multiple dependencies: + + Asset::add('jquery-ui', 'js/jquery-ui.js', array('first', 'second')); + + +## Asset Containers + +To improve response time, it is common to place JavaScript at the bottom of HTML documents. But, what if you also need to place some assets in the head of your document? No problem. The asset class provides a simple way to manage asset **containers**. Simply call the **container** method on the Asset class and mention the container name. Once you have a container instance, you are free to add any assets you wish to the container using the same syntax you are used to: + +#### Retrieving an instance of an asset container: + + Asset::container('footer')->add('example', 'js/example.js'); + +#### Dumping that asset from a given container: + + echo Asset::container('footer')->scripts(); + + +## Bundle Assets + +Before learning how to conveniently add and dump bundle assets, you may wish to read the documentation on [creating and publishing bundle assets](/docs/bundles#bundle-assets). + +When registering assets, the paths are typically relative to the **public** directory. However, this is inconvenient when dealing with bundle assets, since they live in the **public/bundles** directory. But, remember, Laravel is here to make your life easier. So, it is simple to specify the bundle which the Asset container is managing. + +#### Specifying the bundle the asset container is managing: + + Asset::container('foo')->bundle('admin'); + +Now, when you add an asset, you can use paths relative to the bundle's public directory. Laravel will automatically generate the correct full paths. \ No newline at end of file diff --git a/views/forms.md b/views/forms.md new file mode 100644 index 0000000..f6b73e4 --- /dev/null +++ b/views/forms.md @@ -0,0 +1,167 @@ +# Building Forms + +## Contents + +- [Opening A Form](#opening-a-form) +- [CSRF Protection](#csrf-protection) +- [Labels](#labels) +- [Text, Text Area, Password & Hidden Fields](#text) +- [Checkboxes and Radio Buttons](#checkboxes-and-radio-buttons) +- [Drop-Down Lists](#drop-down-lists) +- [Buttons](#buttons) +- [Custom Macros](#custom-macros) + +> **Note:** All input data displayed in form elements is filtered through the HTML::entities method. + + +## Opening A Form + +#### Opening a form to POST to the current URL: + + echo Form::open(); + +#### Opening a form using a given URI and request method: + + echo Form::open('user/profile', 'PUT'); + +#### Opening a Form that POSTS to a HTTPS URL: + + echo Form::open_secure('user/profile'); + +#### Specifying extra HTML attributes on a form open tag: + + echo Form::open('user/profile', 'POST', array('class' => 'awesome')); + +#### Opening a form that accepts file uploads: + + echo Form::open_for_files('users/profile'); + +#### Opening a form that accepts file uploads and uses HTTPS: + + echo Form::open_secure_for_files('users/profile'); + +#### Closing a form: + + echo Form::close(); + + +## CSRF Protection + +Laravel provides an easy method of protecting your application from cross-site request forgeries. 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: + +#### Generating a hidden field containing the session's CSRF token: + + echo Form::token(); + +#### Attaching the CSRF filter to a route: + + Route::post('profile', array('before' => 'csrf', function() + { + // + })); + +#### Retrieving the CSRF token string: + + $token = Session::token(); + +> **Note:** You must specify a session driver before using the Laravel CSRF protection facilities. + +*Further Reading:* + +- [Route Filters](/docs/routing#filters) +- [Cross-Site Request Forgery](http://en.wikipedia.org/wiki/Cross-site_request_forgery) + + +## Labels + +#### Generating a label element: + + echo Form::label('email', 'E-Mail Address'); + +#### Specifying extra HTML attributes for a label: + + 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. + + +## Text, Text Area, Password & Hidden Fields + +#### Generate a text input element: + + echo Form::text('username'); + +#### Specifying a default value for a text input element: + + echo Form::text('email', 'example@gmail.com'); + +> **Note:** The *hidden* and *textarea* methods have the same signature as the *text* method. You just learned three methods for the price of one! + +#### Generating a password input element: + + echo Form::password('password'); + + +## Checkboxes and Radio Buttons + +#### Generating a checkbox input element: + + echo Form::checkbox('name', 'value'); + +#### Generating a checkbox that is checked by default: + + echo Form::checkbox('name', 'value', true); + +> **Note:** The *radio* method has the same signature as the *checkbox* method. Two for one! + + +## Drop-Down Lists + +#### Generating a drop-down list from an array of items: + + echo Form::select('size', array('L' => 'Large', 'S' => 'Small')); + +#### Generating a drop-down list with an item selected by default: + + echo Form::select('size', array('L' => 'Large', 'S' => 'Small'), 'S'); + +#### Generating drop-down list options from the database + +In this example we need to create a drop-down list that allows an administrator to choose a user account. To do so we use the lists() method. + + $user_options = User::where('type', '=', 'standard')->lists('real_name', 'id'); + +This will create an array called $user_options which will have the user record's 'id' field as the key and the user record's 'real_name' field as the value. This is ideal for drop-down lists. + + echo Form::select('user_id', User::where('type', '=', 'standard')->lists('real_name', 'id'), Input::old('user_id')); + +A fun trick to add a default empty list item: + + $user_options = array('') + User::where('type', '=', 'standard')->lists('real_name', 'id'); + + +## Buttons + +#### Generating a submit button element: + + echo Form::submit('Click Me!'); + +> **Note:** Need to create a button element? Try the *button* method. It has the same signature as *submit*. + + +## Custom Macros + +It's easy to define your own custom Form class helpers called "macros". Here's how it works. First, simply register the macro with a given name and a Closure: + +#### Registering a Form macro: + + Form::macro('my_field', function() + { + return ''; + }); + +Now you can call your macro using its name: + +#### Calling a custom Form macro: + + echo Form::my_field(); \ No newline at end of file diff --git a/views/home.md b/views/home.md new file mode 100644 index 0000000..332c8c0 --- /dev/null +++ b/views/home.md @@ -0,0 +1,245 @@ +# Views & Responses + +## Contents + +- [The Basics](#the-basics) +- [Binding Data To Views](#binding-data-to-views) +- [Nesting Views](#nesting-views) +- [Named Views](#named-views) +- [View Composers](#view-composers) +- [Redirects](#redirects) +- [Redirecting With Flash Data](#redirecting-with-flash-data) +- [Downloads](#downloads) +- [Errors](#errors) + + +## The Basics + +Views contain the HTML that is sent to the person using your application. By separating your view from the business logic of your application, your code will be cleaner and easier to maintain. + +All views are stored within the **application/views** directory and use the PHP file extension. The **View** class provides a simple way to retrieve your views and return them to the client. Let's look at an example! + +#### Creating the view: + + + I'm stored in views/home/index.php! + + +#### Returning the view from a route: + + Route::get('/', function() + { + return View::make('home.index'); + }); + +#### Returning the view from a controller: + + public function action_index() + { + return View::make('home.index'); + }); + +Sometimes you will need a little more control over the response sent to the browser. For example, you may need to set a custom header on the response, or change the HTTP status code. Here's how: + +#### Returning a custom response: + + Route::get('/', function() + { + $headers = array('foo' => 'bar'); + + return Response::make('Hello World!', 200, $headers); + }); + +#### Returning a custom response containing a view: + + return Response::view('home', 200, $headers); + + +## Binding Data To Views + +Typically, a route or controller will request data from a model that the view needs to display. So, we need a way to pass the data to the view. There are several ways to accomplish this, so just pick the way that you like best! + +#### Binding data to a view: + + Route::get('/', function() + { + return View::make('home')->with('name', 'James'); + }); + +#### Accessing the bound data within a view: + + + Hello, . + + +#### Chaining the binding of data to a view: + + View::make('home') + ->with('name', 'James') + ->with('votes', 25); + +#### Passing an array of data to bind data: + + View::make('home', array('name' => 'James')); + +#### Using magic methods to bind data: + + $view->name = 'James'; + $view->email = 'example@example.com'; + +#### Using the ArrayAccess interface methods to bind data: + + $view['name'] = 'James'; + $view['email'] = 'example@example.com'; + +#### Share a value with all views into your application: + + View::share('key', 'value'); + + +## Nesting Views + +Often you will want to nest views within views. Nested views are sometimes called "partials", and help you keep views small and modular. + +#### Binding a nested view using the "nest" method: + + View::make('home')->nest('footer', 'partials.footer'); + +#### Passing data to a nested view: + + $view = View::make('home'); + + $view->nest('content', 'orders', array('orders' => $orders)); + +Sometimes you may wish to directly include a view from within another view. You can use the **render** helper function: + +#### Using the "render" helper to display a view: + +
+ +
+ +It is also very common to have a partial view that is responsible for display an instance of data in a list. For example, you may create a partial view responsible for displaying the details about a single order. Then, for example, you may loop through an array of orders, rendering the partial view for each order. This is made simpler using the **render_each** helper: + +#### Rendering a partial view for each item in an array: + +
+ + +The first argument is the name of the partial view, the second is the array of data, and the third is the variable name that should be used when each array item is passed to the partial view. + + +## Named Views + +Named views can help to make your code more expressive and organized. Using them is simple: + +#### Registering a named view: + + View::name('layouts.default', 'layout'); + +#### Getting an instance of the named view: + + return View::of('layout'); + +#### Binding data to a named view: + + return View::of('layout', array('orders' => $orders)); + + +## View Composers + +Each time a view is created, its "composer" event will be fired. You can listen for this event and use it to bind assets and common data to the view each time it is created. A common use-case for this functionality is a side-navigation partial that shows a list of random blog posts. You can nest your partial view by loading it in your layout view. Then, define a composer for that partial. The composer can then query the posts table and gather all of the necessary data to render your view. No more random logic strewn about! Composers are typically defined in **application/routes.php**. Here's an example: + +#### Register a view composer for the "home" view: + + View::composer('home', function($view) + { + $view->nest('footer', 'partials.footer'); + }); + +Now each time the "home" view is created, an instance of the View will be passed to the registered Closure, allowing you to prepare the view however you wish. + +> **Note:** A view can have more than one composer. Go wild! + + +## Redirects + +It's important to note that both routes and controllers require responses to be returned with the 'return' directive. Instead of calling "Redirect::to()"" where you'd like to redirect the user. You'd instead use "return Redirect::to()". This distinction is important as it's different than most other PHP frameworks and it could be easy to accidentally overlook the importance of this practice. + +#### Redirecting to another URI: + + return Redirect::to('user/profile'); + +#### Redirecting with a specific status: + + return Redirect::to('user/profile', 301); + +#### Redirecting to a secure URI: + + return Redirect::to_secure('user/profile'); + +#### Redirecting to the root of your application: + + return Redirect::home(); + +#### Redirecting back to the previous action: + + return Redirect::back(); + +#### Redirecting to a named route: + + return Redirect::to_route('profile'); + +#### Redirecting to a controller action: + + return Redirect::to_action('home@index'); + +Sometimes you may need to redirect to a named route, but also need to specify the values that should be used instead of the route's URI wildcards. It's easy to replace the wildcards with proper values: + +#### Redirecting to a named route with wildcard values: + + return Redirect::to_route('profile', array($username)); + +#### Redirecting to an action with wildcard values: + + return Redirect::to_action('user@profile', array($username)); + + +## Redirecting With Flash Data + +After a user creates an account or signs into your application, it is common to display a welcome or status message. But, how can you set the status message so it is available for the next request? Use the with() method to send flash data along with the redirect response. + + return Redirect::to('profile')->with('status', 'Welcome Back!'); + +You can access your message from the view with the Session get method: + + $status = Session::get('status'); + +*Further Reading:* + +- *[Sessions](/docs/session/config)* + + +## Downloads + +#### Sending a file download response: + + return Response::download('file/path.jpg'); + +#### Sending a file download and assigning a file name: + + return Response::download('file/path.jpg', 'photo.jpg'); + + +## Errors + +To generate proper error responses simply specify the response code that you wish to return. The corresponding view stored in **views/error** will automatically be returned. + +#### Generating a 404 error response: + + return Response::error('404'); + +#### Generating a 500 error response: + + return Response::error('500'); \ No newline at end of file diff --git a/views/html.md b/views/html.md new file mode 100644 index 0000000..efa8dda --- /dev/null +++ b/views/html.md @@ -0,0 +1,139 @@ +# Building HTML + +## Content + +- [Entities](#entities) +- [Scripts And Style Sheets](#scripts-and-style-sheets) +- [Links](#links) +- [Links To Named Routes](#links-to-named-routes) +- [Links To Controller Actions](#links-to-controller-actions) +- [Mail-To Links](#mail-to-links) +- [Images](#images) +- [Lists](#lists) +- [Custom Macros](#custom-macros) + + +## Entities + +When displaying user input in your Views, it is important to convert all characters which have signifance in HTML to their "entity" representation. + +For example, the < symbol should be converted to its entity representation. Converting HTML characters to their entity representation helps protect your application from cross-site scripting: + +#### Converting a string to its entity representation: + + echo HTML::entities(''); + +#### Using the "e" global helper: + + echo e(''); + + +## Scripts And Style Sheets + +#### Generating a reference to a JavaScript file: + + echo HTML::script('js/scrollTo.js'); + +#### Generating a reference to a CSS file: + + echo HTML::style('css/common.css'); + +#### Generating a reference to a CSS file using a given media type: + + echo HTML::style('css/common.css', array('print')); + +*Further Reading:* + +- *[Managing Assets](/docs/views/assets)* + + +## Links + +#### Generating a link from a URI: + + echo HTML::link('user/profile', 'User Profile'); + +#### Generating a link that should use HTTPS: + + echo HTML::secure_link('user/profile', 'User Profile'); + +#### Generating a link and specifying extra HTML attributes: + + echo HTML::link('user/profile', 'User Profile', array('id' => 'profile_link')); + + +## Links To Named Routes + +#### Generating a link to a named route: + + echo HTML::link_to_route('profile'); + +#### Generating a link to a named route with wildcard values: + + $url = HTML::link_to_route('profile', array($username)); + +*Further Reading:* + +- *[Named Routes](/docs/routing#named-routes)* + + +## Links To Controller Actions + +#### Generating a link to a controller action: + + echo HTML::link_to_action('home@index'); + +### Generating a link to a controller action with wildcard values: + + echo HTML::link_to_action('user@profile', array($username)); + + +## Mail-To Links + +The "mailto" method on the HTML class obfuscates the given e-mail address so it is not sniffed by bots. + +#### Creating a mail-to link: + + echo HTML::mailto('example@gmail.com', 'E-Mail Me!'); + +#### Creating a mail-to link using the e-mail address as the link text: + + echo HTML::mailto('example@gmail.com'); + + +## Images + +#### Generating an HTML image tag: + + echo HTML::image('img/smile.jpg', $alt_text); + +#### Generating an HTML image tag with extra HTML attributes: + + echo HTML::image('img/smile.jpg', $alt_text, array('id' => 'smile')); + + +## Lists + +#### Creating lists from an array of items: + + echo HTML::ol(array('Get Peanut Butter', 'Get Chocolate', 'Feast')); + + echo HTML::ul(array('Ubuntu', 'Snow Leopard', 'Windows')); + + +## Custom Macros + +It's easy to define your own custom HTML class helpers called "macros". Here's how it works. First, simply register the macro with a given name and a Closure: + +#### Registering a HTML macro: + + HTML::macro('my_element', function() + { + return '
'; + }); + +Now you can call your macro using its name: + +#### Calling a custom HTML macro: + + echo HTML::my_element(); diff --git a/views/pagination.md b/views/pagination.md new file mode 100644 index 0000000..dee5dec --- /dev/null +++ b/views/pagination.md @@ -0,0 +1,104 @@ +# Pagination + +## Contents + +- [The Basics](#the-basics) +- [Using The Query Builder](#using-the-query-builder) +- [Appending To Pagination Links](#appending-to-pagination-links) +- [Creating Paginators Manually](#creating-paginators-manually) +- [Pagination Styling](#pagination-styling) + + +## The Basics + +Laravel's paginator was designed to reduce the clutter of implementing pagination. + + +## Using The Query Builder + +Let's walk through a complete example of paginating using the [Fluent Query Builder](/docs/database/fluent): + +#### Pull the paginated results from the query: + + $orders = DB::table('orders')->paginate($per_page); + +#### Display the results in a view: + + results as $order): ?> + id; ?> + + +#### Generate the pagination links: + + links(); ?> + +The links method will create an intelligent, sliding list of page links that looks something like this: + + Previous 1 2 ... 24 25 26 27 28 29 30 ... 78 79 Next + +The Paginator will automatically determine which page you're on and update the results and links accordingly. + +It's also possible to generate "next" and "previous" links: + +#### Generating simple "previous" and "next" links: + + previous().' '.$orders->next(); ?> + +*Further Reading:* + +- *[Fluent Query Builder](/docs/database/fluent)* + + +## Appending To Pagination Links + +You may need to add more items to the pagination links' query strings, such as the column your are sorting by. + +#### Appending to the query string of pagination links: + + appends(array('sort' => 'votes'))->links(); + +This will generate URLs that look something like this: + + http://example.com/something?page=2&sort=votes + + +## Creating Paginators Manually + +Sometimes you may need to create a Paginator instance manually, without using the query builder. Here's how: + +#### Creating a Paginator instance manually: + + $orders = Paginator::make($orders, $total, $per_page); + + +## Pagination Styling + +All pagination link elements can be styled using CSS classes. Here is an example of the HTML elements generated by the links method: + + + +When you are on the first page of results, the "Previous" link will be disabled. Likewise, the "Next" link will be disabled when you are on the last page of results. The generated HTML will look like this: + + Previous \ No newline at end of file diff --git a/views/templating.md b/views/templating.md new file mode 100644 index 0000000..95582c2 --- /dev/null +++ b/views/templating.md @@ -0,0 +1,153 @@ +# Templating + +## Contents + +- [The Basics](#the-basics) +- [Sections](#sections) +- [Blade Template Engine](#blade-template-engine) +- [Blade Layouts](#blade-layouts) + + +## The Basics + +Your application probably uses a common layout across most of its pages. Manually creating this layout within every controller action can be a pain. Specifying a controller layout will make your develompent much more enjoyable. Here's how to get started: + +#### Specify a "layout" property on your controller: + + class Base_Controller extends Controller { + + public $layout = 'layouts.common'; + + } + +#### Access the layout from the controllers' action: + + public function action_profile() + { + $this->layout->nest('content', 'user.profile'); + } + +> **Note:** When using layouts, actions do not need to return anything. + + +## Sections + +View sections provide a simple way to inject content into layouts from nested views. For example, perhaps you want to inject a nested view's needed JavaScript into the header of your layout. Let's dig in: + +#### Creating a section within a view: + + + + + +#### Rendering the contents of a section: + + + + + +#### Using Blade short-cuts to work with sections: + + @section('scripts') + + @endsection + + + @yield('scripts') + + + +## Blade Template Engine + +Blade makes writing your views pure bliss. To create a blade view, simply name your view file with a ".blade.php" extension. Blade allows you to use beautiful, unobtrusive syntax for writing PHP control structures and echoing data. Here's an example: + +#### Echoing a variable using Blade: + + Hello, {{$name}}. + +#### Rendering a view: + +

Profile + + @include('user.profile') + +> **Note:** When using the **@include** Blade expression, the view will automatically inherit all of the current view data. + +#### Creating loops using Blade: + +

Comments

+ + @foreach ($comments as $comment) + The comment body is {{$comment->body}}. + @endforeach + +#### Other Blade control structures: + + @if (count($comments) > 0) + I have comments! + @else + I have no comments! + @endif + + @for ($i =0; $i < count($comments) - 1; $i++) + The comment body is {{$comments[$i]}} + @endfor + + @while ($something) + I am still looping! + @endwhile + +#### The "for-else" control structure: + + @forelse ($posts as $post) + {{ $post->body }} + @empty + There are not posts in the array! + @endforelse + + +## Blade Layouts + +Not only does Blade provide clean, elegant syntax for common PHP control structures, it also gives you a beautiful method of using layouts for your views. For example, perhaps your application uses a "master" view to provide a common look and feel for your application. It may look something like this: + + + + +
+ @yield('content') +
+ + +Notice the "content" section being yielded. We need to fill this section with some text, so let's make another view that uses this layout: + + @layout('master') + + @section('content') + Welcome to the profile page! + @endsection + +Great! Now, we can simply return the "profile" view from our route: + + return View::make('profile'); + +The profile view will automatically use the "master" template thanks to Blade's **@layout** expression. + +Sometimes you may want to only append to a section of a layout rather than overwrite it. For example, consider the navigation list in our "master" layout. Let's assume we just want to append a new list item. Here's how to do it: + + @layout('master') + + @section('navigation') + @parent +
  • Nav Item 3
  • + @endsection + + @section('content') + Welcome to the profile page! + @endsection + +Notice the **@parent** Blade construct? It will be replaced with the contents of the layout's navigation section, providing you with a beautiful and powerful method of performing layout extension and inheritance. \ No newline at end of file