{"id":678,"date":"2014-06-24T18:05:17","date_gmt":"2014-06-24T18:05:17","guid":{"rendered":"http:\/\/blog.silverterra.net\/?p=678"},"modified":"2014-06-24T19:18:05","modified_gmt":"2014-06-24T19:18:05","slug":"get-the-client-geo-location-based-on-ip-address","status":"publish","type":"post","link":"https:\/\/blog.silverterra.net\/?p=678","title":{"rendered":"Get the client country based on ip address"},"content":{"rendered":"<blockquote><p>Goal: find the client on the map<\/p><\/blockquote>\n<p>I was supprised when I examined my server&#8217;s stat. There were many client from unknown country. This is not too good. I remember an old solution depends on ip2c database. This is nice and easy, but to keep the database updated not too confortable.<\/p>\n<p><strong>1. database solution<\/strong><\/p>\n<p>I have a simple table (ta_ip2c) with the ip2c data,<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"\/wp-content\/uploads\/2014\/06\/ip2c.jpg\" alt=\"ip2c\" width=\"535\" height=\"212\" class=\"alignnone size-full wp-image-680\" srcset=\"https:\/\/blog.silverterra.net\/wp-content\/uploads\/2014\/06\/ip2c.jpg 535w, https:\/\/blog.silverterra.net\/wp-content\/uploads\/2014\/06\/ip2c-300x118.jpg 300w\" sizes=\"auto, (max-width: 535px) 100vw, 535px\" \/><\/p>\n<p>and I can read the data width a simple select:<\/p>\n<pre data-enlighter-language=\"sql\" class=\"EnlighterJSRAW\">\r\nSELECT * FROM ta_ip2c WHERE $ip_num BETWEEN begin_ip_num AND end_ip_num;\r\n<\/pre>\n<p>$ip_num is the converted ip <code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">$ip_num = ip2long($ip)<\/code><\/p>\n<p><strong>2. online solution (<a href=\"http:\/\/ip2c.org\/\" target=\"_blank\">ip2c.org<\/a>)<\/strong><br \/>\nThe method is the same but no local database. Just ask the server like this:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\n\/*\r\nhttp:\/\/ip2c.org\/?ip=XXX.XXX.XXX.XXX or http:\/\/ip2c.org\/XXX.XXX.XXX.XXX\r\nsample call\r\n*\/\r\n$ip = '89.168.70.220'; \/\/or any other IP here\r\n$s = file_get_contents('http:\/\/ip2c.org\/'.$ip);\r\nswitch($s[0])\r\n{\r\n  case '0':\r\n    echo 'Something wrong';\r\n    break;\r\n  case '1':\r\n    $reply = explode(';',$s);\r\n    echo '&lt;br&gt;Two-letter: '.$reply[1];\r\n    echo '&lt;br&gt;Three-letter: '.$reply[2];\r\n    echo '&lt;br&gt;Full name: '.$reply[3];\r\n    break;\r\n  case '2':\r\n    echo 'Not found in database';\r\n    break;\r\n}\r\n<\/pre>\n<p>The output is very simple:<\/p>\n<pre data-enlighter-language=\"js\" class=\"EnlighterJSRAW\">\r\n0;;;WRONG INPUT\r\n|\r\n+ your request has not been processed due to invalid syntax\r\n    |\r\n    + e.g. bad IPv4 like 300.400.abc.256\r\n    + e.g. bad decimal like 2a3b4c or bigger than MAX_INT\r\n\r\n\r\n1;CD;COD;COUNTRY\r\n|\r\n+ contains two-letter (ISO 3166) and three-letter country codes, and a full country name\r\n+ country name may be multi-word and contain spaces\r\n+ e.g. we take your IP:\r\n    |\r\n    + URL looks like this:  http:\/\/ip2c.org\/?ip=89.168.70.220\r\n    |                       or\r\n    |                       http:\/\/ip2c.org\/89.168.70.220\r\n    |\r\n    + resulting string is:  1;GB;GBR;United Kingdom\r\n\r\n\r\n2;;;UNKNOWN\r\n|\r\n+ given ip\/dec not found in database or not yet physically assigned to any country\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Goal: find the client on the map I was supprised when I examined my server&#8217;s stat. There were many client from unknown country. This is not too good. I remember an old solution depends on ip2c database. This is nice and easy, but to keep the database updated not too confortable. 1. database solution I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,5],"tags":[],"class_list":["post-678","post","type-post","status-publish","format-standard","hentry","category-php","category-web-trick"],"_links":{"self":[{"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/posts\/678","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=678"}],"version-history":[{"count":15,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/posts\/678\/revisions"}],"predecessor-version":[{"id":694,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/posts\/678\/revisions\/694"}],"wp:attachment":[{"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=678"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=678"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=678"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}