I have a sql UPDATE query in PDO that should update a name and a permissions string.
But instead it just places the id of that row inside all columns.
Here is my code:
public function saveRole($roleID, $name, $permissions)
{
$sql = "UPDATE roles SET name = :name, permissions = :permissions WHERE id = :id";
//this one sets a string variable in the PDO wrapper class
PDO::setSQL($sql);
//this one sets an array inside the PDO wrapper class
PDO::setData([
'name' => $name,
'permissions' => $permissions,
'id' => $roleID,
]);
PDO::execute();
return PDO::getResponse(true);
}
As you see, I've written a wrapper for PDO, which looks like this:
static function execute($sql = null, $data = null, $fetchmode = \PDO::FETCH_OBJ)
{
//check if data and SQL are set in function call, if so, use function call params, if not use class params ($this->SQL & $this->data)
self::connect();
try
{
$stmnt = self::$con->prepare(self::$sql);
$stmnt->setFetchMode($fetchmode);
if (sizeof(self::$data) > 0)
{
foreach (self::$data as $key => $value)
{
$stmnt->bindParam(':' . $key, $value);
}
}
$stmnt->execute();
self::$stmnt = $stmnt;
self::$data = [];
self::$sql = '';
self::$lastResponse = new pdoReturn(true, $stmnt);
return;
} catch (\PDOException $exception)
{
self::$data = [];
self::$sql = '';
self::$lastResponse = new pdoReturn(false, $exception);
return;
}
}
function setSQL($sql) {
if (!is_string($sql))
return false;
if (strlen($sql) == 0)
return false;
$this->sql = $sql;
return true;
}
function setData($data) {
if (!is_array($data))
return false;
$this->data = $data;
return true;
}
As you see, I've written a wrapper for PDO
For the immediate fix, change
$stmnt = self::$con->prepare(self::$sql);
$stmnt->setFetchMode($fetchmode);
if (sizeof(self::$data) > 0)
{
foreach (self::$data as $key => $value)
{
$stmnt->bindParam(':' . $key, $value);
}
}
$stmnt->execute();
to
$stmnt = self::$con->prepare(self::$sql);
$stmnt->setFetchMode($fetchmode);
$stmnt->execute(self::$data);
Then read about your first database wrapper's childhood diseases and fix other issues such as statefulness and error reporting.
Related
Recently I try to create an API with PHP. all thing goes alright till suddenly I face unexpected 'a' error when trying to parse a JSON from the request throw Postman. I found something related to my issue but there is no solution in my case here : link
I send
{
"teacher_code":"sas"
}
JSON to teachers.php file to assign a student to the teacher
here is the teacher.php file content :
require_once ("classes/Rest.php");
require_once ("classes/api.php");
$api = new Api();
if($api->getHttpmethod() === 'POST'){
$api->validateParameter('teacher_code' ,$teacher_code = $api->getParam('teacher_code') , STRING , true);
$api->checkUserAccessablity();
$api->teacherCodeinRange($teacher_code);
$query = "INSERT INTO `group_users` (`user_id`,`group_id` )
VALUES (:user_id , (SELECT group_id FROM `groups` WHERE group_name = 'all' AND user_id =
(SELECT user_id FROM `teachers` WHERE t_code = :teacher_code)) )";
$keyValue = [
"user_id" => $api->getUserid() ,
"teacher_code" => $teacher_code
];
$result = $api->queryExecute($query , $keyValue );
$api->returnResponse(SUCCESS , SUCCESS_MESSAGE);
}
and api.php file :
require_once ("dbConnect.php");
require_once ("JWT.php");
class Api extends Rest
{
public $dbConn;
private $userId;
public function __construct()
{
parent::__construct();
$db = new dbConnect();
$this->dbConn = $db->connect();
}
public function setUserid($id){
$this->userId = $id;
}
public function getUserid(){
return $this->userId;
}
public function checkUserAccessablity(){
$payload = $this->deCodetoken();
$this->setUserid($payload->user_id);
$this->validateUser();
}
public function validateUser(){
$query = "SELECT * FROM `users` WHERE user_id = :id";
$keyValue = [
"id" => $this->getUserid()
];
$result = $this->queryExecute($query , $keyValue,true );
if(!$result){
$this->throwError(SYSTEM_ERROR , SYSTEM_ERROR_MESSAGE );
}
if(!is_array($result)){
$this->throwError(USER_NOT_FOUND_CODE , USER_NOT_FOUND_MESSAGE . $this->getUserid());
}
//TODO CHECK USER ACTIVE
return true;
}
public function teacherCodeinRange($tCode){
$query = "SELECT * FROM `teachers` INNER JOIN `licenses` ON (licenses.user_id = teachers.user_id)
WHERE teachers.t_code = :tcode LIMIT 1";
$keyValue = [
"tcode" => $tCode
];
$this->queryExecute($query , $keyValue,true );
return true;
}
public function teacherCodeinStudentrange($teacherID){
//TODO SELECT TEACHER STUDENT RANGE
$query = "SELECT DISTICT user_id FROM `teachers` INNER JOIN `groups` ON (groups.user_id = teachers.user_id)
INNER JOIN `group_users` ON (group_users.group_id = groups.group_id)
WHERE teachers.user_id = :teacherID AND groups.group_name = 'all' AND group_users.user_id = :userID ";
$keyValue = [
"userID" => $this->getUserid(),
"teacherID" => $teacherID,
];
$result = $this->queryExecute($query , $keyValue,true );
if(!is_array($result)){
$this->throwError(TEACHER_NOT_FOUND , TEACHER_NOT_FOUND_MESSAGE);
}
return true;
}
public function getHttpmethod(){
return $this->HttpMethod;
}
public function getParam($key){
return $this->arrayFinddeep($this->data , $key);
}
public function queryExecute($query , $keyArray , $isSelect = false){
$queryExec = $this->dbConn->prepare($query);
if(is_array($keyArray) || !empty($keyArray)) {
foreach ($keyArray as $key => &$value) {
$queryExec->bindParam(':' . $key, $value);
}
}
if($isSelect) {
$queryExec->execute();
$result = $queryExec->fetch(PDO::FETCH_ASSOC);
}else {
$result = $queryExec->execute();
}
return $result;
}
public function getLastuserId(){
return $this->dbConn->lastInsertId();
}
public function generateToken($payload , $secretKey){
try{
return \Firebase\JWT\JWT::encode($payload , $secretKey);
}catch (Exception $exception){
$this->throwError(JWT_PROCESSING_ERROR , $exception->getMessage());
}
}
public function deCodetoken(){
try{
$token = $this->getBearerToken();
$payload = \Firebase\JWT\JWT::decode($token , SECURITY_KEY , ['HS256']);
return $payload;
}catch (Exception $exception){
$this->throwError(ACCESS_TOKEN_ERROR , $exception->getMessage());
}
}
}
and the last class is Rest.php :
require_once ("Constans.php");
class Rest
{
protected $HttpMethod;
protected $request;
protected $data;
public function __construct(){
$this->HttpMethod = $_SERVER['REQUEST_METHOD'];
if($this->checkValidhttpMethod()) {
try{
$handler = fopen('php://input', 'r');
$this->request = stream_get_contents($handler);
}catch (Exception $exception){
//TODO HANDLE EXEPTION
}
$this->validateRequest();
}
}
public function checkValidhttpMethod(){
if(empty($this->HttpMethod) or !in_array($this->HttpMethod,ACCEPTABLE_HTTP_METHOD)){
$this->throwError(NOT_VALID_HTTP_METHOD,NOT_VALID_HTTP_METHOD_Message);
}
return true;
}
public function setJsonheader(){
header("content-type: application/json");
}
public function validateRequest(){
if($_SERVER['CONTENT_TYPE'] !== 'application/json'){
$this->throwError(REQUEST_CONTENT_NOT_VALID , REQUEST_CONTENT_NOT_VALID_MESSAGE);
}
try{
$this->data = json_decode($this->request , true);
}catch (Exception $exception){
//TODO HANDLE EXEPTION
}
}
public function processAPI(){
}
public function throwError($code , $message){
$this->setJsonheader();
echo json_encode(['error' => ['status' => $code , 'message' => $message]]);
exit;
}
public function returnResponse($code , $data){
$this->setJsonheader();
echo json_encode(['response' => ['status' => $code , 'result' => $data ]]);
exit;
}
//TODO SQL injection Validate
public function validateParameter($fieldName , $value , $dataType , $required = true){
if($required && empty($value)){
$this->throwError(PARAMETR_REQUIRED,PARAMETR_REQUIRED_MESSAGE . $fieldName);
}
//TODO SQL injection
//TODO CHECK The All Data Type
switch ($dataType){
case BOOLEAN :
if(!is_bool($value)){
$this->throwError(PARAMETR_DATA_TYPE_NOT_VALID , PARAMETR_DATA_TYPE_NOT_VALID_MESSAGE . $fieldName);
}
break;
case INTEGER :
if(!is_numeric($value)){
$this->throwError(PARAMETR_DATA_TYPE_NOT_VALID , PARAMETR_DATA_TYPE_NOT_VALID_MESSAGE . $fieldName);
}
break;
case STRING :
if(!is_string($value)){
$this->throwError(PARAMETR_DATA_TYPE_NOT_VALID , PARAMETR_DATA_TYPE_NOT_VALID_MESSAGE . $fieldName);
}
break;
case DONT_CARE :
break;
default:
break;
}
return $value;
}
public function arrayFinddeep($array, $search)
{
foreach($array as $key => $value) {
if (is_array($value)) {
$sub = $this->arrayFinddeep($value, $search);
if (count($sub)) {
return $sub;
}
} elseif ($key === $search) {
return $value;
}
}
return array();
}
/**
* Get hearder Authorization
* */
function getAuthorizationHeader(){
$headers = null;
if (isset($_SERVER['Authorization'])) {
$headers = trim($_SERVER["Authorization"]);
}
else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI
$headers = trim($_SERVER["HTTP_AUTHORIZATION"]);
} elseif (function_exists('apache_request_headers')) {
$requestHeaders = apache_request_headers();
// Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization)
$requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders));
//print_r($requestHeaders);
if (isset($requestHeaders['Authorization'])) {
$headers = trim($requestHeaders['Authorization']);
}
}
return $headers;
}
/**
* get access token from header
* */
function getBearerToken() {
$headers = $this->getAuthorizationHeader();
// HEADER: Get the access token from the header
if (!empty($headers)) {
if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
return $matches[1];
}
}
$this->throwError(AUTHORIZATION_HEADER_NOT_FOUND , AUTHORIZATION_HEADER_NOT_FOUND_MESSAGE);
}
}
all queries go along queryExecute function in api.php class and recently I got that the bindParam function is not going to work fine too.
I really don't have any idea where the problem is, as In the reference said its somehow related to DB queries result. I try to use mysqli also but it did not work.
any help will be appreciated :-)
I got a codeigniter custom_result_object with this:
$user = $this->CI->db->get_where('users', array('email' => $email), 1)->custom_row_object(0,'entities\User');
and everything looks fine. I can update values with my setters.
Before I'm going to save i check my values with:
die(print_r($user));
and the values are correct.
I put my object in my update method.
$this->CI->db->update('users', $user, "id = ".$user->getId());
But the db is not updating. Am I missing something?
Thx!
EDIT:
So by using CI native db-method i can use:
public function save($user)
{
if($user->getId() == NULL){
$this->CI->db->insert('users', $user);
}else{
$this->CI->db->update('users', $user, "id = ".$user->getId());
}
}
Edit 2:
After some more checking I can see that it's not setting variables that are protected. CI is able to get the object through getters and setters but not able to save back to DB?
public function saveData($tbl,$data,$update = false,$previewStr = false){
$set_str = "NO_QUOTES()";
if(isset($data[$set_str])){
foreach($data[$set_str] as $set_key => $set_value){
$this->db->set($set_key, $set_value, FALSE);
}
unset($data[$set_str]);
}
if(isset($update[$set_str])){
foreach($update[$set_str] as $whr_key => $whr_value){
$this->db->where($whr_key." ".$whr_value,NULL,false);
}
unset($update[$set_str]);
if(is_array($update) and count($update) <= 0){
$update = true;
}
}
if($update == false){
$this->db->insert($tbl, $data);
if($previewStr){
return $this->db->last_query();
}else{
return $this->db->insert_id();
}
}else{
$result = NULL;
if(!is_array($update)){
if(is_array($data) and count($data) > 0){
foreach($data as $field => $value){
$this->db->set($field, $value);
}
}
$result = $this->db->update($tbl);
}else{
$result = $this->db->update($tbl, $data,$update);
}
if($previewStr){
return $this->db->last_query();
}else{
return $result;
}
}
}
public function delData($tbl = false,$where = array()){
if($tbl !== false){
return $this->db->delete($tbl, $where);
}else{
return false;
}
}
public function simpleQuery($query,$return_array = false,$return_single = false)
{
$ac = $this->db->query($query);
if($return_array === false){
return $ac;
}else{
if($return_single === false){
return $ac->result_array();
}else{
return $ac->row_array();
}
}
}
Use above code in your model and you i am giving you how to update it use below code in your controller you can insert update and delete by above code
$result=$this->Products_model->saveData("customer",array("customer_name"=>$name),array("cust_id"));
Can someone please help me, I get this fatal error message when I try to run the code in a browser. I have searched through various topics and couldn't find the answer. I have two very similar functions and only one of them is reporting an error. Function getById is working just fine, but function get reports an error. Here's my db.php file:
class DB {
private $db;
public $limit = 5;
public function __construct($config){
$this->connect($config);
}
private function connect($config){
try{
if ( !class_exists('Mongo')){
echo ("The MongoDB PECL extension has not been installed or enabled");
return false;
}
$connection= new MongoClient($config['connection_string'],array('username'=>$config['username'],'password'=>$config['password']));
return $this->db = $connection->selectDB($config['dbname']);
}catch(Exception $e) {
return false;
}
}
public function create($collection,$article){
$table = $this->db->selectCollection($collection);
return $result = $table->insert($article);
}
public function get($page,$collection){
$currentPage = $page;
$articlesPerPage = $this->limit;
//number of article to skip from beginning
$skip = ($currentPage - 1) * $articlesPerPage;
$table = $this->db->selectCollection($collection); **//here reports an error**
$cursor = $table->find();
//total number of articles in database
$totalArticles = $cursor->count();
//total number of pages to display
$totalPages = (int) ceil($totalArticles / $articlesPerPage);
$cursor->sort(array('saved_at' => -1))->skip($skip)->limit($articlesPerPage);
//$cursor = iterator_to_array($cursor);
$data=array($currentPage,$totalPages,$cursor);
return $data;
}
public function getById($id,$collection){
// Convert strings of right length to MongoID
if (strlen($id) == 24){
$id = new MongoId($id);
}
$table = $this->db->selectCollection($collection);
$cursor = $table->find(array('_id' => $id));
$article = $cursor->getNext();
if (!$article ){
return false ;
}
return $article;
}
public function delete($id,$collection){
// Convert strings of right length to MongoID
if (strlen($id) == 24){
$id = new \MongoId($id);
}
$table = $this->db->selectCollection($collection);
$result = $table->remove(array('_id'=>$id));
if (!$id){
return false;
}
return $result;
}
public function update($id,$collection,$article){
// Convert strings of right length to MongoID
if (strlen($id) == 24){
$id = new \MongoId($id);
}
$table = $this->db->selectCollection($collection);
$result = $table->update(
array('_id' => new \MongoId($id)),
array('$set' => $article)
);
if (!$id){
return false;
}
return $result;
}
public function commentId($id,$collection,$comment){
$postCollection = $this->db->selectCollection($collection);
$post = $postCollection->findOne(array('_id' => new \MongoId($id)));
if (isset($post['comments'])) {
$comments = $post['comments'];
}else{
$comments = array();
}
array_push($comments, $comment);
return $postCollection->update(
array('_id' => new \MongoId($id)),
array('$set' => array('comments' => $comments))
);
}
}
Firstly,Thanks for reading this. How to solve my problems
CODE
$roomid = CMS::$MySql->Query("SELECT room_id FROM user_roomvisits WHERE user_id ='".$users['id']."' ORDER BY entry_timestamp DESC LIMIT 1");
$room = CMS::$MySql->Query("SELECT caption FROM rooms WHERE id ='".$roomid."'");
AND got the error :
Catchable fatal error: Object of class mysqli_result could not be converted to string.
Here mysql class
<?php
class MySql{
private $Link;
private $Statement;
public $Result = null;
private $FetchRows = Array();
public function __construct($Data)
{
$this->Link = new MySQLi($Data['mysql.hostname'], $Data['mysql.username'], $Data['mysql.password'], $Data['mysql.database']);
}
public function Query($Query)
{
if (isset($this->Statement))
{
$this->Statement->Close();
$this->Statement = null;
}
return $this->Link->query($Query);
}
public function Prepare($Query)
{
if (isset($this->Statement))
{
$this->Statement->Close();
}
$this->Statement = $this->Link->prepare($Query);
}
public function Execute($FuncArgs = null)
{
if (!is_array($FuncArgs))
{
$FuncArgs = func_get_args();
}
$Args = Array('');
foreach ($FuncArgs as &$Arg)
{
$Args[0] .= substr(gettype($Arg), 0, 1);
$Args[] =& $Arg;
}
call_user_func_array(Array($this->Statement, 'bind_param'), $Args);
if (!$this->Statement->Execute())
{
exit('Execute Stmt Error: '.$this->Statement->error);
}
return $this->Statement;
}
public function Fetch($Columns)
{
if (!is_array($Columns))
{
$Columns = func_get_args();
}
if ($this->Result == null)
{
$this->Result = array_combine($Columns, $Columns);
$Args = Array();
foreach ($Columns as $Column)
{
$Args[] =& $this->Result[$Column];
}
call_user_func_array(Array($this->Statement, 'bind_result'), $Args);
}
$RowsLeft = $this->Statement->fetch();
if (!$RowsLeft)
{
self::Clear();
return false;
}
return $this->Result;
}
?>
these are the mysql class for the PDO maybe?
$roomid = CMS::$MySql->Query("SELECT room_id FROM user_roomvisits WHERE user_id ='".$users['id']."' ORDER BY entry_timestamp DESC LIMIT 1");
while($row=mysql_fetch_array($roomid)){
$rumid=$row[0];
}
$room = CMS::$MySql->Query("SELECT caption FROM rooms WHERE id ='".$rumid."'");
the result from mysql query is object. u cannot echo objects
use var_dump() or print_r() to view the structure of them
Codeigniter when i submit more than one option of form_multiselect(), Only just the last one that saved on database.
in my view :
<label>Trimestres :</label>
<div class="controls" >
<?php $options = array(
'trim1' => ' Premier trimestre (Janv,Fév,Mars)',
'trim2' => ' Deuxiéme trimestre (Avril,Mai,Juin)',
'trim3' => ' Troisiéme trimestre (Juill,Aout,Sept)',
'trim4' => ' Quatriéme trimestre (Oct,Nov,Déc)',
);
echo form_multiselect('trimestres', $options , $this->input->post('trimestres') ? $this->input->post('trimestres') : $participant_sport->trimestres, 'id="trim"'); ?>
</div>
</div>
in my controller :
public function inscriresport ($id = NULL)
{
// Fetch a participant or set a new one
if ($id) {
$this->data['participant_sport'] = $this->participantsport_m->get($id);
count($this->data['participant_sport']) || $this->data['errors'][] = 'participant non trouvé';
}
else {
$this->data['participant_sport'] = $this->participantsport_m->get_new();
}
// Process the form
$this->participantsport_m->array_from_post(array('matricule', 'nom', 'prenom', 'beneficiaire', 'sexe', 'telephone', 'date_naissance', 'date_inscription_sport', 'trimestres' ,'sport_montant_paye', 'sport_debut_periode', 'sport_fin_periode'));
$this->participantsport_m->save($data, $id);
redirect('admin/agent/profile/3608');
}
// Load the view
$this->data['subview'] = 'admin/agent/inscriresport';
$this->load->view('admin/_layout_main', $this->data);
}
The function array_from_post() is defined on application\core\MY_Model.php :
public function array_from_post($fields){
$data = array();
foreach ($fields as $field) {
$data[$field] = $this->input->post($field);
}
return $data;
}
in my model :
public function get_new()
{
$participant_sport = new stdClass();
$participant_sport->matricule = '';
$participant_sport->nom = '';
$participant_sport->prenom = '';
$participant_sport->beneficiaire = '';
$participant_sport->sexe = '';
$participant_sport->telephone = '';
$participant_sport->date_naissance = '';
$participant_sport->date_inscription_sport = '';
$participant_sport->trimestres = '';
$participant_sport->sport_montant_paye = '';
$participant_sport->sport_debut_periode = '';
$participant_sport->sport_fin_periode = '';
return $participant_sport;
}
Any help Please? i think that must be an array but i don't know how to do it?
i thing that i must do something like that :
foreach($_POST["strategylist[]"] as $s) {
# do the insert here, but use $s instead of $_POST["strategylist[]"]
$result=mysql_query("INSERT INTO sslink (study_id, strategyname) " .
"VALUES ('$id','" . join(",",$s) . "')")
or die("Insert Error: ".mysql_error());
}
to insert more than one option selected in one row but i don't know how to do it in codeigniter
the get() function :
public function get($id = NULL, $single = FALSE){
if ($id != NULL) {
$filter = $this->_primary_filter;
$id = $filter($id);
$this->db->where($this->_primary_key, $id);
$method = 'row';
}
elseif($single == TRUE) {
$method = 'row';
}
else {
$method = 'result';
}
if (!count($this->db->ar_orderby)) {
$this->db->order_by($this->_order_by);
}
return $this->db->get($this->_table_name)->$method();
}
If select name (in HTML tag) is trimestres it will always remember last selection. Use trimestres[] as a name to get array with all selected values`
<select name="trimestres[]" multiple …
By the way:
I don't know how array_from_post() works but it has to change trimestres[] values to one string to save all of them in one column. It is hard to search/add/delete one value if all values are in one string. It is "SQL Antipattern". You could do another table in database for trimestres - one value in one row.
Edit:
It will change all arrays into string with elements connected by ,. Not tested.
public function array_from_post($fields){
$data = array();
foreach ($fields as $field) {
// print_r($this->input->post($field));
if( is_array( $this->input->post($field) ) ) {
$data[$field] = join(",", $this->input->post($field));
} else {
$data[$field] = $this->input->post($field);
}
// print_r($data[$field]);
}
return $data;
}
Edit:
Not tested.
public function inscriresport ($id = NULL)
{
// Fetch a participant or set a new one
if ($id) {
$this->data['participant_sport'] = $this->participantsport_m->get($id);
count($this->data['participant_sport']) || $this->data['errors'][] = 'participant non trouvé';
// explode to array
// print_r($this->data['participant_sport']->trimestres); // test before explode
// $this->data['participant_sport']['trimestres'] = explode(",", $this->data['participant_sport']['trimestres']);
$this->data['participant_sport']->trimestres = explode(",", $this->data['participant_sport']->trimestres);
// print_r($this->data['participant_sport']->trimestres); // test after explode
} else {
$this->data['participant_sport'] = $this->participantsport_m->get_new();
}
// rest of code
}
There is a easy way to solve this problem that I found today.
you have to serialize the $_POST['trimestres'] array just after array_form_post .
the this array will save to database as a serialize string.
public function inscriresport ($id = NULL)
{
// Fetch a participant or set a new one
if ($id) {
$this->data['participant_sport'] = $this->participantsport_m->get($id);
count($this->data['participant_sport']) || $this->data['errors'][] = 'participant non trouvé';
}
else {
$this->data['participant_sport'] = $this->participantsport_m->get_new();
}
// Process the form
$this->participantsport_m->array_from_post(array('matricule', 'nom', 'prenom', 'beneficiaire', 'sexe', 'telephone', 'date_naissance', 'date_inscription_sport', 'trimestres' ,'sport_montant_paye', 'sport_debut_periode', 'sport_fin_periode'));
$data['trimestres'] = serialize($_POST['trimestres']);
$this->participantsport_m->save($data, $id);
redirect('admin/agent/profile/3608');
}
// Load the view
$this->data['subview'] = 'admin/agent/inscriresport';
$this->load->view('admin/_layout_main', $this->data);
}
When you just need this data back form database just use php unserialize() function .
Hope it will help to do this easily ....
-thanks