A Quick Guide to implement a REST Web Service with database connection using SLIM MicroFramework
1.- SLIM INSTALLATION
Install composer in your project:
curl -s https://getcomposer.org/installer | php
Create a
composer.json
file in your project root:{
"require": {
"slim/slim": "2.*"
}
}
Install via composer:
php composer.phar install
Add this line to your application’s
index.php
file:<?php
require 'vendor/autoload.php';
2.- Testing installation (Create an index.php to test)
$app = new \Slim\Slim(array(
'debug' => true
));
$app->get('/', function () {
echo 'Hola Mundo';
});
$app->run();
3.- Optional Managing of VIRTUAL HOST
<VirtualHost local.televisa:8081>
ServerName local.pruebas
DocumentRoot /Users/Tomas/projects/empresa/php
SetEnv APPLICATION_ENV "development"
<Directory /Users/Tomas/projects/empresa/php>
DirectoryIndex index.php
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
4.-Dir Structure
4.-Dir Structure
4a) config.xml: Logger configuration file
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://logging.apache.org/log4php/">
<appender name="myAppender" class="LoggerAppenderFile">
<layout class="LoggerLayoutPattern">
<param name="conversionPattern" value="%date [%logger] %message%newline" />
</layout>
<param name="file" value="/Users/Tomas/projects/empresa/php/WSSubscriber/logs/WSSS.log" />
</appender>
<root>
<level value="DEBUG" />
<appender_ref ref="myAppender" />
</root>
</configuration>
4b) veo-config.ini: Database configuration and other conf parameters for the application.
[database]
host = localhost
username = dummyuser
password = dummypass
dbname = databasename
type = mysql
charset = 'utf8'
4c) GenericDAO:
<?php
include_once __DIR__.'/../init.php';
include_once __HELPER_PATH__.'/VeoConfiguration.php';
class GenericDAO {
private $logger = NULL;
protected $pdo_obj = NULL; // Stores the open connection PDO object
private $connection_string = NULL; // Used to build the database connection
private $db_type = NULL; // Stores the database type
private $db_host = NULL;
private $db_user = NULL;
private $db_pass = NULL;
private $db_name = NULL;
private $db_charset = NULL;
private $is_active = false; // Checks to see if the connection is active
protected $pdo_obj_rr = NULL; // Stores the open connection PDO object
private $connection_string_rr = NULL; // Used to build the database connection
private $db_type_rr = NULL; // Stores the database type
private $db_host_rr = NULL;
private $db_user_rr = NULL;
private $db_pass_rr = NULL;
private $db_name_rr = NULL;
private $db_charset_rr = NULL;
private $is_active_rr = false; // Checks to see if the connection is active
public function __construct() {
$config = VeoConfiguration::getInstance();
$this->logger = Logger::getLogger("GenericDAO");
$this->db_host = $config->get('database', 'host');
$this->db_user = $config->get('database', 'username');
$this->db_pass = $config->get('database', 'password');
$this->db_name = $config->get('database', 'dbname');
$this->db_type = $config->get('database', 'mysql');
$this->db_charset = $config->get('database', 'charset');
$this->connection_string = "mysql:host=" . $this->db_host . ";dbname=" . $this->db_name;
$this->db_host_rr = $config->get('databaserr', 'host');
$this->db_user_rr = $config->get('databaserr', 'username');
$this->db_pass_rr = $config->get('databaserr', 'password');
$this->db_name_rr = $config->get('databaserr', 'dbname');
$this->db_type_rr = $config->get('databaserr', 'mysql');
$this->db_charset_rr = $config->get('databaserr', 'charset');
$this->connection_string_rr = "mysql:host=" . $this->db_host_rr . ";dbname=" . $this->db_name_rr;
return $this;
}
/*
* only one connection allowed
*/
protected function connect() {
if (!$this->is_active) {
try {
$attrs = array(
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES " . $this->db_charset
);
$this->pdo_obj = new PDO($this->connection_string, $this->db_user, $this->db_pass, $attrs);
$this->pdo_obj->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->is_active = true;
} catch (PDOException $e) {
$this->logger->error("ERROR:" . $e->getMessage());
$this->logger->error("ERROR:" . $e->getTraceAsString());
throw $e;
}
}
return $this->is_active;
}
protected function connect_rr(){
if (!$this->is_active_rr) {
try {
$attrs = array(
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES " . $this->db_charset_rr
);
$this->pdo_obj_rr = new PDO($this->connection_string_rr, $this->db_user_rr, $this->db_pass_rr, $attrs);
$this->pdo_obj_rr->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->is_active_rr = true;
} catch (PDOException $e) {
$this->logger->error("ERROR:" . $e->getMessage());
$this->logger->error("ERROR:" . $e->getTraceAsString());
throw $e;
}
}
return $this->is_active_rr;
}
protected function disconnect() {
$isDisconnect = false;
if ($this->is_active) {
unset($this->pdo_obj);
$this->is_active = false;
$isDisconnect = true;
}
return $isDisconnect;
}
protected function disconnect_rr() {
$isDisconnect = false;
if ($this->is_active_rr) {
unset($this->pdo_obj_rr);
$this->is_active_rr = false;
$isDisconnect = true;
}
return $isDisconnect;
}
/*
* SELECT (any)
* Required: $sqlSelect
*/
public function select($sqlSelect) {
$this->connect_rr();
$exception = NULL;
$arrayResult = NULL;
try {
$sql = $this->pdo_obj_rr->prepare($sqlSelect);
$sql->execute();
$arrayResult = $sql->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
$exception = $e;
$this->logger->error("ERROR:" . $e->getMessage());
$this->logger->error("ERROR:" . $e->getTraceAsString());
}
$this->disconnect_rr();
if($exception){
throw $exception;
}
return $arrayResult;
}
/*
* INSERT
* Required: $strInsert sql insert
*/
public function insert($strInsert, $getLastId = FALSE) {
$exception = NULL;
$totalRows = -1;
$this->connect();
try {
$ins = $this->pdo_obj->prepare($strInsert);
$ins->execute();
if ($getLastId) {
$totalRows = $this->pdo_obj->lastInsertId();
} else {
$totalRows = $ins->rowCount();
}
} catch (PDOException $e) {
$this->logger->error("ERROR:" . $e->getMessage());
$this->logger->error("ERROR:" . $e->getTraceAsString());
$exception = $e;
}
$this->disconnect();
if($exception){
throw $e;
}
return $totalRows;
}
/*
* DELETE
* Required: Stament to sql delete
*/
public function delete($strDelete) {
$exception = NULL;
$totalRows = -1;
$this->connect();
try {
$del = $this->pdo_obj->prepare($strDelete);
$del->execute();
$totalRows = $del->rowCount();
} catch (PDOException $e) {
$this->logger->error("ERROR:" . $e->getMessage());
$this->logger->error("ERROR:" . $e->getTraceAsString());
$exception = $e;
}
$this->disconnect();
if($exception){
throw $e;
}
return $totalRows;
}
/*
* UPDATE
* Required: $strUpdate
*/
public function update($strUpdate) {
$exception = NULL;
$totalRows = -1;
$this->connect();
try {
$upd = $this->pdo_obj->prepare($strUpdate);
$upd->execute();
$totalRows = $upd->rowCount();
} catch (Exception $e) {
$this->logger->error("ERROR:" . $e->getMessage());
$this->logger->error("ERROR:" . $e->getTraceAsString());
$exception = $e;
}
$this->disconnect();
if($exception){
throw $e;
}
return $totalRows;
}
}
?>
4d) VeoServicesDAO DAO APP specific functions.
<?php
include_once __DIR__ . '/../../init.php';
include_once __DATA_PATH__ . '/GenericDAO.php';
/**
* Description of VeoServicesDAO
*
*/
class VeoServicesDAO extends GenericDAO {
private $logger;
public function __construct() {
parent::__construct();
$this->logger = Logger::getLogger('VeoServicesDAO');
}
/**
* Looks for entitlement using the contract number and the mso_id.
* @param string $contract The contract code.
* @param string $mso_id The mso_id
* @return array The subscriber information.
*/
public function getEntitlementByContractAndCityId($contract, $city=null) {
$sqlSelect = 'SELECT * FROM entitlement WHERE contract = "' . $contract . '"';
if (!empty ($city))
$sqlSelect.= ' AND city_id = "' .$city.'"';
$this->logger->debug('getEntitlementByContractAndCity: ' . $sqlSelect);
$result = $this->select($sqlSelect);
if (count($result) === 1 )
return $result[0];
else if(count($result) > 1)
return 1;
else
return NULL;
}
}
?>
<?php
include_once __DIR__ . '/../init.php';
/**
* This class implements the singleton pattern to return configuration values
* without opening and closing the file every time needed.
*
* @author Abraham Soto
*/
class VeoConfiguration {
//The reference to the file
private $file_ini;
//The ¡nstance of the class that will be returned when needed.
private static $instance = NULL;
/** Constructor of the class.*/
private function __construct() {
$this->file_ini = parse_ini_file(__CONFIG_FILE_INI__, true);
}
/** Singleton method, returns an instance of this class. */
public static function getInstance(){
if(self::$instance == NULL){
self::$instance = new VeoConfiguration();
}
return self::$instance;
}
/**
* This method returns the value set in the config file.
* @param type $section optional, the section to which the config property belongs to.
* @param type $name The name of the property.
*
* @return string returns an string with the value obtained from the config file. if the value is not in the file returns NULL.
*/
public function get($section, $name){
return isset($this->file_ini[$section][$name]) ?
$this->file_ini[$section][$name] : '';
}
}
?>
4f) WSSS.log: Log file with write permissions.
4g) Init.php Constants definition and Logger initially instantiation.
<?php
//Root path of the application.
define('__ROOT_PATH__', __DIR__);
//Path to the Config folder.
define('__CONFIG_PATH__', __ROOT_PATH__ . '/configs');
//Path to the veo-config.ini file.
define('__CONFIG_FILE_INI__', __CONFIG_PATH__ . '/veo-config.ini');
//Path to the helper class
define('__HELPER_PATH__', __ROOT_PATH__ . '/helpers');
//Path to the log files
define('__LOGGER_FILE_APP__', __ROOT_PATH__ . '/logs/veo_app_errors.log');
//Path to the library class
define('__LIBRARY_PATH__', __ROOT_PATH__ . '/vendor');
//Path to the dao class
define('__DATA_PATH__', __ROOT_PATH__ . '/data');
//Include logger and initialize it
include_once __LIBRARY_PATH__.'/log4php/Logger.php';
Logger::configure(__CONFIG_PATH__.'/config.xml');
?>
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
require 'vendor/autoload.php';
include_once 'init.php';
include_once __DATA_PATH__ . '/dao/VeoServicesDAO.php';
$dao = new VeoServicesDAO();
$logger = Logger::getLogger("index.php");
$app = new \Slim\Slim(array(
'debug' => false
));
$app->get('/', function () {
echo 'Utilice <b>/consulta</b> para acceder al Web Service para consultar estatus de un suscriptor tomando como parametros POST contrato y opcionalmente una ciudad-<br> Recibe POST: <br> <b>{"contract":"value", "city":"value"}</b> <br> Regresa <br> <b>{"status":"value"}</b>';
});
/**
* Consult.
* Input: It will take the POST containing a contract and optional parameter city.
* Output: Return the status for the subscriber contract.
* Test Cases:
* Success: HTTP 200 OK
* Failure: HTTP 500 Error
* Errors: HTTP 400 Exception
* Exceptions:
* Missin Data Fields HTTP 417 Exception
*
* @todo finish the functions on this page
*/
$app->post('/consulta', function () use ($app, $logger,$dao) {
$app->response()->header('Content-Type', 'application/json; charset=utf-8');
$response = array();
try {
if($app->request()->getBody() === ''){
throw new Exception('Missing Data Fields', 417);
}
$request = json_decode($app->request()->getBody());
if(empty($request->contract)){
throw new Exception('Missing Data Field contract', 417);
}
$city = !empty($request->city)?$request->city:NULL;
$contract = $request->contract;
$entitlement = $dao->getEntitlementByContractAndCityId($contract,$city);
if (!$entitlement){
throw new Exception('No data found', 418);
}
else if ($entitlement==1){
throw new Exception('More than one register found', 419);
}
else{
$response['status'] = $entitlement['account_status'];
}
} catch (Exception $e) {
$response['error_code'] = $e->getCode();
$response['error_message'] = $e->getMessage();
}
echo json_encode($response, JSON_UNESCAPED_UNICODE);
});
$app->run();
?>
No hay comentarios:
Publicar un comentario