Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

laravel 4 saving ip address to model

I'm trying to save a user ip address to my database using Laravel 4. I found the following function which returns a string

Request::getClientIp()

How would I store this in my model? Just a string or is there a more efficient way?

$table->string('ip_address');
like image 599
user391986 Avatar asked Jul 22 '13 19:07

user391986


2 Answers

Option 1: Use VARCHAR(45) column

Considering the discussion in another SO question Maximum length of the textual representation of an IPv6 address?, the maximum length of IPv6 is 45 when including the IPv4 tunneling feature.

Thus, a safer migration command would be:

$table->string('ip_address', 45);

Pros:

  1. The column is human-readable. No need for conversions when setting the value or querying the row out for viewing.

Cons:

  1. It uses more space than Option 2, almost 3 times larger in fact. But I wouldn't worry much unless you are planning it have millions of rows.

Option 2: Use BLOB column

As @euantorano provided the link to IP address storing in mysql database, you may store the IP as binary to save some space.

The simplest answer would be to use:

$table->binary('ip_address');

Pros:

  1. Store IP addresses in binary will save you some space.

Cons:

  1. You will need to convert the IP address string to binary first using something like PHP's inet_pton(). The column will not be directly readable since it is stored in binary format. You will see weird characters or blank if tried to query it out directly. You may want to look at my way to store and retrieve the IP address in Option 3 below.

  2. The query builder in Laravel, despite the method being called binary, will actually create a BLOB column for you. BLOB is stored off the table, out of the row buffer, which possibly means a lower performance. And there really isn't a reason not to use BINARY column type since we know IP addresses aren't that long for BLOB to be necessary.


Option 3: Use VARBINARY(16) column

Laravel's query builder produces a BLOB column for the example in Option 2. If you are using MySQL, you will want to use VARBINARY(16) instead of BLOB for better performance.

Migration script:

class CreateMyLogsTable extends Migration {

    public function up()
    {
        Schema::create('my_logs', function(Blueprint $table) {
            $table->increments('id');
        });

        DB::statement('ALTER TABLE `my_logs` ADD `ip_address` VARBINARY(16)');
    }

    public function down()
    {
        DB::statement('ALTER TABLE `my_logs` DROP COLUMN `ip_address`');

        Schema::drop('my_logs');
    }
}

Obviously the only important part above is the DB::statement(...). We need to use raw queries as Taylor Otwell suggested. Feel free to create the rest of the table your way.

From here you can use PHP's inet_pton() and inet_ntop() to convert the IP address strings to binary and vice versa.

Pros:

  1. Saves space compared to Option 1
  2. Better DB performance compared to Option 2

Cons:

  1. Like Option 2, you need to either manually convert back and forth between binary and human-readable string, or use Eloquent model with a pair custom accessor/mutator which I will demonstrate below.

Extra credit: Add custom Eloquent accessor/mutator (optional):

Here is where I find Eloquent really useful. You can set your own accessor/mutator to your Eloquent model and you can get/set via your model's instance variable as usual.

class MyLog extends Eloquent {

    public $timestamps = false;

    public function getIpAddressAttribute($value)
    {
        return inet_ntop($value);
    }

    public function setIpAddressAttribute($value)
    {
        $this->attributes['ip_address'] = inet_pton($value);
    }
}

Now if you do:

$log = new MyLog;
$log->ip_address = '192.168.0.1';
$log->save();

The IP address will be saved as binary correctly. And you can do:

$log = MyLog::find(1);
echo $log->ip_address;

And it will echo out 192.168.0.1. Very useful!

like image 164
Unnawut Avatar answered Nov 17 '22 12:11

Unnawut


$table->string('ip_address', 39); 

Because the maximum length of an IPv6 address is 39.

IPv4 will be supported as it's length doesn't exceeds 15.

like image 1
yassine Avatar answered Nov 17 '22 12:11

yassine