I am trying to use GeoIP2 PHP API ( https://github.com/maxmind/GeoIP2-php ) within CodeIgniter. How can I load GeoIP2 and use it for user geolocation?
I have tried loading it like this:
$this->load->library("GeoIp2/Database/Reader");
or
require APPPATH . "libraries/GeoIp2/ProviderInterface.php";
require APPPATH . "libraries/GeoIp2/Database/Reader.php";
or
$this->load->file("GeoIp2/ProviderInterface");
$this->load->library("GeoIp2/Database/Reader");
I get this error: "Unable to load the requested file: ProviderInterface"
I have looked this Namespace in PHP CodeIgniter Framework , but i have little experience with namespaces.
No success with this, I am not winning, I really do not know how to implement this within CodeIgniter.
I was trying to find the solution of this question. But couldn't find on stackoverflow. I am writing my own code here. Maybe, it will be helpful for someone. I have added a new function in my utility_helper.php file :
function get_ip_country_code($ip_address) {
require APPPATH .'third_party/GeoIP2/autoload.php';
$reader = new GeoIp2\Database\Reader(FCPATH.'public/geoip/GeoIP2-Country.mmdb');
$record = $reader->country($ip_address);
return $record->country->isoCode;
}
I put the GeoIP2 library in the third_party folder and put the mmdb file in the public folder. It works fine for me. I hope it will save someone's time :)
The GeoIp2 php sdk takes advantage of PHP's namespace feature, which the CodeIgniter framework does not support, which is why you're getting the error when you try to load the library. The post you linked to offers a solution using spl_autoload, however I do not use CodeIgniter and haven't tested it with the GeopIp2 php sdk.
Few ways you can embed this within CodeIgniter.
First, you need to include it within the script:
require_once( 'GeoIp2/vendor/autoload.php' );
use GeoIp2\Database\Reader;
Next, I call Reader() for the detection methods
$reader = new Reader('GeoIp2/GeoIP2-City.mmdb');
$record = $reader->city($ip);
// Country (code)
$record->country->isoCode;
// State
$record->mostSpecificSubdivision->name;
// City
$record->city->name;
// zip code
$record->postal->code;
I just tested this on CodeIgniter 3x and works.
I used a bridge class. Inside /application/libraries create a file called CI_GeoIp2.php and add the following code.
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* GeoIp2 Class
*
* #package CodeIgniter
* #subpackage Libraries
* #category GeoIp2
* #author Timothy Marois <timothymarois#gmail.com>
*/
require_once( APPPATH . 'third_party/GeoIp2/vendor/autoload.php' );
use GeoIp2\Database\Reader;
class CI_GeoIp2 {
protected $record;
protected $database_path = 'third_party/GeoIp2/GeoIP2-City.mmdb';
public function __construct() {
$ci =& get_instance();
$reader = new Reader(APPPATH.$this->database_path);
$ip = $ci->input->ip_address();
if ($ci->input->valid_ip($ip)) {
$this->record = $reader->city($ip);
}
log_message('debug', "CI_GeoIp2 Class Initialized");
}
/**
* getState()
* #return state
*/
public function getState() {
return $this->record->mostSpecificSubdivision->name;;
}
/**
* getState()
* #return country code "US/CA etc"
*/
public function getCountryCode() {
return $this->record->country->isoCode;
}
/**
* getCity()
* #return city name
*/
public function getCity() {
return $this->record->city->name;
}
/**
* getZipCode()
* #return Zip Code (#)
*/
public function getZipCode() {
return $this->record->postal->code;
}
/**
* getRawRecord()
* (if you want to manually extract objects)
*
* #return object of all items
*/
public function getRawRecord() {
return $this->record;
}
}
Now you can either autoload or load it up using
$this->load->library("CI_GeoIp2");
I prefer to autoload it like this under autoload.php config
$autoload['libraries'] = array('CI_GeoIp2'=>'Location');
So within the script I use,
$this->Location->getState()
$this->Location->getCity()
... and so on
Related
In Laravel I need to communicate to a 3rd party API. Thay have given me some PHP implementation (class) which I can use to connect and communicate with their API.
But when I try this as a class in a subfolder of the App folder and add this to my controller, I get a class not found error.
I have added a folder 'Qenner' (the provider of the API) in the App folder. And copied their classes in there.
In my controller I'm using these classes and add a code sample, like they send it to me.
Controller code (API-KEY is replaced with the actual key):
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Qenner\Search;
use QennerSearch\ServiceClient;
class TestController extends Controller
{
public function index() {
$search = new Search('https://search.qenner.com', 'API-KEY', true, 'nl-NL');
$response = $search->getCriteria([], ['Country'], []);
if (!$response->isError()) {
$criterionSets = $response->getCriterionSets();
$countryCriterionSet = criterionSets[0];
$countries = $countryCriterionSet->getCriteria();
$resultCount = $response->getResultCount();
}
dd($response);
}
Search.php in Qenner folder:
/**
* #file
* Contains QennerSearch\Search.
*/
namespace QennerSearch;
use QennerSearch\model\messages\CriterionTypesResponse;
use QennerSearch\model\messages\CriteriaRequest;
use QennerSearch\model\messages\CriteriaResponse;
use QennerSearch\model\messages\ErrorResponse;
use QennerSearch\model\messages\SearchRequest;
use QennerSearch\model\messages\SearchResponse;
use QennerSearch\model\messages\PriceRequest;
use QennerSearch\model\messages\PriceResponse;
use QennerSearch\model\messages\AccommodationInfoRequest;
use QennerSearch\model\messages\AccommodationInfoResponse;
use QennerSearch\model\messages\AutoCompleteRequest;
use QennerSearch\model\messages\AutoCompleteResponse;
/**
* Class Search, using ServiceClient to communicate, implementing the SearchInterface
*
* #package QennerSearch
*/
class Search extends ServiceClient implements SearchInterface {
.....
The folder has a ServiceClient.php
ServiceClient.php
/**
* #file
* Contains QennerSearch\Search.
*/
namespace QennerSearch;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
/**
* Class Search.
*
* #package QennerSearch
*/
class ServiceClient {
protected $http_client = null;
protected $engine_url = null;
protected $api_key = null;
protected $log_calls = false;
protected $locale = null;
protected $last_result_code = 0;
protected $last_error_body = null;
public function __construct($engine_url, $api_key, $log_calls = false, $locale = "nl-NL") {
$this->http_client = new Client();
$this->engine_url = $engine_url;
$this->api_key = $api_key;
$this->log_calls = $log_calls;
$this->locale = $locale;
I get this error:
Class 'QennerSearch\ServiceClient' not found
While I expected a dump of the output
Updated
After seeing your folder structure in the comments, I believe ServiceClient.php and Search.php, both are inside the folder: app\Qenner, hence inside those files:
wherever you are using: namespace QennerSearch;
you should use: namespace App\Qenner;
and then inside your controller, instead of using: use QennerSearch\ServiceClient;
use: namespace App\Qenner\ServiceClient
Namespaces are not like aliases, they need to reflect the position of the file itself if that makes sense.
Please give it a try and let me know if it works.
I am trying to load a custom class in my CakePHP3 project, although I can't seem to find out what I am missing.
I have a folder src/Library with Config.php in it:
<?php
namespace App\Library;
/**
* Class containing CONST values for important settings
*
* #version 1.0
* #author berry
*/
class Config
{
const UPLOAD_DIRECTORY = './upload/';
}
I put use App\Library\Config; in my PicturesController, which Visual Studio even recognizes as a valid class (I can access the const through intellisense)
Here is my controller:
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Filesystem\Folder;
use Cake\Filesystem\File;
use App\Library\Config;
/**
* Pictures Controller
*
* #property \App\Model\Table\PicturesTable $Pictures
*/
class PicturesController extends AppController
{
public function upload()
{
if($this->request->is('post'))
{
$oConfig = new Config();
$oUploadDir = new Folder($oConfig::UPLOAD_DIRECTORY);
debug($oUploadDir);
$aFile = $this->request->data('submittedfile');
}
}
So despite my IDE even registering the class (and telling me I'm using it correctly) I get Class 'App\Library\Config' not found thrown in the browser.
I changed the name from Library to Berry (My first name).
Apparently you can't call it Library. Probably used somewhere else in Cake.
I trying to add DOM PDF library to my codeigniter application
1.Download dompdf and copy the dompdf folder to libraries folder.
2.Create file named Dompdf.php in libraries folder
In my controller
public function pdf_test()
{
$this->load->library('Dompdf');
$this->Dompdf->loadHtml('hello world');
$this->pdf->render();
$this->pdf->stream("welcome.pdf");
}
Dompdf.php
<?php defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter PDF Library
*
* Generate PDF's in your CodeIgniter applications.
*
* #package CodeIgniter
* #subpackage Libraries
* #category Libraries
* #author Chris Harvey
* #license MIT License
* #link https://github.com/chrisnharvey/CodeIgniter-PDF-Generator-Library
*/
require_once(dirname(__FILE__) . '/dompdf/autoload.inc.php');
class Pdf extends DOMPDF
{
/**
* Get an instance of CodeIgniter
*
* #access protected
* #return void
*/
protected function ci()
{
return get_instance();
}
/**
* Load a CodeIgniter view into domPDF
*
* #access public
* #param string $view The view to load
* #param array $data The view data
* #return void
*/
public function load_view($view, $data = array())
{
$html = $this->ci()->load->view($view, $data, TRUE);
$this->load_html($html);
}
}
But i will this error.
Message: Class 'DOMPDF' not found
Filename: libraries/Dompdf.php
Line Number: 16
I am using latest DOMPDF
in my case. i use this
$dompdf = new Dompdf\DOMPDF();
require_once(_MAP."libraries/dompdf/autoload.inc.php");
$dompdf = new Dompdf\DOMPDF();
$html = 'rats :)';
$dompdf->load_html($html);
$dompdf->render();
$dompdf->stream("sample.pdf");
Starting with v0.7.0 Dompdf uses namespaces. You probably need to add a use statement prior to referencing the class. Or reference it using the full namespace path.
Try:
require_once(dirname(__FILE__) . '/dompdf/autoload.inc.php');
use Dompdf\Dompdf;
class Pdf extends Dompdf
{
...
}
Usage is available in the readme or on the wiki usage page.
I simply changed
$dompdf = new Dompdf\DOMPDF();
to
$dompdf = new Dompdf\Dompdf();
inside the Pdf.php
I have done pdf generation with tcpdf library but with a slightly different approach from you. Here is my solution with tcpdf. You can try it with Dompdf.
Download tcpdf and put in third_party folder
Make a file PDF.php in libraries folder with the following contents
require_once APPPATH."third_party/tcpdf/tcpdf.php";
class PDF extends TCPDF {
public function __construct() {
parent::__construct();
}
}
In controllers folder create a file Createpdf.php with following codes
defined("BASEPATH") OR exit("No direct script access allowed");
class Createpdf extends CI_Controller {
public function pdf()
{
$this->load->library("pdf");
$data["content"] = "Hello from CodeIgniter with TCPDF...";
$this->load->view("pdfreport", $data);
}
}
and the pdfreport.php view is:
$obj_pdf = new TCPDF('P', PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$obj_pdf->AddPage();
$obj_pdf->writeHTML($content, true, false, true, false, '');
$obj_pdf->Output('output.pdf', 'I');
First install it by composer
composer require dompdf/dompdf
And use this in pdf library .
require 'vendor/autoload.php';
use Dompdf\Dompdf as Dompdf;
I'm currently building some tests for my Image model which handles files and wanted to use vsfStream to test the file manipulations.
I can't seem to get my tests to recognise the vsfClass.
The vsfStream library is in app/Vendor/vsfStream
My ImageTest.php file is as follows:
<?php
App::uses('Image', 'Model');
App::uses('vfsStream', 'Vendor');
//App::import('Vendor', 'vfsStream', array('file' => 'vfsStream' . DS . 'vfsStream.php'));
/**
* Image Test Case
*
*/
class ImageTest extends CakeTestCase {
/**
* Fixtures
*
* #var array
*/
public $fixtures = array(
'app.image',
'app.contractor',
'app.project',
'app.project_contractor',
'app.project_image'
);
/**
* setUp method
*
* #return void
*/
public function setUp() {
parent::setUp();
$this->Image = ClassRegistry::init('Image');
$this->root = vfsStream::setup('exampleDir');
}
...more code
I get the error
Error: Class 'vfsStream' not found
File: C:\xampp\htdocs\sgaluminium\app\Test\Case\Model\ImageTest.php
Line: 32
Any help would be appreciated. Thanks
It seems that vsfStream was not loaded correctly. Did you load it with composer? I recommend you use this composer plugin: https://github.com/uzyn/cakephp-composer (read the how-to-use section on their website) and you write your composer.json like this:
{
"require-dev": {
"phpunit\/phpunit": "3.7.35",
"mikey179/vfsStream": "1.2"
}
}
This setup works very well in my project. In my test-file I use:
App::uses('vfsStream', 'Vendor');
just like you do.
I've got a class library in defined here .../projectname/library/Me/Myclass.php defined as follows:
<?php
class Me_Myclass{
}
?>
I've got the following bootstrap:
<?php
/**
* Application bootstrap
*
* #uses Zend_Application_Bootstrap_Bootstrap
*/
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
/**
* Bootstrap autoloader for application resources
*
* #return Zend_Application_Module_Autoloader
*/
protected function _initAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Default',
'basePath' => dirname(__FILE__),
));
$autoloader->registerNamespace('Me_');
return $autoloader;
}
/**
* Bootstrap the view doctype
*
* #return void
*/
protected function _initDoctype()
{
$this->bootstrap('view');
$view = $this->getResource('view');
$view->doctype('XHTML1_STRICT');
}
/**
* Bootstrap registry and store configuration information
*
* #return void
*/
protected function _initRegistry()
{
$config = new Zend_Config_Ini(APPLICATION_PATH .
'/configs/application.ini', APPLICATION_ENV,
array('allowModifications'=>true));
Zend_Registry::set('configuration', $config);
}
}
In my controller I try to instantiate the class like this:
<?php
class SomeController extends Zend_Controller_Action
{
public function indexAction()
{
$classMaker=new Me_Myclass();
}
}
?>
When I navigate directly to http:/something.com/projectname/some?id=1 I get the following error:
Fatal error: Class 'Me_Myclass' not found in /home/myuser/work/projectname/application/controllers/SomeController.php on line x
Any ideas?
Potentially Pertinent Miscellany:
The autoloader seems to work when I'm extending models with classes I've defined in other folders under application/library.
Someone suggested changing the 'Default', which I attempted but it didn't appear to fix the problem and had the added negative impact of breaking function of models using this namespace.
You class needs to be name Me_Myclass:
class Me_Myclass
{
}
Move your library folder up a level so that you have the folder structure:
/
/application
/library
/public
And then in your Bootstrap add the following to the _initAutoload():
Zend_Loader_Autoloader::getInstance()->registerNamespace('Me_');
you can define the autoload dir in the config.ini file like this:
autoloaderNamespaces[] = "Me_"
;You could add as many as you want Classes dir:
autoloaderNamespaces[] = "Another_"
autoloaderNamespaces[] = "Third_"
works 100%
I think #smack0007 means replace the contents of your _initAutoload method with Zend_Loader_Autoloader::getInstance()->registerNamespace('Me_'); so it looks like this:
protected function _initAutoload()
{
Zend_Loader_Autoloader::getInstance()->registerNamespace('Me_');
}
Not sure if this is your problem, but I just spent the last day and half trying to figure out my own similar problem (first time loading it up on Linux from Windows). Turns out I was blind to my library's folder name case.
/library
/Tlib
is not the same as (on *nix)
/library
/tlib
Class name is typically this
class Tlib_FooMe {
...
}
Hope this helps someone who is similarly absentminded.