我正在尝试使用 Laravel 4 将用户 ip 地址保存到我的数据库中。我发现以下函数返回一个字符串
Request::getClientIp()
我将如何将其存储在我的模型中?只是一个字符串还是有更有效的方法?
$table->string('ip_address');
选项 1:使用 VARCHAR(45) 列
考虑另一个 SO 问题中的讨论IPv6 地址的文本表示的最大长度?,包含 IPv4 隧道功能时,IPv6 的最大长度为 45。
因此,更安全的迁移命令是:
$table->string('ip_address', 45);
优点:
缺点:
选项 2:使用 BLOB 列
由于@euantorano 提供了存储在 mysql 数据库中的 IP 地址的链接,您可以将 IP 存储为二进制文件以节省一些空间。
最简单的答案是使用:
$table->binary('ip_address');
优点:
缺点:
您需要先使用 PHP 的inet_pton()之类的东西将 IP 地址字符串转换为二进制。该列将无法直接读取,因为它以二进制格式存储。如果尝试直接查询,您将看到奇怪的字符或空白。您可能想看看我在下面的选项 3 中存储和检索 IP 地址的方式。
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');
}
}
显然,上面唯一重要的部分是 DB::statement(...)。我们需要使用Taylor Otwell 建议的原始查询。随意按照自己的方式创建表格的其余部分。
从这里您可以使用 PHP 的inet_pton()和inet_ntop()将 IP 地址字符串转换为二进制,反之亦然。
优点:
缺点:
额外功劳:添加自定义 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。很有用!
$table->string('ip_address', 39);
因为 IPv6 地址的最大长度是 39。
支持 IPv4,因为它的长度不超过 15。
来自@Unnawut。
如果要在同一字段中同时处理 ipv4 和 ipv6,则需要从 更改为binary(16)
。varbinary(16)
但是如果你只需要处理 ip v4 就可以了INT UNSIGNED
如果你只想处理 ip v6BINARY(16)