laravel 4将ip地址保存到模型中

时间:2013-07-22 19:10:58

标签: laravel ip laravel-4

我正在尝试使用Laravel 4将用户IP地址保存到我的数据库。 我发现以下函数返回一个字符串

Request::getClientIp()

我如何将它存储在我的模型中?只是一个字符串或是否有更有效的方式?

$table->string('ip_address');

3 个答案:

答案 0 :(得分:41)

选项1:使用VARCHAR(45)列

考虑到另一个SO问题Maximum length of the textual representation of an IPv6 address?中的讨论,在包含IPv4隧道功能时,IPv6的最大长度为45。

因此,更安全的迁移命令将是:

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

优点:

  1. 该列是人类可读的。设置值或查询行以供查看时无需转换。
  2. 缺点:

    1. 它比选项2使用更多的空间,实际上几乎是它的3倍。但除非你计划有数百万行,否则我不会太担心。

    2. 选项2:使用BLOB列

      由于@euantorano提供了IP address storing in mysql database的链接,您可以将IP存储为二进制以节省一些空间。

      最简单的答案是使用:

      $table->binary('ip_address');
      

      优点:

      1. 以二进制形式存储IP地址可以节省一些空间。
      2. 缺点:

        1. 您需要先使用PHP inet_pton()等内容将IP地址字符串转换为二进制。该列不能直接读取,因为它以二进制格式存储。如果尝试直接查询,您将看到奇怪的字符或空白。您可能希望查看我在以下选项3中存储和检索IP地址的方式。

        2. Laravel中的查询构建器,尽管该方法被称为二进制,但实际上create a BLOB column将为您提供。 BLOB is stored off the tableout of the row buffer可能意味着性能较低。并且没有理由不使用BINARY列类型,因为我们知道IP地址对于BLOB来说并不是那么长。


        3. 选项3:使用VARBINARY(16)列

          Laravel的查询构建器为选项2中的示例生成BLOB列。如果您使用的是MySQL,则需要使用VARBINARY(16)而不是BLOB来获得更好的性能。

          迁移脚本:

          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');
              }
          }
          

          显然,上面唯一重要的部分是DB :: statement(...)。我们需要将原始查询用作Taylor Otwell suggested。随意按照自己的方式创建其余的表格。

          从这里你可以使用PHP的inet_pton()inet_ntop()将IP地址字符串转换为二进制,反之亦然。

          <强>优点:

          1. 与选项1相比节省空间
          2. 与选项2相比,DB性能更佳
          3. <强>缺点:

            1. 与选项2一样,您需要在二进制和人类可读的字符串之间来回手动转换,或者使用Eloquent模型和一对自定义存取器/ mutator,我将在下面演示。

            2. 额外信用:添加自定义Eloquent访问者/ mutator(可选):

              这是我发现Eloquent非常有用的地方。您可以将自己的访问者/变异者设置为您的Eloquent模型,您可以像往常一样通过模型的实例变量获取/设置。

              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);
                  }
              }
              

              现在,如果你这样做:

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

              IP地址将正确保存为二进制。你可以这样做:

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

              它将回显192.168.0.1。非常有用!

答案 1 :(得分:1)

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

因为IPv6地址的最大长度为39。

支持IPv4,因为它的长度不超过15。

答案 2 :(得分:0)

来自@Unnawut。

如果要在同一字段中处理ipv4和ipv6,则需要从binary(16)更改为varbinary(16)

但如果你只需要处理ip v4 INT UNSIGNED

如果您只想处理ip v6 BINARY(16)

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

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