I want simply initialise the \AsyncMysqlConnectionResult $connec; object
<?hh
namespace Connection;
require_once("ini.php");
/**
* Class for execute and fetch query
*/
class MyQuery
{
/**
* if connection isn't valid recreate pool
*/
private ?\AsyncMysqlConnectionPool $pool;
/**
* \AsyncMysqlConnection object, store $conn
*/
private \AsyncMysqlConnection $connec;
/**
* \AsyncMysqlQueryReturn object, store return query
*/
private \AsyncMysqlQueryResult $result;
/**
* check if $conn object isValid(), if not release
* connection
*/
public function __construct(\AsyncMysqlConnection $conn)
{
if ($conn->isValid() == false)
{
$this->pool = new MyPool();
$this->connec = $this->pool->connect();
}
else
$this->connec = $conn;
$this->result = object;
}
/**
* escape query and execute it
*/
public async function query(string $query): Awaitable<\AsyncMysqlQueryResult>
{
$query = $this->connec->escapeString($query);
echo "Query escape\n";
/* Try to execute the query, if fail display error */
try
{
$this->result = await $this->connec->query($query);
//log request with ini
}
catch (Exception $e)
{
echo "Couldn't execute the request, error with message :<br>";
var_dump($e->getMessage());
//log request with fail
}
echo "Query done succefully\n";
return $this->result;
}
/**
* escape Map array and execute the request
*/
public async function queryf(HH\FormatString<HH\SQLFormatter> $query, array<string> $params): Awaitable<\AsyncMysqlQueryResult>
{
$i = 0;
while ($params[$i++])
$params[$i] = $this->connec->escapeString($params[$i]);
/* Try to execute the query, if fail display error */
try
{
$result = await $this->connec->queryf($query, implode(', ', $params));
//log request with ini
}
catch (Exception $e)
{
echo "Couldn't execute the request, error with message :<br>";
var_dump($e->getMessage());
//log request with fail
}
echo "Query done succefully\n";
return $this->result;
}
}
newtype AsyncMysqlConnectionResult = object;
newtype FormatString<T> = string;
async function simple_query(\AsyncMysqlConnection $conn): Awaitable<Vector>
{
$connec = new MyQuery($conn);
$ret = await $connec->query('SELECT * FROM users');
return $ret->vectorRows();
}
function run_query(\AsyncMysqlConnection $conn): void
{
$r = \HH\Asio\join(simple_query($conn));
var_dump($r);
}
run_query($conn);
For having this object I use https://docs.hhvm.com/hack/reference/class/AsyncMysqlConnectionPool/connect/ class and connect() method to have this : \AsyncMysqlConnectionResult $connec object.
I can't find a way to initialise this variable type, I've try to
create newtype AsyncMysqlConnectionResult = object but the filechecker return me :
Unbound name: Connection\object (an object type)
Instead of storing the result on the class, why doesn't your query methods simply return the result. For example:
public async function query(string $query): Awaitable<\AsyncMysqlQueryResult>
{
$query = $this->connec->escapeString($query);
return await $this->connec->query($query);
}
or if you really want the result to be stored on the class, make it nullable. This will allow you to not set it in the constructor, and only set it after a query has been made.
private ?\AsyncMysqlQueryResult $result;
This is the only way a find to rewrite queryf() method.
public async function queryf($query, array<int, string> $params): Awaitable<\AsyncMysqlQueryResult>
{
$result = "";
/* Try to execute the query, if fail display error */
try // execute query
{
$result = await $this->connec->queryf($query, implode(', ', $params));
// If log_request === TRUE log request with ini
if ($this->log_request === TRUE)
await $this->logRequest($query, 0);
}
catch (Exception $e) // If the query can't be execute display error
{
echo "\nCouldn't execute the request, error with message :<br>\n";
var_dump($e->getMessage());
//log request with fail
await $this->logRequest((string)$query, -1);
}
return (object)$result;
}
I have no error and everything work fine.
If someone have a better and solution I'm here.
Related
I've taken over the code from another developer, and I'm quite confused and stuck: one controller I can call the class method CLASSS::method perfectly OK. the other Controller has a copy of the orginal code and modified. On the second one, I get the "non-static method" error.
Call Chain:
Controller->Class->filtered results->Controller response
1A) (Working) Conttroller
<?php
namespace App\Http\Controllers\V1;
use App\Site as SiteClass;
use Facades\App\Site;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
use App\{
Http\Controllers\Controller,
Http\Requests\SiteRequest,
Helper\ResourceTrait,
Assets,
Alerts,
Licensee,
Permits,
LandOwner,
Utility
};
use Illuminate\Support\Collection;
class SiteController extends Controller
{
private $obj;
public function __construct()
{
$this->obj = new SiteClass();
}
public function index(Request $request)
{
try
{
$data = Site::filter(
($request->has('sort')? $request->input('sort') : ''),
($request->has('filter')? $request->input('filter') : '')
);
...removed some extra code that's not relevant ...
return response($data);
}
catch(\Exception $e)
{
Log::info('Create exception from here?' . $e);
return response(array('error'=>$e->getMessage()),422);
}
} // index
....
}
1B) (Working) Class
<?php
namespace App;
use Illuminate\Support\Facades\Config;
use \App\BaseModel;
class Site extends BaseModel
{
protected $table = 'sites';
protected $fillable = [
"status","structureType","siteId","name","coverage","address","postCode", "subdistrict", "district", "region", "state", "country", "localCouncil", "latitude", "longitude", "dimensions",
"siteHandover", "startBilling", "utilityBillAcct", "utilityBillingAddress", "renewalTerm",
"capex", "opex", "siteManager", "siteManagerPhone", "siteManagerEmail", "siteOwnerManager", "siteOwnerManagerPhone", "siteOwnerManagerEmail"
];
...
// Working Static method call.
public function filter($sort = null, $search = null)
{
$data = $this;
// check if search variable not empty
if ($search != null)
{
$data = $data->where(function ($query) use ($search){
return $query->where($this->table.'.name','like','%'.$search.'%')
->orWhere($this->table.'.status','=',$search)
->orWhere($this->table.'.siteId','like','%'.$search.'%')
->orWhere($this->table.'.address','like','%'.$search.'%')
->orWhere($this->table.'.subdistrict','like','%'.$search.'%')
->orWhere($this->table.'.district','like','%'.$search.'%')
->orWhere($this->table.'.region','like','%'.$search.'%')
->orWhere($this->table.'.state','like','%'.$search.'%')
->orWhere($this->table.'.country','like','%'.$search.'%')
->orWhere($this->table.'.localCouncil','like','%'.$search.'%')
;
});
if ($sort != null)
{
$sorts = explode('|', $sort);
$data = $data->orderBy($sorts[0],$sorts[1]);
}
}
// check if sort variable not empty
if ($sort != null)
{
$sorts = explode('|', $sort);
$data = $data->orderBy($sorts[0],$sorts[1]);
}
else
{
$data = $data->orderBy('siteId','desc');
}
// return data
return $data->paginate(Config::get('api.records'));
}
}
2A) (Failing) Controller
<?php
namespace App\Http\Controllers\V1;
use App\{
Http\Controllers\Controller,
Helper\ResourceTrait,
Http\Requests\OrganisationRequest,
Organisation
};
use Illuminate\{
Http\Request,
Support\Facades\Config,
Support\Facades\Log
};
class OrganisationController extends Controller
{
private $org;
public function __construct()
{
$this->org = new Organisation();
}
public function index(Request $request)
{
try
{
//WORKAROUND: $this->org->... works
$data = Organisation::filter(
($request->has('sort')? $request->input('sort') : ''),
($request->has('filter')? $request->input('filter') : '')
); // FAILS with non-static method call error
return response($data);
}
catch(\Exception $e)
{
return response(array('error'=>$e->getMessage()),422);
}
} // index
}
...
2B) Failing Class
<?php
namespace App;
use Illuminate\Support\Facades\Config;
use \App\BaseModel;
class Organisation extends BaseModel
{
protected $table = 'organisation';
public function filter($sort = null, $search = null)
{
$data = $this;
// check if search variable not empty
if ($search != null)
{
$data = $data->where(function ($query) use ($search){
return $query->where($this->table.'.name','like','%'.$search.'%')
;
});
if ($sort != null)
{
$sorts = explode('|', $sort);
$data = $data->orderBy($sorts[0],$sorts[1]);
}
}
// check if sort variable not empty
if ($sort != null)
{
$sorts = explode('|', $sort);
$data = $data->orderBy($sorts[0],$sorts[1]);
}
else
{
$data = $data->orderBy('name');
}
// return data
return $data->paginate(Config::get('api.records'));
}
}
To my untutored eye, they look identical, yet one works and the other doesn't. Apologies in advance for the volume of code, but I don't know which parts are affecting what. I suspect it's somethng to do with an imported class, but I'm lost frankly :-D
Site has a Facade while Organisation does not.
Facades (from the docs) provide a "static" interface to classes that are available in the application's service container.
Lumen 5.4.
class AfterMiddleware
{
public function handle($request, Closure $next)
{
try {
return $next($request);
} catch (IpValidationException $e) {
return response()->json($e->getMessage(), 422);
} catch (RemoteException $e) {
return response()->json($e->getMessage(), 503);
} catch (BaseException $e) {
return response()->json($e->getMessage(), 400);
} catch (\Exception $e) {
return response()->json($e->getMessage(), $e->getCode());
}
}
}
After the exception is raised, the $next($request) goes to the following function in Laravel\Lumen\Routing:
/**
* Get the initial slice to begin the stack call.
*
* #param \Closure $destination
* #return \Closure
*/
protected function prepareDestination(BaseClosure $destination)
{
return function ($passable) use ($destination) {
try {
return call_user_func($destination, $passable);
} catch (Exception $e) {
return $this->handleException($passable, $e);
} catch (Throwable $e) {
return $this->handleException($passable, new FatalThrowableError($e));
}
};
}
And it's catched there, so I my AfterMiddleware is useless. Any ideas how to circumvent it? I've found a solution and moved all the exceptions to render() in my Handler class, but it is much more convienient to use middleware.
I haven't tried this, but from Lumen's code, I think it is possible.
The handleException function invoked from prepareDestination checks if the ExceptionHanlder is bound to the container or not. If it is not, it is throwing the exception.
protected function handleException($passable, Exception $e)
{
if (! $this->container->bound(ExceptionHandler::class) || ! $passable instanceof Request) {
throw $e;
}
$handler = $this->container->make(ExceptionHandler::class);
$handler->report($e);
return $handler->render($passable, $e);
}
So, try by removing the below ExceptionHandler binding from bootstrap/app.php
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
This is how I handle mine, its working on Lumen 5.5.* and php 7.1.
Late answer, but hopefully it will helps someone else. 😀
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Response;
use Illuminate\Validation\ValidationException;
use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Illuminate\Http\Exception\HttpResponseException;
use Symfony\Component\Debug\Exception\FatalThrowableError;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that should not be reported.
*
* #var array
*/
protected $dontReport = [
AuthorizationException::class,
HttpException::class,
ModelNotFoundException::class,
ValidationException::class,
];
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* #param \Exception $e
* #return void
*/
public function report(Exception $e)
{
parent::report($e);
}
/**
* Render an exception into an HTTP response.
*
* #param \Illuminate\Http\Request $request
* #param \Exception $e
* #return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
// if (env('APP_DEBUG')) {
// return parent::render($request, $e);
// }
$response = [
'success' => false
];
$response['status'] = null;
if ($e instanceof HttpResponseException) {
$response['status'] = Response::HTTP_INTERNAL_SERVER_ERROR;
} elseif ($e instanceof MethodNotAllowedHttpException) {
$response['status'] = Response::HTTP_METHOD_NOT_ALLOWED;
} elseif ($e instanceof NotFoundHttpException) {
$response['status'] = Response::HTTP_NOT_FOUND;
} elseif ($e instanceof AuthorizationException) {
$response['status'] = Response::HTTP_FORBIDDEN;
$e = new AuthorizationException('HTTP_FORBIDDEN', $response['status']);
} elseif ($e instanceof ValidationException && $e->getResponse()) {
$response['status'] = Response::HTTP_BAD_REQUEST;
$e = new ValidationException('HTTP_BAD_REQUEST', $response['status'], $e);
} elseif ($e instanceof ValidationException) {
$response['status'] = 422;
$response['errors'] = $e->validator->errors();
} elseif ($e instanceof ModelNotFoundException) {
$response['status'] = 404;
} elseif ($e instanceof UnableToExecuteRequestException) {
$response['status'] = $e->getCode();
} elseif ($e instanceof FatalThrowableError) {
$response['status'] = Response::HTTP_INTERNAL_SERVER_ERROR;
} elseif ($e) {
$response['status'] = Response::HTTP_INTERNAL_SERVER_ERROR;
$response['unhandled'] = 'exception-lumen-ksoft';
}
if ($response['status']) {
$response['message'] = $e->getMessage();
$response['error_code'] = $e->getCode() ?? '';
// $response['exception'] = $e->getTraceAsString() ?? '';
if (app()->environment() == 'local'){
$response['file'] = $e->getFile() ?? '';
$response['line'] = $e->getLine() ?? '';
}
return response()->json($response, $response['status']);
} else {
return parent::render($request, $e);
}
}
}
I'm making a social network's login page but when I login a get the error above. My db.php is (i use pdo):
<?php
class DB {
private static function connect() {
$pdo = new PDO('mysql:host=127.0.0.1;dbname=social;charset=utf8', 'danny', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
}
public static function query($query, $params = array()) {
$statement = self::connect()->prepare($query);
$statement->execute($params);
if (explode(' ', $query)[0] == 'SELECT') {
$data = $statement->fetchAll();
return $data;
}
}
}
?>
Called from
$user_id = DB::query('SELECT id
FROM users
WHERE email=:email')[0]['id'];
DB::query('INSERT INTO login_tokens
VALUES(\'\', :token, :user_id)',
array(':token'=>sha1($token), ':user_id'=>$user_id));
Your class has many issues. to fix them:
class DB {
protected static $pdo;
public static function connect() {
static::$pdo = new PDO('mysql:host=127.0.0.1;dbname=social;charset=utf8', 'danny', 'Dani2034');
static::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public static function query($query, $params = array()) {
$statement = self::$pdo->prepare($query);
$statement->execute($params);
return $statement;
}
}
DB::connect(); // called only once
$user_id = DB::query('SELECT id FROM users WHERE email=?', array($email))->fetchColumn();
DB::query('INSERT INTO login_tokens VALUES(null, ?, ?)', array(sha1($token), $user_id));
I'm getting data from my accounting program in Windows Platform to my PHP Script. I'm transferring data from mssql to mysql. I decided to use PDO. I have a problem with transition. How can i supply two connection simultaneously ?
Here is my own PDO Class.
class Database {
protected $_host = "***********";
protected $_engine = "mysql";
protected $_dbuser = "***********";
protected $_dbpassword = "***********";
protected $_db = "***********";
protected $_sql;
protected $pdo;
/* #desc This Function is Setting SQL Connection
* #return SQL Connection
*
*/
protected function getPdo()
{
if ($this->pdo === NULL) {
try {
$dsn = $this->_engine.':dbname='.$this->_db.';host='.$this->_host.';charset=utf8';
$this->pdo = new PDO($dsn, $this->_dbuser, $this->_dbpassword, array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"
));
//$this->pdo->setAttribute();
//$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
return $this->pdo;
}
/* #desc This Function is Preparing Sql Statement For Query
* #return array Returns PDO Object Query
*
*/
public function query($sql)
{
return $this->_sql = $this->getPdo()->prepare($sql);
}
/* #desc This Function is for Binding Values into SQL Statements
* #return Binded SQL Statements
*
*/
public function bind($param, $value, $type = null){
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->_sql->bindValue($param, $value, $type);
}
/* #desc This Function Execute Query
* #return SQL Execution
*
*/
public function execute($values = NULL){
return (!isset($values)) ? $this->_sql->execute() : $this->_sql->execute($values);
}
/* #desc This Function Execute Query and Fetch Multiple Result
* #return array Returns Array of Table Rows. Array is multidimensional
*
*/
public function queryResults(){
$this->execute();
return $this->_sql->fetchAll(PDO::FETCH_ASSOC);
}
/* #desc This Function Execute Query and Fetch Only Single Result
* #return array Returns Array of Table Row. Array is not multidimensional.
*
*/
public function queryResult(){
$this->execute();
return $this->_sql->fetch(PDO::FETCH_ASSOC);
}
public function queryColumn($index = NULL){
$index = (isset($index)) ? intval($index) : 0;
$this->execute();
return $this->_sql->fetchAll(PDO::FETCH_COLUMN,$index);
// $this->execute();
// return $this->_sql->fetchAll(PDO::FETCH_COLUMN);
}
/* #desc This Function Returns Effected Row Count during Update, Delete and Insert
* #return int Returns Effected Row Count
*
*/
public function effected(){
return $this->_sql->rowCount();
}
/* #desc This Function Returns Effected Row Count during Update, Delete and Insert
* #return int Returns Effected Row Count
*
*/
public function rowCount(){
return count($this->queryResults());
}
public function lastID(){
return $this->_sql->lastInsertId();
}
You need to create 2 instances of PDO class - one for MSSQL and one for MySQL.
I have these classes below for my online store.
This super class holds all common methods used by the child classes.
class grandpa
{
public function test1($string)
{
return $string;
}
}
So do the PDO connection,
class database_pdo extends grandpa
{
protected $connection = null;
protected $dsn,$username,$password;
public function __construct($dsn,$username,$password)
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->get_connection();
}
public function get_connection()
{
try
{
$this->connection = new PDO($this->dsn, $this->username, $this->password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
$this->get_error($e);
}
}
public function __sleep()
{
return array('dsn', 'username', 'password');
}
public function __wakeup()
{
$this->get_connection();
}
public function get_error($e)
{
$this->connection = null;
die($e->getMessage());
}
public function __destruct()
{
$this->connection = null;
}
}
I have this class extend from pdo for other common methods that require pdo connection,
class papa extends database_pdo
{
protected $connection = null;
public function __construct($connection)
{
$this->connection = $connection;
}
public function test2($string)
{
return $string;
}
}
The child classes,
class kido_1 extends papa
{
public function __construct($connection)
{
parent::__construct($connection);
}
public function test3($string)
{
return $string;
}
}
How it use the classes above,
# Host used to access DB.
define('DB_HOST', 'localhost');
# Username used to access DB.
define('DB_USER', 'xxx');
# Password for the username.
define('DB_PASS', 'xxx');
# Name of your databse.
define('DB_NAME', 'xxx');
# Data source name.
define('DSN', 'mysql:host='.DB_HOST.';dbname='.DB_NAME);
$connection = new database_pdo(DSN,DB_USER,DB_PASS);
$kido = new kido($connection);
$_SESSION['cart'] = serialize($kido);
$kido = unserialize($_SESSION['cart']);
print_r($kido->test3('hello'));
I get this error,
invalid data source name
It is caused by unserialize() that I need it for my cart data...
How can I fix this? Or a better way of rewrite these classes?
Your papa::connection is a PDO object. Therefore, when you are trying to serialize $kido, you are trying to serialize a resource, which is not possible.
Try adding a $this->connection = null; in your database_pdo::__sleep() method.
a solution I think...
class papa extends grandpa
{
protected $connection = null;
public function __construct($connection)
{
$this->connection = $connection;
}
public function test2($string)
{
return $string;
}
}