I have made a class function which will get rows from a table in my database along with an optional argument. This works when getting a single row however I cant get this to work when multiple rows are returned.
Here is what is in the Users class
public function getUsers($filter="") {
$Database = new Database();
if($filter == 'male')
$extra = "WHERE gender = 'm'";
$sql = "SELECT *
FROM users
$extra";
if ($Database->query($sql))
return $Database->result->fetch_assoc();
else
return false;
}
Database Class
class Database {
private $db = array();
private $connection;
private $result;
public function __construct() {
$this->connect();
}
public function connect() {
$this->connection = mysqli_connect('mysql.com', 'username', 'pass');
mysqli_select_db($this->connection, 'database');
}
public function query($sql) {
$this->result = mysqli_query($this->connection, $sql);
return $this->result;
}
This is the code used to try and display the rows
if ($student = $User->getUsers($filter)) {
echo "<table>\n";
echo "<tr><td>Col 1</td><td>Col 2</td><td>Col 3</td><td>Col 4</td><td></td><td></td></tr>";
foreach($student as $row) {
echo "<tr>";
echo "<td>$row[col1]</td>";
echo "<td>$row[col2]</td>";
echo "<td>$row[col3]</td>";
echo "<td>$row[col4]</td>";
echo "<td>$row[col5]</td>";
echo "<td>$row[col6]</td>";
echo "</tr>\n";
}
echo "</table>";
}
(I'm learning OO PHP, bear with me)
I'm still learning OOP but I have used this:
protected $connection, $result, $_numRows;
public function query($sql)
{
$this->result = mysql_query($sql, $this->connection);
$this->_numRows = mysql_num_rows($this->result);
}
/*
* #desc get result af query
*
* #returns string $result
*/
public function getResult()
{
return $this->result;
}
/*
* #desc Return rows in table
* #returns int $_numRows
*/
public function numRows()
{
return $this->_numRows;
}
/*
* #desc Count rows and add to array
* #return string $rows array
*/
public function rows()
{
$rows =array();
for ($x=0; $x < $this->numRows(); $x++) {
$rows[] = mysql_fetch_assoc($this->result);
}
return $rows;
}
Then you could use something like this to get the rows:
public function getUsers($filter="") {
$Database = new Database();
if($filter == 'male')
$extra = "WHERE gender = 'm'";
$sql = "SELECT *
FROM users
$extra";
if ($this->numRows() == 0) {
echo "No rows found";
} else {
foreach ($this->rows() as $b) {
$c = array('something' => $b['col']);
}
return $c;
}
Modify the last part to suit your needs.
It's not clear in your code where $result comes from...
You should call the fetch_assoc() method of an object returned by:
$mysqli->query($query)
Why are you using $result->fetch_assoc() twice? you are returning an array.. you should deal with $student.
Related
Hi there still new to PHP and struggling with something really basic and it's frustrating me cause I can't see the error. I have read the PHP manual on passing array of objects.
class Customer{
public $companyId;
public $customerId;
public $name;
public function __construct($companyId,$customerId,$name)
{
$this->companyId = $companyId;
$this->customerId = $customerId;
$this->name = $name;
}
}
class CustomersDB
{
...
/**
* #return Customer[]
*/
public function getCustomers($search_str): array {
$resultObj = array();
$result = NULL;
try {
if (! $this->db) {
die('Database handle not defined') ;
}
if ($search_str && ! empty($search_str)) {
$result = $this->ListCustomers(Utils::COMPANY_ID, $search_str, $this->db);
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$_tmp = new Customer($row['CompanyID'],
$row['CustomerID'],
$row['CustomerName']);
// $resultObj.push($_tmp);
$resultObj[] = $_tmp;
}
}
} catch (Exception $e) {
// echo Utils::logMsgtoWeb($e->getTraceAsString());
} finally {
$result = NULL;
}
return $resultObj;
}
}
use Respect\Rest\Routable;
class Customers implements Routable {
/**
*
* Can pass in a partial string to search for a customer
* or pass in an ID for a specific match.
*/
public function get($searchStr){
// header('Content-type: application/json');
$result = $this->custdb.getCustomers($searchStr); // ERRORS HERE
if ($result && ! empty($result)) {
return json_encode( $result);
} else {
return NULL;
}
}
}
I get this error: PHP Recoverable fatal error: Object of class Scheduler\db\CustomersDB could not be converted to string in Customers.php.
Any help would be appreciated.
So i have this class for loading data from my MySQL database :
class Db {
protected static $connection;
public function connect() {
if(!isset(static::$connection)) {
$config = parse_ini_file('config.ini');
static::$connection = new mysqli('localhost',$config['username'],$config['password'],$config['dbname']);
}
if(static::$connection === false) {
return false;
}
return static::$connection;
}
public function query($query) {
return $this->connect()->query($query);
}
public function select($query) {
$rows = array();
$result = $this->query($query);
if($result === false) {
return false;
}
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
return $rows;
}
public function error() {
return $this->connect()->error;
}
public function quote($value) {
return "'" . $this->connect()->real_escape_string($value) . "'";
}
}
I use that class like this :
$db = new Db();
$rows = $db -> select("SELECT name, shortlink FROM `test` WHERE id=3");
It gives me an array with the data.
The problem is that i want to pull out specific data, for example the shortlink field.
How do i do that? I have tried echo $rows['shortlink'], but that gives me the following error :
Undefined index: shortlink
So how do I print specific data?
Your returned $rows columns is an array of associative arrays, to pull out shortlink data returned from the query you have to do something like this:
foreach($rows as $row) {
echo $row['shortlink'];
}
I am trying to write my own MVC Framework using this tutorial. Everything worked fine and i completed the tutorial with no issues.
However later i decided to use PDO (PHP Data objects) instead of mysql() functions for Database Operations. So i modified My sqlQuery.php file to use PDO istead of mysql functions.
sqlQuery.php
<?php
class SQLQuery {
private $_dbHandle;
private $_result;
/**
* Connects to database
*
* #param $address
* #param $account
* #param $pwd
* #param $name
*/
function connect($address, $account, $pwd, $name) {
try{
$this->_dbHandle = new PDO("mysql:host=$address;dbname=$name", $account, $pwd);
}catch (PDOException $e) {
die($e->getCode() . " : " . $e->getMessage());
}
}
/** Disconnects from database **/
function disconnect() {
$this->_dbHandle = null;
}
function get($whereClause = array()) {
$query = "select * from $this->_table";
if(is_array($whereClause) && count($whereClause)){
$query .= " where ";
foreach($whereClause as $column=>$value)
$query .= " $column = $value";
}else if(is_int($whereClause)){
$query .= " where id = $whereClause ";
}
return $this->query($query);
}
/**
* Custom SQL Query
*
* #param $query
* #return array|bool
*/
function query($query) {
$this->_result = $this->_dbHandle->query($query);
$this->_result->setFetchMode(PDO::FETCH_CLASS, $this->_model);
if (preg_match("/select/i",$query)) {
$result = array();
$numOfFields = $this->_result->rowCount();
if($numOfFields > 1){
while($result[] = $this->_result->fetch()){
}
}else{
$result = $this->_result->fetch();
}
return $result;
}
return true;
}
}
Now when In my Controller when i print $this->Item->get() I get all the results in my database as Objects of Items Model and $this->Item->get(2) gives me the item object with id=2 as expected.
However, I don't like the idea that my API needs to be to call an additional method get() to get the objects of the Items Model, Instead it makes more sense that when a Items Model is initialized i get the desired object and so my API can be $this->item->mycolumnName.
To achieve this i tried to move the get() call in the Models constructor like this :
model.php
<?php
class Model extends SQLQuery{
protected $_model;
function __construct() {
$this->connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
$this->_model = get_class($this);
$this->_table = strtolower($this->_model)."s";
$this->get();
}
function __destruct() {
}
}
However this gives me a Fatal error
Fatal error: Maximum function nesting level of '256' reached, aborting! in /var/www/html/FitternityAssignment/library/sqlquery.php on line 59
I don't know what i have done wrong.
The issue is line 59: while($result[] = $this->_result->fetch()){
function query($query) {
$this->_result = $this->_dbHandle->query($query);
$this->_result->setFetchMode(PDO::FETCH_CLASS, $this->_model);
if (preg_match("/select/i",$query)) {
$result = array();
$numOfFields = $this->_result->rowCount();
if($numOfFields > 1){
while($result[] = $this->_result->fetch()){
}
}else{
$result = $this->_result->fetch();
}
return $result;
}
return true;
}
Let's narrow in on the issue:
while($result[] = $this->_result->fetch()){
}
Infinite loop.
When fetch() returns something, then it is added to $result, because $result is an array, and then of course it evaluates to true because the size of $result grows each time a fetched result is added.
$results = [];
while($row = $this->_result->fetch()){
$results[] = $row; // or whatever you need to do with the row
}
Might work. I say might because it depends on what $this->_result->fetch() returns when no results are left. I'll assume false or null, in which case the above will work, because when there are no more results then fetch() will return null or false and $row will then evaluate to false.
Hi I have a couple of php classes. And I am passing a connection to a MySql database.
When I make an instance of the firs class and try to call the invoice class with the method getinvoicedetails() I get error "Command out of sync; you can't run this command".
Any help wil be appreciated.
Here is the code:
<?php //Invoicectrl class
class invoicectrl
{
// define properties
public $invoices = Array();
public $connection;
public $userID;
public $ownerID;
// constructor
public function __construct($userIDin,$ownerIDin) {
$this->userID = $userIDin;
$this->ownerID = $ownerIDin;
}
//function to set connection to db
public function setconnection($conn){
$this->connection = $conn;
}
public function getinvoicelist(){
$res = Array();
$invIDs = Array();
//Get list of invoicenumbers and invoiceIDs
$queryd = "CALL sp_getOwnersInvNumIDs (".$this->ownerID.")";
$result = $this->connection->query($queryd) or die($this->connection->error.__LINE__);
// GOING THROUGH invoices and getting there data
$o=0;
while($row = $result->fetch_assoc()) {
$invIDs[$o]['ID'] = $row['invoiceID'];
$invIDs[$o]['NR'] = $row['invoicenumber']; }
$result->free();
//Set each invoice own info
for($i=0;$i<=count($invIDs)-1;$i++){
$res[$i] = new invoice($invIDs['ID'],$invIDs['NR']);
$res[$i]->setconnection($this->connection);
$res[$i]->getinvoicedetails();
}
return $res;
}
}
?>
And here is the invoice class
<?php //Invoice class
class invoice
{
// define properties
public $invoiceID;
public $invoicenumber;
public $itemIDs=Array();
public $items= Array();
public $customerID;
public $cust_company;
public $cust_name;
public $cust_email;
public $cust_adress1;
public $cust_adress2;
public $cust_adress3;
private $connection;
// constructor
public function __construct($invoiceIDin,$invoicenumberin) {
$this->invoiceID = $invoiceIDin;
$this->invoicenumber = $invoicenumberin;
}
//function to set connection to db
public function setconnection($conn){
$this->connection = $conn;
}
//sets all invoices details
public function getinvoicedetails(){
//Get customer on invoice
$queryd = "select customerID FROM Accounting_Invoice_Customer where invoiceID =".$this->invoiceID."";
$result = $this->connection->query($queryd) or die($this->connection->error.__LINE__);
while($row1 = $result->fetch_assoc()) {
$this->customerID = $row1['customerID'];
}
$result->free();
//Get list of items on invoice
$queryd = "call sp_getItems(".$this->invoiceID.")";
$result = $this->connection->query($queryd) or die($this->connection->error.__LINE__);
$o=0;
while($row2 = $result->fetch_assoc()) {
$this->items[$o]['itemID'] = $row2['itemID'];
//$this->items[$o]['itemnumber'] = $row['itemnumber'];
//$this->items[$o]['itemdescription'] = $row['itemdescription'];
//$this->items[$o]['itempricewotax'] = $row['itempricewotax'];
$o++;
}
$result->free();
}
}
?>
When you run a SQL request, you have to get through the whole result or to close the cursore before sending another request.
The best thing to do, here is to get the whole result at first and then traverse it with a foreach loop to be able to send the second request.
Moreover, it should be a good idea to use INNER JOIN in your sql query.
$queryd = "CALL sp_getOwnersInvNumIDs (".$this->ownerID.")";
$result = $this->connection->query($queryd) or die($this->connection->error.__LINE__);
$invIDs = $result->fetch_all();
$res = array();
foreach($invIDs as $inv){
$inv = new invoice($invIDs['invoiceID'],$invIDs['invoiceNumber']);
$inv->setconnection($this->connection);
$inv->getinvoicedetails();
$res[] =$inv;
}
I can do this when selecting a single row fine but cant quite get my head around doing this for multiple rows of data.
For the single row I simply instantiate a new object that does a number of operations behind the scenes that bascially produces a row from the database as our object.
Example:
$object = new Classname($param);
foreach($object->row as $key=>$value) {
echo $key.":".$value."\n";
}
//output
id:1
firstname:steve
lastname:took
etc...
Any clever people here able to point me in the right direction please?
NOTE: just want to be able to create an object for each row rather than the one object with nested arrays
EDIT: sorry $object->row is a member of the class that stores selected row from the database
If I got you the answer is pretty simple mysql_fetch_object
Example:
while ($row = mysql_fetch_object($result)) {
echo $row->user_id;
echo $row->fullname;
}
Why don't you consider to use an ORM (Object Relational Mapper), like Doctrine or Propel?
I prefer Doctrine: http://www.doctrine-project.org/
Enjoy! :)
Here is an example
class users extends db {
public $users_id = 0;
public $users_group = 0;
public $users_firstname = 0;
public $users_lastname = 0;
public function open($id) {
if (is_numeric($id)) {
$sql = "SELECT * FROM users WHERE users_id = '$id'";
$res = parent::DB_SELECT($sql);
if (mysql_num_rows($res) <> 1) {
return 0;
}
} else {
$sql = "SELECT * FROM users " . $id;
$res = parent::DB_SELECT($sql);
if (mysql_num_rows($res) <= 0) {
return 0;
}
}
$data = array();
while ($row = mysql_fetch_array($res)) {
$this->users_id = $row['users_id'];
$this->users_group = $row['users_group'];
$this->users_firstname = $row['users_firstname'];
$this->users_lastname = $row['users_lastname'];
$data[] = (array) $this;
}
return $data;
}
public function setUsersId($users_id) { $this->users_id = addslashes($users_id); }
public function getUsersId() { return stripslashes($this->users_id); }
public function setUsersGroup($users_group) { $this->users_group = addslashes($users_group); }
public function getUsersGroup() { return stripslashes($this->users_group); }
public function setUsersFirstname($users_firstname) { $this->users_firstname = addslashes($users_firstname); }
public function getUsersFirstname() { return stripslashes($this->users_firstname); }
public function setUsersLastname($users_lastname) { $this->users_lastname = addslashes($users_lastname); }
public function getUsersLastname() { return stripslashes($this->users_lastname); }
}
You could use MySQLi.
// Connect
$db = new mysqli('host', 'user', 'password', 'db');
// Query
$users = $db->query('SELECT * from users');
// Loop
while($user = $users->fetch_object()) {
echo $users->field;
}
// Close
$users->close();
$db->close();
More info here: http://php.net/manual/en/book.mysqli.php