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

use*_*986 13 ip laravel laravel-4

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

Request::getClientIp()
Run Code Online (Sandbox Code Playgroud)

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

$table->string('ip_address');
Run Code Online (Sandbox Code Playgroud)

Unn*_*wut 41

选项1:使用VARCHAR(45)列

考虑在另一个SO问题中讨论IPv6地址的文本表示的最大长度?,包含IPv4隧道特性时,IPv6的最大长度为45.

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

$table->string('ip_address', 45);
Run Code Online (Sandbox Code Playgroud)

优点:

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

缺点:

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

选项2:使用BLOB列

由于@euantorano提供了存储在mysql数据库中的IP地址的链接,因此您可以将IP存储为二进制以节省一些空间.

最简单的答案是使用:

$table->binary('ip_address');
Run Code Online (Sandbox Code Playgroud)

优点:

  1. 以二进制形式存储IP地址将为您节省一些空间.

缺点:

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

  2. Laravel中的查询构建器,尽管该方法被称为二进制,但实际上将为您创建一个BLOB列.BLOB存储在表外,从行缓冲区中存储,这可能意味着性能较低.并且确实没有理由不使用BINARY列类型,因为我们知道IP地址不需要那么长的BLOB.


选项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');
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,上面唯一重要的部分是DB :: statement(...).我们需要像Taylor Otwell建议的那样使用原始查询.随意创建表格的其余部分.

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

优点:

  1. 与选项1相比节省空间
  2. 与选项2相比,DB性能更佳

缺点:

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

额外功劳:添加自定义Eloquent accessor/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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果你这样做:

$log = new MyLog;
$log->ip_address = '192.168.0.1';
$log->save();
Run Code Online (Sandbox Code Playgroud)

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

$log = MyLog::find(1);
echo $log->ip_address;
Run Code Online (Sandbox Code Playgroud)

并且它将回显192.168.0.1.很有用!


小智 1

$table->string('ip_address', 39); 
Run Code Online (Sandbox Code Playgroud)

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

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