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地址保存到模型的主要内容,如果未能解决你的问题,请参考以下文章