laravel 4将IP地址保存到模型

Posted

技术标签:

【中文标题】laravel 4将IP地址保存到模型【英文标题】:laravel 4 saving ip address to model 【发布时间】:2013-07-21 15:45:45 【问题描述】:

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

Request::getClientIp()

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

$table->string('ip_address');

【问题讨论】:

看看这个相关的问题:***.com/questions/6427786/… 谢谢!我正在考虑 VARBINARY 但我在模式构建器中找不到这种类型,它与 $table->binary('data'); 是一样的吗? ? four.laravel.com/docs/schema 看起来它只是一个二进制列而不是 VARBINARY:laravel.com/api/… - 测试它并查看它可能是个好主意。 【参考方案1】:

选项 1:使用 VARCHAR(45) 列

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

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

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

优点:

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

缺点:

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

选项 2:使用 BLOB 列

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

最简单的答案是使用:

$table->binary('ip_address');

优点:

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

缺点:

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

    尽管方法被称为二进制,Laravel 中的查询构建器实际上会为您提供create a BLOB column。 BLOB is stored off the table、out of the row buffer,可能意味着性能较低。而且确实没有理由不使用 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');
    

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

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

优点:

    与选项 1 相比节省空间 与选项 2 相比,数据库性能更好

缺点:

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

额外功劳:添加自定义 Eloquent 访问器/修改器(可选):

这是我发现 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。很有用!

【讨论】:

使用提供的步骤,它将 IP 地址作为长二进制文件插入,并在从数据库中获取它时返回 7f00:1::。发送到数据库的 IP 是127.0.0.1。使用您的 192.168.0.1 示例返回 c0a8:1:: 这是使用选项 3。 @davidxd333 感谢您强调这一点。这是因为 BINARY 在存储时会将零填充到 IPv4 地址。正如 Kanin Peanviriyakulkit 在下面的另一个答案中提到的那样,我们确实需要使用 VARBINARY 而不是 BINARY。我已经修改了对 VARBINARY 的回答。 down方法中的DB::statement(...)有必要吗? @MattPotts 不,因为您已经删除了整个表格行【参考方案2】:
$table->string('ip_address', 39); 

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

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

【讨论】:

【参考方案3】:

来自@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://***.com/a/5133610/2126472

【讨论】:

对!感谢您指出了这一点。很高兴在 SO 上看到熟悉的名字! :D 啊!也很高兴见到你。

以上是关于laravel 4将IP地址保存到模型的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5.5 中的用户 IP 地址和位置

根据 IP 地址将位置保存到数据库

如何将IP地址保存在数据库中[关闭]

如何使用 Spring 安全性将 IP 地址从经过身份验证的用户保存到数据库?

Laravel 路由中的 IP 地址显示 404

如何使用 GeoIP2() django 模型从 IP 地址调用中提取保存的信息以显示在我的 html 中