How do I set a DB2_SCROLLABLE with hold in PHP? - php

I've been working on creating an object oriented database call class for practice and I've been trying to figure out how to incorporate a scrollable cursor properly. I would like to be able to call this function in order to grab the next 10 records or a different function for the previous 10 records. I've gotten to the point where I can specify an offset for the records through the scrollable cursor but I cannot call the same function again to get the next set without passing in an incremented offset value.
How would I go about being able to specify a number of records per page and simply call getNextSet() or getPrevSet() in order to get the results I want.
My current line of thinking is setting a static variable somewhere and incrementing/deincrementing or resetting it accordingly then use that as the offset value in the functions. However, I believe I heard there was an issue with using static variables in instantiated classes.
Here's the code so far:
<?php
$i5DBconn = db2_connect("*LOCAL", "", "");
if (!$i5DBconn) {
echo "Database Connection failed. SQL Err:";
echo db2_conn_error();
echo "<br>";
echo db2_conn_errormsg();
die();
}
class queryDB{
var $query;
var $outputFunction;
var $parameters;
function performDBCall(){
global $i5DBconn;
$dbStatement = db2_prepare($i5DBconn, $this->query, array('cursor' => DB2_SCROLLABLE));
$i = 1;
foreach ($this->parameters as $param) {
db2_bind_param($dbStatement, $i, 'param', DB2_PARAM_IN);
$i++;
}
$result = db2_execute($dbStatement);
if (!$result){
echo "$this->query failed!. ";
echo 'SQLSTATE value: ' . db2_stmt_error();
echo ' Message: ' . db2_stmt_errormsg();
}
return $dbStatement;
}
}
class invoiceCall extends queryDB {
function testQueryFormatter($dbResultSet, $dataOffset){
$zebraStriping = 1;
?>
//snipped header row formatting
<?php
$rowLimit = 10;
while(($rowData = db2_fetch_array($dbResultSet, $dataOffset)) && ($zebraStriping < $rowLimit)){
list($dataNames) = $rowData;
?>
//snipped data formatting
<?php
$dataOffset++;
}
}
}
$offsetVal = 5;
$testQuery = new invoiceCall();
$testQuery->query = "select invoice#, status, amountpaid, amountbilled, invoicedate, paydate, custname, termofpay, balance from TESTSCHEMA.SAMPLE_INVOICE_TABLE";
//$testQuery->parameters = [8000001];
$resultSet = $testQuery->performDBCall();
$testQuery->testQueryFormatter($resultSet, $offsetVal);
?>
If there are also some coding practices I could improve on, let me know as I am starting my first real journey into Object Oriented PHP.

Related

Why is Tinybutstrong Mergeblock giving me the error: 'item before ... is neither an object nor an array. Its type is NULL..'

I am trying to use Tinybutstrong to merge a template with an sql query result. Below is the PHP code being run, the custom database reader plugin I am attempting to use, the template file and the error message.... The code is being run from within a wordpress site, hence the use of the wpdb object and the custom database reader plugin.
The code being run:
include_once('wp-content/themes/mine/tbs_plugins/tbsdb_wpdb.php');
$link = new wpdb($username, $password, $dbname, $servername);
$sql_query = 'select year from mytable limit 10';
$TBS = new clsTinyButStrong;
$TBS->LoadTemplate('wp-content/themes/mine/templates/mytemplate.htm');
$TBS->MergeBlock('blk1', $link, $sql_query);
$TBS->Show();
Custom database reader plugin tbsdb_wpdb.php:
<?php
function tbsdb_wpdb_open(&$source,&$query) {
$source->get_results($source->prepare($query),ARRAY_A);
return $source;
}
function tbsdb_wpdb_fetch(&$Rs,$num) {
if ($num<=$Rs->num_rows) {
return $Rs->get_row(null,ARRAY_A,$num-1) ;
}
else {
return False ;
}
}
function tbsdb_wpdb_close(&$source) {
// not needed
}
?>
Part of Template mytemplate.htm:
.
.
.
[blk1;block=begin]
<table><tr><td align="center">[blk1.year]</td></tr></table>
[blk1;block=end]
.
.
.
Error message:
TinyButStrong Error in field [blk1.year...]: item before 'year' is neither an object nor an array. Its type is NULL. This message can be cancelled using parameter 'noerr'.
I have listed out the results from the query in a for loop as follows:
$rows = $link->get_results($sql_query);
echo "<table>";
foreach ($rows as $obj) :
echo "<tr><td>" . $obj->Year . "</td></tr>";
endforeach;
echo "</table>";
this gives me a correct result but when using TBS class/Loadtemplate/Mergeblock/Show... no joy, I get the error message... Any ideas would be appreciated.
Solved it myself by modifying the tbsdb_wpdb.php to:
function tbsdb_wpdb_open(&$source,&$query) {
global $link;
global $sql_query;
return $link->get_results($sql_query,ARRAY_A);
}
function tbsdb_wpdb_fetch(&$Rs,$num) {
global $link;
global $sql_query;
if ($num<=$link->num_rows) {
return $link->get_row($sql_query,ARRAY_A,$num-1) ;
}
else {
return False ;
}
}
So essentially my global declarations were missing (or rather, in the wrong place).

Hide individual sections of a RSFormPro form when submission limit has been reached

I use RsForm Pro on Joomla CMS, and there I have created a form. In my form, I have 5 sections with a checkbox. I want to display individual sections up to a certain limit (let's say a max of 20 users), after the submission limit has been reached the form section needs to be disabled.
I found a limit for submit form, but if 20 users submit only one section in the form (not for checkbox), another 4 can't be available for other users. In other words, I don't want to disable all sections unless all sections have reached there limit.
This is code for limit submit form:
// Define the maximum number of submissions. For this example we'll use 25.
$max = 25;
// Get a database connection.
$db = JFactory::getDbo();
// Setup the query. This query counts the number of submissions for the current form.
// $formId contains the ID of the current form.
$db->setQuery("SELECT COUNT(`SubmissionId`) FROM #__rsform_submissions WHERE `FormId`='".(int) $formId."'");
$submissions = $db->loadResult();
if ($submissions >= $max) {
$formLayout = 'Sorry, we have no more spaces on this time. Please wait next registration. Thank you!.';
}
EDIT SOLVED:
$limit25 = 25;
$limit21 = 21;
$limit20 = 20;
$db = JFactory::getDbo();
$db->setQuery("SELECT COUNT(`FieldName`) FROM `nqm2i_rsform_submission_values` WHERE `nqm2i_rsform_submission_values`.`FieldName` = 'Bus_Blockchain_March 11th'");
$first_submission_value = $db->loadResult();
if ($first_submission_value >= $limit25) {
echo '<style>.rsform-block-bus-blockchain-march-11th { display:none;}</style>';
}
$db->setQuery("SELECT COUNT(`FieldName`) FROM `nqm2i_rsform_submission_values` WHERE `nqm2i_rsform_submission_values`.`FieldName` = 'Bus_Blockchain_March 13'");
$secont_submission_value = $db->loadResult();
if ($second_submission_value >= $limit25) {
echo '<style>.rsform-block-bus-blockchain-march-13 { display:none;}</style>';
}
$db->setQuery("SELECT COUNT(`FieldName`) FROM `nqm2i_rsform_submission_values` WHERE `nqm2i_rsform_submission_values`.`FieldName` = 'Bus_Blockchain_March 18'");
$third_submission_value = $db->loadResult();
if ($third_submission_value >= $limit25) {
echo '<style>.rsform-block-bus-blockchain-march-18 { display:none;}</style>';
}
$db->setQuery("SELECT COUNT(`FieldName`) FROM `nqm2i_rsform_submission_values` WHERE `nqm2i_rsform_submission_values`.`FieldName` = 'evening_QA'");
$fourth_submission_value = $db->loadResult();
if ($fourth_submission_value >= $limit20) {
echo '<style>.rsform-block-evening-qa { display:none;}</style>';
}
$db->setQuery("SELECT COUNT(`FieldName`) FROM `nqm2i_rsform_submission_values` WHERE `nqm2i_rsform_submission_values`.`FieldName` = 'evening_QA_2'");
$fifth_submission_value = $db->loadResult();
if ($fifth_submission_value >= $limit21) {
echo '<style>.rsform-block-evening-qa-2 { display:none;}</style>';
}
if(
$first_submission_value >= $limit25
&& $secont_submission_value >= $limit25
&& $third_submission_value >= $limit25
&& $fourth_submission_value >= $limit20
&& $fifth_submission_value >= $limit21
) {
$formLayout = 'Sorry, we have no more spaces on this time. Please wait next registration. Thank you!';
}
I see that you have edited your question to reveal your solution. Rather than to ask you to post your solution as an answer (which you should have done), I'll do you one better -- I've taken the time to refactor your code, implement Joomla's query building methods, make it more efficient, cleaner, more direct, and easier to manage.
Most importantly, because all of the database interactions can be performed with a single query, they should be.
Because your field names seamlessly relate to your classnames, a "lookup array" or "mapping array" will allow my snippet to reliably deliver your desired results dynamically. You will never need to adjust more than $formId and $field_maxes.
Code: (tested locally with my own rsform pro table)
$formId = 3; // or whatever the correct formId value is
$field_maxes = [
'Bus_Blockchain_March 11th' => 25,
'Bus_Blockchain_March 13' => 25,
'Bus_Blockchain_March 18' => 25,
'evening_QA' => 20,
'evening_QA_2' => 21
];
$classes_to_hide = []; // initiate as empty array
$formLayout = ''; // initiate as empty string
$db = JFactory::getDbo();
$quoted_fields = implode(',', $db->q(array_keys($field_maxes))); // create quoted comma-separated values
$query = $db->getQuery(true)
->select("FieldName, COUNT(1) AS " . $db->qn("Count"))
->from("#__rsform_submission_values")
->where([
"FormId = " . (int) $formId,
"FieldName IN ($quoted_fields)"
])
->group("FieldName")
->order("FIELD ($quoted_fields)");
// if you wish to see the rendered query, uncomment the next line (do not show to public)
// JFactory::getApplication()->enqueueMessage("<div>" . $query->dump() . "</div>", "notice");
try // listen for syntax errors
{
$db->setQuery($query);
if (!$results = $db->loadAssocList()) // declare and check for empty result set
{
echo "No Results in Form";
}
else
{
foreach ($results as $row) // iterate rows
{
if ($row['Count'] >= $field_maxes[$row['FieldName']]) { // if fieldname has reached limit
$classes_to_hide[] = ".rsform-" . str_replace(['_', ' '], '-', $row['FieldName']);
}
}
if ($tally = sizeof($classes_to_hide)) // declare and check if not empty
{
echo "<style>" , implode(", ", $classes_to_hide) , " {display:none;}</style>"; // apply css styling to one or more designated classes
if ($tally == sizeof($field_maxes)) // if all fieldnames are full
{
$formLayout = 'Sorry, we have no more spaces on this time. Please wait next registration. Thank you!';
}
}
}
}
catch (Exception $e)
{
JFactory::getApplication()->enqueueMessage("Query Syntax Error", "error");
// if you have a syntax error and wish to see the message, uncomment the next line (do not show to public)
//JFactory::getApplication()->enqueueMessage($e->getMessage(), "error");
}

php mysql returns only 1 row if using class

I have this code:
class SampleClass extends MainClass {
private $totalOrder;
//construct goes here
function get_total_number_of_order($buyerIndex) {
$totalSum = //sql to get sum of orders
return $totalSum;
}
function fetch_buyer() {
$qryBuyerInfo = //sql to get buyer info;
while($rs = $qryBuyerInfo->fetch()) {
$this->totalOrder = $this->get_total_number_of_order($rs['buyer_index']);
echo $buyerInfo .'<br>';
echo $this->totalOrder .'<br>';
}
}
I'm wondering why I only get 1 record wherein fact my table has at least 20 records. But if I comment out $this->totalOrder = $this->get_total_number_of_order($rs['buyer_index']);I will be able to generate all 20 records. Another thing I tried is to put get_total_number_of_order to other class an every loop, I initiate new class to use get_total_number_of_order function.
Anybody can have any better idea?
I think I found the issue in your code.
while($rs = $qryBuyerInfo->fetch()) {
$this->totalOrder = $this->get_total_number_of_order($rs['buyer_index']);
echo $buyerInfo .'<br>';
echo $this->totalOrder .'<br>';
}
with above code, you are only getting 1 record as you are re-writing the data into same object. You need to add this loop data into an array. Something like below:
$i=0;
while($rs = $qryBuyerInfo->fetch()) {
$this->totalOrder[$i] = $this->get_total_number_of_order($rs['buyer_index']);
echo $buyerInfo .'<br>';
echo $this->totalOrder[$i] .'<br>';
$i++;
}

Difference between array type and object type in PHP [duplicate]

This question already has answers here:
PHP Objects vs Arrays -- Performance comparison while iterating
(11 answers)
Closed 7 years ago.
As I know, an array in php can designed by key and value.
e.q.
$person = array(
'name'=>'JOSH',
'age'=>18
);
It likes an object but just defined by another way.
e.q.
class info{
$name;
$age;
}
$person = new info();
$person->name = 'JOSH';
$person->age = 18;
I always use array in PHP, but some of my co-workers they say the object type is better than array type.
But I don't understand what different between array type and object type.
Can someone tell me what different between this two types if I just want to declare variable in PHP ?
There are a lot of differences, but the object is more powerfull.
Is in a way to avoid rewrite code, and clean the code.
Think you want to do some operations to numbers in an array:
To keep it simple, I suppose you already get the values from array or object.
<?
$item = array(
'name'=>'carrot',
'price'=>0.20,
'stock' => 15
);
?>
For example, in an shop context, you want to get the price befor buy, and update the stock.
<?
function getprice($item){
return $item['price'];
}
function substock($item,$units){
$item['stock'] = $item['stock'] - $units;
}
echo getprice($item);
echo "<br/>";
echo substock($item,"3");
?>
It will output something like:
0.20
12
That can be a way, but what can we do with the objects:
<?
class items{
var $name , $price, $stock;
function __construct($in_name, $in_price, $in_stock){
if (!empty($in_name)){$this->name = $in_name;}
if (!empty($in_price)){$this->price = $in_price;}
if (!empty($in_stock)){$this->stock = $in_stock;}
}
function getprice(){
return $this->price;
}
function substock($units){
$newstock = $this->stock - $units;
$this->stock = $newstock;
return $newstock;
}
}
$item = new items("carrot","0.20","15");
echo $item->getprice();
echo "<br/>";
echo $item->substock("3");
?>
It will output something like:
0.20
12
Till this point is not a prety much difference, is'n it?
But imagine you want to create a bigger thing. Just play around with it.
Now I want to load an item just with the name of the carrot.
Then changing the method construct to be able to create an objet with different inputs:
var $name , $price, $stock;
function __construct($in_name, $in_price=NULL, $in_stock=NULL){
$args = func_num_args();
if ($args == 1){
$this->name = $in_name;
$this->fromdb($in_name);
}else{
if (!empty($in_name)){$this->name = $in_name;}
if (!empty($in_price)){$this->price = $in_price;}
if (!empty($in_stock)){$this->stock = $in_stock;}
}
}
function fromdb($name){
$sql = "SELECT * FROM items WHERE name = '" . $name . "'";
//... here we bring from database the item and put in an array called $itemdb.I skip this part to do it shorter. If you want, ask about and I'll post this peace and the database objet.
$this -> price = $itemdb['price'];
$this -> stock = $itemdb['stock'];
}
function getprice(){
return $this->price;
}
function substock($units){
$newstock = $this->stock - $units;
$this->stock = $newstock;
return $newstock;
}
}
$item = new items("carrot");
echo $item->getprice();
echo "<br/>";
echo $item->substock("3");
?>
If the value in the database is same as the example before.It will output something like:
0.20
12
But from here you have infinite posibilities. Just play more.
Give a family item, and creating new methods.
<?
class items{
var $name , $price, $stock, $family;
function __construct($in_name, $in_price=NULL, $in_stock=NULL, $in_family=NULL){
$args = func_num_args();
if ($args == 1){
$this->name = $in_name;
$this->fromdb($in_name);
}else{
if (!empty($in_name)){$this->name = $in_name;}
if (!empty($in_price)){$this->price = $in_price;}
if (!empty($in_stock)){$this->stock = $in_stock;}
if (!empty($in_family)){$this->family = $in_family;}
}
}
function fromdb($name){
$sql = "SELECT * FROM items WHERE name = '" . $name . "'";
//... here we bring from database the item and put in an array called $itemdb. I skip this part to do it shorter. If you want, ask about and I'll post this peace and the database objet.
$this -> price = $itemdb['price'];
$this -> stock = $itemdb['stock'];
$this -> family = $itemdb['family'];
}
function getprice(){
return $this->price;
}
function getfamily(){
return $this->family;
}
function substock($units){
$newstock = $this->stock - $units;
$this->stock = $newstock;
return $newstock;
}
function veggiesinfamily(){
$sql = "SELECT count(name),family FROM items WHERE family = '" . $this->family . "'";
//... here we bring from database the number of item of a family product in $number. I skip this part to do it shorter. If you want, ask about and I'll post this peace and the database objet.
return $number;
}
function familystock(){
$sql = "SELECT SUM(stock),family FROM items WHERE family = '" . $this->family . "'";
//... here we bring from database the sum of stock items of a family product in $number. I skip this part to do it shorter. If you want, ask about and I'll post this peace and the database objet.
return $number;
}
}
$item = new items("carrot");
echo "There are " . $item->veggiesinfamily() . $item->getfamily() . " kinds.<br/>";
echo "There are " . $item->familystock() . " units of " . $item->getfamily();
?>
We have also in our database an item: potato, 0.3, 10, roots (name, price, stock, family)
If the value in the database have as family roots and as elements carrot and potatoe. The output will be.
There is 2 roots kinds.
There is 25 units of roots.
And so on.
If you load the objet from an external file as item_class.php, and load as include("item_class.php"), can grow your script easily.
Cheers.

PDO - Call to a member function fetch() on a non-object?

I looked at all the other posts on this and none of them came up with exactly what my problem is so here we go:
$dbh stores my PDO connection, if I do a var dump on it, it returns:
object(PDO)#1 (0) { }
So I know my PDO connection is working. I then use $sth to hold my query:
$c = 2;
$sth = $dbh->query("SELECT * FROM table WHERE ID = " . $c);
Then to make sure this is working I did:
echo $sth->rowCount();
That return a value of 6. So I know it is grabbing some rows. My next step of checking my problem was to fetch a single row like the following:
$row = $sth->fetch()
print_r($row);
This returned a single row (as it should) with the $row array filled exactly how I would expect it (column names as keys and column values as the array value).
So we are good up to this point. Once I move $row = $sth->fetch() into a while loop my script fails the error it returns is: Call to a member function fetch() on a non-object
Here is my while loop:
while($row = $sth->fetch()){
//while loop stuff here
}
I know it has something to do with the condition of the loop because even when I comment out all the stuff in the middle it still isn't working. What am I doing wrong? Why won't this work? I'm beyond confused on this as it has worked in the past with all the PDO I have done but for some reason it is failing in this script.
If anyone has any tips or something that can help it would be greatly appreciated.
EDIT Since ninetwozero's post worked, I'm posting my class and basically everything I've got to get this figured out.
class html_elements {
var $units;
var $useMaps;
var $cid;
var $uid;
var $companyMoney;
var $currCity;
var $terminals;
var $termLocs;
var $cityArray;
var $cargoArray;
var $cargo;
var $tid;
var $truckArray;
var $load;
var $cityID;
var $cargoID;
var $xp;
var $gasPrice;
var $warning;
function __construct($u, $maps, $c, $userID, $cMoney, $dbh, $city, $tid, $xp){
$this->units = $u;
$this->useMaps = $maps;
$this->cid = $c;
$this->uid = $userID;
$this->companyMoney = $cMoney;
$this->currCity = $city;
$this->terminals = array();
$this->termLocs = array();
$this->cityArray = array();
$this->cargoArray = array();
$this->cargo = array();
$this->tid = $tid;
$this->truckArray = array();
$this->load = 0;
$this->cityID = array();
$this->cargoID = array();
$this->xp = $xp;
$this->gasPrice = 0;
$sth = null;
$sth = $dbh->query("SELECT * FROM tblCTerminals WHERE companyID = " . $c);
//THIS LOOP FAILS
while($row = $sth->fetch()){
$this->termLocs[] = $row['Location'];
}
}
Then in another file that has my class file included in it is:
$h = new html_element($u->get_units(), $u->get_maps(), $u->get_company(), $u->get_user_id(), $c->get_money(), $dbh, $u->get_city(), $u->get_truck_id(), $u->get_xp());
Each of those getters work, I tested them. Also $dbh is what is used my connection file that is included before anything else. So I know all of that is working.
I got to say that you've encountered a pretty interesting error, so let's try some things to pinpoint the cause:
if( $sth == null ) die('My sth is null at #1');
while( $row = $sth->fetch() ) {
if( $row == null ) die('My row is null at #2');
echo '<pre>';
print_r($row);
echo '</pre>';
}
Let me know what this tells you.
Edit:
$sql = 'SELECT * FROM tblCTerminals WHERE companyID = ' . $c;
if( intval($c) == 0 ) { die('Aaaaaaaaaa.......aaaaah.');
foreach ($dbh->query($sql) as $row) {
echo '$row[\'Location\'] is: ' . $row['Location'] .'<br />';
$this->termLocs[] = $row['Location'];
}

Categories