laravel 4 saving ip address to model

后端 未结 3 889
一个人的身影
一个人的身影 2020-12-28 19:11

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()


        
相关标签:
3条回答
  • 2020-12-28 19:26
    $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.

    0 讨论(0)
  • 2020-12-28 19:28

    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!

    0 讨论(0)
  • 2020-12-28 19:30

    From @Unnawut.

    You need to change from binary(16) to varbinary(16) if you want to deal with both ipv4 and ipv6 in the same field.

    But if you need to deal only ip v4 just INT UNSIGNED

    If you want to deal only ip v6 BINARY(16)

    ref: MYSQL - SELECT IP v4/v6, inet_pton & bin2hex

    ref2: https://stackoverflow.com/a/5133610/2126472

    0 讨论(0)
提交回复
热议问题