So I started to get a little more practice in php and want to create a object oriented forum. Therefor I want to have a Database class such like:
<?php
class Database {
public $databaseConnection;
function __construct(){
$this->databaseConnection = new PDO('sqlite:test.sq3', 0, 0);
$this->databaseConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$params = NULL;
$pdoStatement = $this->databaseConnection->prepare('CREATE TABLE IF NOT EXISTS user(
id INTEGER PRIMARY KEY,
username VARCHAR(40) NOT NULL UNIQUE,
numberoflogins INTEGER DEFAULT 0,
bannedstatus BOOLEAN DEFAULT FALSE,
dateofjoining TIME
)');
$pdoStatement->execute(array_values((array) $params));
}
function query($sql, $params = NULL){
$s = $this->databaseConnection->prepare($sql);
$s->execute(array_values((array) $params));
return $s;
}
function insert($table, $data){
self::query("INSERT INTO $table(" . join(',', array_keys($data)) . ')VALUES('. str_repeat('?,', count($data)-1). '?)', $data);
return $this->databaseConnection->lastInsertId();
}
}
Then I do this in the same script:
$database = new Database();
$database->insert('user',array( 'id' => 0,
'username' => 'gulaschsuppe',
'numberoflogins' => 23,
'bannedstatus' => TRUE,
'dateofjoining' => time()));
$searchID = 0;
$userData = $database->query('SELECT username FROM user WHERE id = 0');
$username = $userData->fetchAll();
print_r(array_values($username));
?>
I just wanted to see how things working. The most important part of the code is the class. I needed a little bit time to figure out how I get the information I wanted. This is what I get.
Array ( [0] => Array ( [username] => gulaschsuppe [0] => gulaschsuppe ) )
Everythings working, but I donĀ“t think this is best way to get the informations. I get an Array with an Array. Also, now there is no validation but first I want to focus on the functions query and insert.
So, can you explain how the last part with username => g. [0] => g. occured ?
I would like to know how I can improve the functions and please tell me when I do something totally wrong.
Array (
[0] => Array (
[username] => gulaschsuppe
[0] => gulaschsuppe
)
)
You're getting the result with both names columns (so you could do $row['username']) and numerically (so you can do $row[0]). This is the default PDO behavior. You need to use the PDO::FETCH_* constants in order to change the fetched results. PDO::FETCH_BOTH is the default value.
You can either set it when you're fetching:
$username = $userData->fetchAll(PDO::FETCH_ASSOC);
Or globally at some point:
$this->databaseConnection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
In the case that you want only a single column, you can use this fetch mode:
$usernames = $userData->fetchAll(PDO::FETCH_COLUMN);
// $usernames = array('gulaschsuppe');
This fetches only a single column for each row, without wrapping each result in another array (column 0 is fetched by default).
See the PDOStatement::fetch() documentation for more details.
Related
I have two PHP arrays in a section of a website I'm building for a class. One contains data that I created with a simple foobar array bit, and the other is created from a fetchAll() PDO call. I can't access the PDO array's element for some reason, so I created a sample array and called var_export() on both arrays to see if there were any differences. Here is the code:
if ($dao->userExistsLogin($_POST["email"], $_POST["password"]))
{
$useremail = $_POST["email"];
$_SESSION["authenticated"] = "true";
$logger->LogDebug("email from post array in login handler: " . $_POST["email"]);
$user_results = $dao->getIDFromEmail($useremail);
$logger->LogDebug(print_r($user_results, true));
$array = [
"foo" => "bar",
"bar" => "foo",
];
$logger->LogDebug(var_export($array, true));
$logger->LogDebug(var_export($user_results, true));
$logger->LogDebug(gettype($user_results));
$_SESSION['user_id'] = $user_results['id'];
header("Location: http://localhost/WIWO/user_account.php");
}
The GetIDFromEmail function is here:
public function getIDFromEmail($email)
{
$conn = $this->getConnection();
$getIDFromEmailQuery = "SELECT * FROM user WHERE email=:email";
$query = $conn->prepare($getIDFromEmailQuery);
$query->bindParam(":email", $email);
$query->execute();
$result = $query->fetchAll(PDO::FETCH_ASSOC);
$this->logger->LogDebug(print_r($result, true));
return $result;
}
And here's what's in my logger from the var_export() commands:
2020-10-31 17:57:10 - DEBUG --> array (
'foo' => 'bar',
'bar' => 'foo',
)
2020-10-31 17:57:10 - DEBUG --> array (
0 =>
array (
'id' => '251',
'email' => 'heck',
'institution' => 'heck',
'access' => '1',
),
)
Why can I not access the second array at $_SESSION['user_id'] = $user_results['id'];? For some reason that line totally fails to do anything. I know the session is started and correct because other variables stored in the SESSION superglobal are showing up correctly, but the user_id never gets set. Does it have something to do with "0 =>" showing up in the var_export() of the second array? I notice that doesn't show up in the first array - is the second array malformed or something?
You're using PDOStatement::fetchAll(), which will always return an array of rows. Instead you might want to use PDOStatement::fetch() which will return precisely one row.
I haven't seen the userExistsLogin() method, but you could probably simplify your code if you have that method return the user id on success, and something falsey (e.g. 0, FALSE or NULL) on error. This will not only reduce code complexity, but it will reduce database load as well.
Since moving session handling over to the database, the $_SESSION array doesn't seem to hold any values which I think is how sessions behave in PHP once the implementation is moved to DB.
This is causing quite a headache for me now. I'm not able to access the username of the user logged in via the details stored in the DB.
Here's my implementation of a function to retrieve the details of a user from the DB.
public function getUser($id, $db) {
$dbobj->query("SELECT * FROM SESSION WHERE id = $id);
$result = $dbobj->res();
return $result['data']['use'];
}
$result holds the values int he following format
array(1) (
[0 => array(3) (
[id => (string) 3fgg67bbsd77bVVgh
[access => (string) 14567893546
[data => (string) luser|s:5"Marke";
)
)
I would like $temp to hold the value "Marke". How should I parse the resultest returned?
I'd appreciate any help please.
resultset() function might be not exist.
So you can use this code:
public function getSessionUserName($id, $dbobj) {
$lcid = $id;
$dbobj->query("SELECT * FROM SESSION WHERE id = :sessid");
$dbobj->bind(':sessid', $lcid);
// execute query
$dbobj->execute();
// Commented this line
//$result = $dbobj->resultset();
// Use fetch() method
$result = $dbobj->fetch();
if ($result) {
//$temp= $result['data']['luser'];
$temp= $result['luser']
return $temp;
}
}
$result will generate following type of output (Output will be based on fields ):
Array
(
[id] => 3fgg67bbsd77bVVgh
[0] => 3fgg67bbsd77bVVgh
[access] => 14567893546
[1] => 14567893546
[luser] => Marke
[2] => Marke
)
I'm having an issue using the Quickbase API to perform the following:
SELECT 1, 2, 3 FROM table AA that has column BB = 1
foreach record {
Insert 1, 2, 3 into table ZZ.
}
function add_children($opportunity_id) {
global $config;
$qbc = new QuickBase($_SESSION['qb_username'] ,
$_SESSION['qb_password'],
true,
$config['AA'],
$config['debug'],
$config['app_token']);
$xml = $qbc->do_query("{'" . $config['AA'] . "'.EX.''}", 0, 0, 'a', 0, '', '');
$records = array();
foreach($xml->record as $record) {
$r = array();
$r['record_id'] = $record->record_id_;
$r['account_number'] = $record->account_number;
$records[] = $r;
$xml = $qbc->add_record($records[]);
}
}
First, I'm assuming that you're using this PHP SDK by QuickbaseAdmirer https://github.com/QuickbaseAdmirer/QuickBase-PHP-SDK. There are a few potential problems with your code.
Double check that your constructor is correct. Unless you've modified it, the Quickbase constructor in the SDK (again that I'm assuming you're using) takes user name, password, xml, database id, and then token in that order. Whatever value is in $config['debug'] may be taken as the token and the value of $config['app_token'] may be taken as your realm. Also, $config['AA'] as used in the constructor should be a string of random seeming characters like "bbqn1y5qv". Here's the constructor in the SDK for reference:
public function __construct($un, $pw, $usexml = true, $db = '', $token
= '', $realm = '', $hours = '')
Your query $xml = $qbc->do_query("{'" . $config['AA'] . "'.EX.''}", 0, 0, 'a', 0, '', ''); is not returning any records because $config['AA'] is both being used as your DBID (in the constructor) and your field ID in the query. The DBID must be a string and the field ID must be an integer that corresponds to the field you're making the query for. For example, if you wanted to return records created today your query would be '{1.IR.today}' because 1 is always the field ID for date created. It's also not returning any records because the SDK requires queries be passed as an array of arrays. So, my records created today query needs to be rewritten as:
$query= array(
array(
'fid' => '1',
'ev' => 'IR'),
'cri' => 'today'),
);
You'll also need to pass a string of period separated values to the clist parameter of the method or leave it blank for the table defaults. For example, if I wanted to get the date created and record ID for all records in this table sorted by date ascending, I would use this:
$query= array(
array(
'fid' => '3',
'ev' => 'GT'),
'cri' => '0'),
);
$xml = $qbc->do_query($query, '', '', '1.3', '1', '', 'sortorder-A');
You can read up more on the Quickbase API, and do_query specifically, here http://www.quickbase.com/api-guide/index.html#do_query.html
The add record API call takes pairs of field IDs and values. The SDK handles that by taking an array of arrays with 'fid' and 'value' pairs. Assuming you want to put the value of $record->record_id_ in field #37 and $record->account_number in field #30 your code should look like this:
foreach($xml->record as $record) {
$records= array(
array(
'fid' => '37', //Whatever field you want to store the value to
'value' => $record->record_id_),
array(
'fid' => '30',
'value' => $record->account_number),
);
$xml = $qbc->add_record($records);
}
Throw in a print_r($xml); at the end and you can see any response from Quickbase for debugging. You should get something like this for a success:
SimpleXMLElement Object ( [action] => API_AddRecord [errcode] => 0 [errtext] => No error [rid] => 81 [update_id] => 1436476140453 )
The way your code is presented, you may not get the results you expect. Your do query and add record method calls are performed on the same table and that isn't normally what someone would want. Usually, the goal is to perform a do query on one table and then use that data to add records in a different table. If that's the case, you'll need to change the database ID in your $qbc object before you preform the add record call. This is easy enough to do with $qbc->set_database_table('DBID'); where DBID is the target table ID (which should be a string of random seeming characters like "bbqn1y5qv").
Best of luck!
i am trying to call m custom function repeatedly with same or different parameters value,inside foreach loop parameters depending upon value to key provided my foreach.
foreach ($result as $r) {
if($r->marks1==null || $r->marks2==null)
{
echo $r->p_code;
$toUpdate=$this->getResult($username,$r->p_code);
print_r($toUpdate);
}
}
but when i am printing the latest query result i am getting $toUpdate get appended by latest parameter query.
Array
(
[query] => select * from `result` where (`studentid` = ?) and `studentid` = ? and `ccode` = ? and `a_no` = ? order by `date` desc limit 1
[bindings] => Array
(
[0] => XYZ
[1] => XYZ
[2] => course123code
[3] => 12321
)
[time] => 0.18
)
my user name getting same, while course code is get overrides while finding second result.
i want to get the result getResult() inside foreach loop so that it may give the related result for different parameters value.
public function getLatestResult($username,$course_code)
{
$user=new User;
$currentDetailOfUser=$this->userCurrentDetail($username);
$userdetail=json_decode($currentDetailOfUser,true);
$username =$userdetail['username'];
$studentid =$userdetail['userid'];
$studentBatch =$userdetail['batch'];
$programCode =$userdetail['programCode'];
$activeSemester =$userdetail['activesemester'];
$condition_key=array(
'studentid' =>$studentid
);
$getCurrentResult1 =$user->getDetail('student_result',$condition_key);
$getCurrentResult2 =$user->getDetail('student_result',$condition_key);
$resultAssessment1=$getCurrentResult1->where('studentid',$studentid)->where('course_code',$course_code)->where('assignment_no',1)->orderBy('date','Desc')->limit(1)->get();
$resultAssessment2=$getCurrentResult2->where('studentid',$studentid)->where('course_code',$course_code)->where('assignment_no',2)->orderBy('date','Desc')->limit(1)->get();
$recentResult=array_merge($resultAssessment1,$resultAssessment2);
return $recentResult;
}
This is a bad practice if you are fetching data from db inside the foreach loop.
BTW you can do this by keeping all new result in same array by index its some unique value, it will be look like this-
$toUpdate=array();
foreach ($result as $r) {
if($r->marks1==null || $r->marks2==null)
{
echo $r->p_code;
$toUpdate[$r->p_code]=$this->getResult($username,$r->p_code); // added $r->p_code as index to Array - $toUpdate
}
}
print_r($toUpdate); // this will give all the related result according your parameters
[UPDATE]
Try using unset($yourarray) for your next request these array will be new and they assign the new value each time -
public function getLatestResult($username,$course_code)
{
$user=new User;
$currentDetailOfUser=$this->userCurrentDetail($username);
$userdetail=json_decode($currentDetailOfUser,true);
$username =$userdetail['username'];
$studentid =$userdetail['userid'];
$studentBatch =$userdetail['batch'];
$programCode =$userdetail['programCode'];
$activeSemester =$userdetail['activesemester'];
$condition_key=array(
'studentid' =>$studentid
);
$getCurrentResult1 =$user->getDetail('student_result',$condition_key);
$getCurrentResult2 =$user->getDetail('student_result',$condition_key);
$resultAssessment1=$getCurrentResult1->where('studentid',$studentid)->where('course_code',$course_code)->where('assignment_no',1)->orderBy('date','Desc')->limit(1)->get();
$resultAssessment2=$getCurrentResult2->where('studentid',$studentid)->where('course_code',$course_code)->where('assignment_no',2)->orderBy('date','Desc')->limit(1)->get();
unset($currentDetailOfUser);
unset($userdetail);
unset($condition_key);
unset($recentResult);
$recentResult=array_merge($resultAssessment1,$resultAssessment2);
return $recentResult;
}
Hope this can help you.
I'm having an issue where I call the result_array() function on n query object from in codeigniter:
$this->db->select(array('a','b','c'));
$query = $this->db->get('basic');
print_r($query->list_fields());
$test = $query->result_array();
print_r($query->list_fields());
When I run this code, or:
$query = $this->db->get('basic');
print_r($query->list_fields());
print_r($query->list_fields());
or:
$query = $this->db->get('basic');
$test = $query->result_array();
print_r($query->list_fields());
The second list_fields() function always returns an array size 0, the first returns the correct list of field names.
In the last example where there is only one list_fields() function, the array is again size zero.
Any guidance in this matter will be greatly appreciated. I need the list_fields() function to be accessible after I read the result_array().
Here is the result of the first block of code:
Array
(
[0] => site_id
[1] => institution
[2] => caller
[3] => call_complete
[4] => call_details
[5] => id
[6] => timestamp
)
Array
(
)
Thank you, for your help
That looks to be a bug in the database driver. For example, in CI_DB_mysqli_result:
public function list_fields()
{
$field_names = array();
while ($field = $this->result_id->fetch_field())
{
$field_names[] = $field->name;
}
return $field_names;
}
A subsequent call will return array() because the while loop seeks over all the fields and leaves the pointer at the end of the list.
However, in the result class, result_id is public, so you can use mysqli_result::field_seek:
$query = $this->db->get('basic');
var_dump($query->list_fields());
// this should be called before any call to list_fields()
$query->result_id->field_seek(0);
var_dump($query->list_fields());
However, this is bad practise, as this only works for mysqli; for mysql, you'll need this:
mysql_field_seek($query->result_id, 0);
and for mssql:
mssql_field_seek($query->result_id, 0);
The correct way to do this is really to fix it in the database drivers. See this pull request :-)