在Laravel 4中将IP地址保存到模型中。
在Laravel 4中将IP地址保存到模型中。
我正在尝试使用Laravel 4将用户IP地址保存到数据库中。
我找到了下面的函数,它返回一个字符串
Request::getClientIp()
我应该如何在我的模型中存储它?只是一个字符串还是有更高效的方法?
$table->string('ip_address');
选项1:使用VARCHAR(45)列
考虑另一个SO问题中的讨论一个IPv6地址的文本表示的最大长度是多少?,包括IPv4隧道功能时IPv6的最大长度为45。
因此,一个更安全的迁移命令将是:
$table->string('ip_address', 45);
优点:
- 该列是可读的,无需进行转换,即可设置值或查询行以查看。
缺点:
- 它比选项2使用更多的空间,事实上几乎要大3倍。 但是,除非您计划拥有数百万行否则不用太担心。
选项2:使用BLOB列
正如@euantorano提供的存储在mysql数据库中的IP地址链接所述,您可以将IP存储为二进制以节省一些空间。
最简单的答案是使用:
$table->binary('ip_address');
优点:
- 以二进制形式存储IP地址将为您节省一些空间。
缺点:
- 您将需要首先使用类似PHP inet_pton()的工具将IP地址字符串转换为二进制。由于以二进制格式存储,因此该列将无法直接读取。如果尝试直接查询,您将看到奇怪的字符或空白。您可能想看看我在选项3中存储和检索IP地址的方法。
-
Laravel中的查询构建器,尽管调用的方法为“binary”,但实际上会为您创建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地址字符串转换为二进制或将二进制转换为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。非常实用!