KodeInfo | Learning resources for web and mobile development

Eloquent ORM in Laravel

December 13th, 2014 16:17:01 by Imran Iqbal Comments(0) - Views(6186)

In our previous tutorials we have learned how to configure database and how we can use the schema builder to structure tables within our database. But to insert data we have to write SQL queries using the data object. But what if we  don't need to write SQL query and everything will be taken care by ORM. This functionality is provided by object relational mappers or simply 'ORM'sORMs  can be used to allow us to map our application objects to database tables, and individual instances of these objects as rows. 

Laravel ships with its own ORM component called 'Eloquent'. Let's learn more about Eloquent by tackling these actions in order. 

  • C - Creating a new row 
  • R - Reading existing rows
  • U -  Updating existing rows
  • D - Deleting  existing rows

Creating new models

Before we start building a new model, let's build a table name called 'games' using schema builder and migrations like below.

php artisan migrate:make create_games

When we ran above artisan command in interface it will create a new migration called create_games with the present timestamp like below. We will add our columns to the migration.

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateGames extends Migration {

	/**
	 * Run the migrations.
	 *
	 * @return void
	 */
	public function up()
	{
		Schema::create('games' , function($table){

				$table->increments('id');
				$table->string('name', 128);
				$table->text('description');
		});
	}

	/**
	 * Reverse the migrations.
	 *
	 * @return void
	 */
	public function down()
	{
		Schema::drop('games');
	}

}

If you notice we named our table games so our Eloquent model name will be Game. Eloquent is clever by default it will look for plural form of the model name to store our objects instances. This behaviour can be overridden but now we will go now like this.

Let run the migration to update the database.

php artisan migrate make
Migration table created successfully.
Migrated: 2014_12_13_161931_create_games

Now let's create a new Eloquent model to represent our games

// app/models/Game.php

class Game extends Eloquent
{

}

Now Eloquent model was ready and let's create a new game using our new model.

// app/routes.php

Route::get('/', function()
{
	$game = new Game;
	$game->name = 'Game of Thrones';
	$game->description = 'It is a game of seven kingdoms';
	$game->save();
});

We created new instance of our Game model and set its public attributes, which map to table columns, to the values that we require. When we are done, we simply call the save() method on the object to persist the data in a new row.

Let's visit the route to save new row in database using the model which recently created. It won't return however, we received an error here.

Column not found: 1054 Unknown column 'update_at' in field list ..............

It's because Eloquent attempts to populate the updated_at  and created_at columns of our table with the current time. This is because it's expects us to add ->timestamps() method in schema builder. To disable automatic timestamps updates with Eloquent models, just add a new public attribute to Game model.

// app/models/Game.php

class Game extends Eloquent
{
	public $timestamps = false;
}

Now let's go again to our route and now this time it will create a new row in our table games with out giving any error. Suppose if we want to add timestamps()  to our table. it's bad to change manually our database schema, so let's create another migration to change our table schema.

php artisan migrate:make add_timestamps_to_games
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddTimestampsToGames extends Migration {

	/**
	 * Run the migrations.
	 *
	 * @return void
	 */
	public function up()
	{
		Schema::table('games', function($table){

			$table->timestamps();
		});
	}

	/**
	 * Reverse the migrations.
	 *
	 * @return void
	 */
	public function down()
	{
		Schema::table('games', function($table){

			$table->dropColumns('updated_at', 'created_at');
		});
	}

}

Now in the new migration we added timestamps() to our table games, and also let's change the public timestamp attribute in our model Game to true. 

php artisan migrate 

// app/models/Game.php

class Game extends Eloquent
{
	public $timestamps = true;
}

Now let's execute our route once again, if you observe our database table. You see a new row with updated_at and created-at columns with timestamps.

Suppose if you want to change your table name from plural name of your model you can change it in your model by creating a new public attribute with name table like below.

// app/models/Game.php

class Game extends Eloquent
{
	public $table = game;
}

Reading Existing Models

Now let's find our how can we read existing rows once after we inserted using save() method using Eloquent in the previous section. But for now we will use find() method to find a specific model instance from the database by its id column. 

// app/routes.php

Route::get('/', function()
{
	$game = Game::find(1);
	return $game->name;
});

We can retrieve all the games using a method called all().

Route::get('/', function()
{
	$game = Game::all();
});

There are lot of other options also to read existing rows from database using model instance.

Updating Existing Models

To update a particular row data using the model instance we have to find first the row using find() method and then we have to use that instance to update the data in the existing row like below,

// app/routes.php

Route::get('/', function()
{
	$game = Game::find(1);
	$game->name = 'Game of Thrones';
	$game->description = 'It is a game of seven kingdoms';
	$game->save();
});

Deleting Existing Rows

To delete the existing rows also first we have to find that particular row using model instance and then we have to use that instance to delete that row.

// app/routes.php

Route::get('/', function()
{
	$game = Game::find(1);
	$game->delete();

});

To delete single row or multiple rows at a single time we can also use another method called destroy() like below.

// app/routes.php

Route::get('/', function()
{
	Game::destroy(1);
        Game::destroy(2,3,4);

});   

Query Scopes

Query scopes can be useful if you find yourself repeating the same queries over and over again. Let's explain with some example.

Roue::get('/', function()
{

 return Game::where('name', 'LIKE', '....%')->get();
});

Suppose if we are repeating this query in different situations we can make this as one method in our model Game and then we can use it like below.

class Game extends Eloquent
{
	public $timestamps = false;

       public function getNames($query)
       {

           return $query::where('name', 'LIKE', '....%')->get();
       }
}

Let's switch back to our route to use the newly created scope method.

Roue::get('/', function()
{

    return Game::getNames()->get();
});

Let's assume our table has lots of data to explain some query methods. Before that let's explain the output types of our model instances.

Roue::get('/', function()
{
   $game = Game::find(1);
   return $game;  // json output
});
Roue::get('/', function()
{
   $games = Game::all();
   foreach($gmaes as $game) { echo $game->name; } //array
});
Roue::get('/', function()
{
   $games = Game::all();
   var_dump($games); //object
});

let's see different fetch methods while getting rows from database using our model instance.

Roue::get('/', function()
{
   Game::first(); //returns first row
   Game::where('name', '=' ,'Cricket')->get(); //returns rows where constraints meets
   Game::where('name', '=' ,'Cricket')->get(array('id','name'); //returns specific columsn fromresult rows
   Game::lists('name'); //returns all rows values for spcific column
   Game::first()->toSql(); //converts to sql query
   Game::truncate(); //to delete all rows
   Game::where('name', '=' ,'Cricket')->delete(); //deletes specific row
   Game::take(2)->get(); //returns only two rows
   Game::take(2)->skip(2)->get(); //sets offset while pciking limited rows
});

There are lot of other query methods which will be useful for query building please take a look at them in laravel docs. Thanks for reading this tutorial.

Thanks

Kode Info

Author

  • Imran Iqbal
    Imran Iqbal

    Imran is a web developer and consultant from India. He is the founder of KodeInfo, the PHP and Laravel Community . In the meantime he follows other projects, works as a freelance backend consultant for PHP applications and studies IT Engineering . He loves to learn new things, not only about PHP or development but everything.

Related

WHY USE A FRAMEWORK OVER PLAIN PHP

WHY USE A FRAMEWORK OVER PLAIN PHP
read more

GETTING STARTED WITH LARAVEL

GETTING STARTED WITH LARAVEL
read more

UNDERSTANDING LARAVEL STRUCTURE

UNDERSTANDING LARAVEL STRUCTURE
read more

UNDERSTANDING LARAVEL ROUTES

UNDERSTANDING LARAVEL ROUTES
read more

comments powered by Disqus