[SOLVED] SQLite3 - PHP Fatal error: Uncaught Error: Call to a member function exec()
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
SQLite3 - PHP Fatal error: Uncaught Error: Call to a member function exec()
I have been trying to sort a SQLite3 database on a 'Date' (type=text) Column. No matter what format I use "07/09/2020" or "2020-07-09" The database will not sort it accurately. Because of this I am going to try using julian days (type=real)
So in trying to Update SQLite3 database I get a Fatal error.
Don't have a clue how to interpret this or fix it.
The code below is the PHP program which will create the database, create and populate the table and attempt to update the table.
I want to run this in Firefox after this bug is fixed!
Code:
<?php
// file /var/www/rickSQL.com/public_html/renoAZID/aatest00.php
// Thu Jul 9, 11:04
error_reporting (E_ALL ^ E_NOTICE);
global $db;
class MyDB extends SQLite3 {
function __construct() {
$this->open('test00.db');
}
}
$db = new MyDB();
if(!$db) {
echo $db->lastErrorMsg();
} else {
echo "Opened database successfully\n";
}
"DROP TABLE IF EXISTS `testdata`";
$query=
"CREATE TABLE IF NOT EXISTS `testdata` (
`Id` INTEGER PRIMARY KEY AUTOINCREMENT,
`Date` TEXT NOT NULL,
`Location` TEXT NOT NULL,
`Description` TEXT NOT NULL,
`Category` TEXT NOT NULL,
`Amount` REAL
);";
$ret = $db->exec($query);
if(!$ret){
echo $db->lastErrorMsg();
} else {
echo "Table created successfully\n";
}
$query=
"INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('04/03/2019','419 Upper Blvd', 'Kitchen Sink And Faucet','appliances',438.5);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('04/21/2019','419 Upper Blvd','Refrigerator And BR Light','appliances',1567.55);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('05/03/2019','419 Upper Blvd','Washer Dryer','appliances',1102.1);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('05/17/2019','419 Upper Blvd','Kitchen Lights','appliances',113.67);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('04/01/2019','419 Upper Blvd','Kitchen Fixtures Stove - Ect','appliances',862.82);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('04/26/2019','419 Upper Blvd','House Cleanup','cleaning', 130);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('11/12/2018','419 Upper Blvd','Remove Wallpaper','demo', 650);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('11/19/2018','419 Upper Blvd','Remove Sinks And Toilets – Baths','demo',206.85);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('11/19/2018','419 Upper Blvd','Gas In Kitchen – Off- Rm Lr Heater','demo',99);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('06/01/2019','419 Upper Blvd','Misc','tools',26.35);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('06/13/2019','419 Upper Blvd','Misc','tools',84.79);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('09/24/2019','419 Upper Blvd','Misc','tools',19.58);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('10/29/2019','3607 Smithfield','Service-New Rollers-Lube','maint', 208.2);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('03/01/2019','3607 Smithfield','Seasonal Inspection','maint',39.95);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('10/16/2020','3607 Smithfield','New Remote and Estimate for seals','maint',46.84);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('06/01/2020','419 Upper Blvd','Sprinkler Turn-on; Backflow Test','landscape',65.0);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('04/10/2020','419 Upper Blvd','Fertilize & Weed Control','landscape','0.00');
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('06/21/2020','419 Upper Blvd','Fertilize & Weed Control - paid for April also','landscape',126.0);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('10/16/2018','3607 Smithfield','New Remote and Estimate for seals','maint', 46.84);
";
$ret = $db->exec($query);
if(!$ret) {
echo $db->lastErrorMsg();
} else {
echo "Records created successfully\n";
}
// ================================================================================================
// UPDATE DATES HERE
// ================================================================================================
$query="SELECT * FROM testdata;";
$ret = $db->query($query); // FATAL ERROR POINTS TO THIS
while($row = $ret->fetchArray(SQLITE3_ASSOC) ) {
$rows[]=$row;
}
echo "Operation done successfully\n";
for($i=0; $i<count($rows); $i++) {
$val=$rows[$i]['Date'];
$index=(int)$rows[$i]['Id'];
$x=explode("/",$val);
updateDb($index, $x);
/* OUTPUT INCLUDING THE ERROR MESSAGE
Opened database successfully
Table created successfully
Records created successfully
Operation done successfully
PHP Fatal error: Uncaught Error: Call to a member function exec() on null in /var/www/rickSQL.com/public_html/renoAZID/aatest00.php:136
Stack trace:
#0 /var/www/rickSQL.com/public_html/renoAZID/aatest00.php(84): updateDb(1, Array)
#1 {main}
thrown in /var/www/rickSQL.com/public_html/renoAZID/aatest00.php on line 136
*/
}
//print_r($rows); exit("Leaving Update area - Line 75\n\n");
// ================================================================================================
// THIS SECTION WILL NOT RUN - HELP
$query="SELECT * FROM testdata;";
$ret = $db->query($query);
while($row = $ret->fetchArray(SQLITE3_ASSOC) ) {
$rows[]=$row;
}
echo "Operation done successfully after update \n";
$db->close();
print_r($rows);
// ============================== FUNCTIONS HERE =============================
function updateDb($index, $val) { // update database to julian dates
$x=gregoriantojd($val[0], $val[1], $val[2]);
$query="UPDATE testdata SET `Date`= ".$x." WHERE `Id`= ".$index.";";
//exit($query.".... bye from line 131 \n\n");
// $query = UPDATE testdata SET `Date`= 2458577 WHERE `Id`= 1;
$ret = $db->exec($query);
if(!$ret) {
echo $db->lastErrorMsg();
} else {
echo $db->changes(), " Dates updated successfully\n";
}
} // update()
?>
The ISO standard date format is Y-M-D and should sort as ASCII text so conversion to Julian is not necessary. I tested your script and the actual error is in your updatedb function i.e line
$ret = $db->exec($query);
Although you defined $db as a global variable it isn't. If you add the database descriptor as a passed parameter your script/function works. I changed it to Y-M-D.
Code:
function updateDb($index, $val, $fd) { Convert to Y-M-D
$query="UPDATE testdata SET Date='".$val[2]."-".$val[0]."-".$val[1]."' where Id=".$index;
$ret = $fd->exec($query);
}
If you want to see how sorting works try this test from sqlite3 command line after running the php script.
.open test00db
select * from testdata order by Date desc;
Code:
sqlite> select * from testdata order by Date desc;
15|2020-10-16|3607 Smithfield|New Remote and Estimate for seals|maint|46.84
18|2020-06-21|419 Upper Blvd|Fertilize & Weed Control - paid for April also|landscape|126.0
16|2020-06-01|419 Upper Blvd|Sprinkler Turn-on; Backflow Test|landscape|65.0
17|2020-04-10|419 Upper Blvd|Fertilize & Weed Control|landscape|0.0
13|2019-10-29|3607 Smithfield|Service-New Rollers-Lube|maint|208.2
12|2019-09-24|419 Upper Blvd|Misc|tools|19.58
11|2019-06-13|419 Upper Blvd|Misc|tools|84.79
10|2019-06-01|419 Upper Blvd|Misc|tools|26.35
4|2019-05-17|419 Upper Blvd|Kitchen Lights|appliances|113.67
3|2019-05-03|419 Upper Blvd|Washer Dryer|appliances|1102.1
6|2019-04-26|419 Upper Blvd|House Cleanup|cleaning|130.0
2|2019-04-21|419 Upper Blvd|Refrigerator And BR Light|appliances|1567.55
1|2019-04-03|419 Upper Blvd|Kitchen Sink And Faucet|appliances|438.5
5|2019-04-01|419 Upper Blvd|Kitchen Fixtures Stove - Ect|appliances|862.82
14|2019-03-01|3607 Smithfield|Seasonal Inspection|maint|39.95
8|2018-11-19|419 Upper Blvd|Remove Sinks And Toilets – Baths|demo|206.85
9|2018-11-19|419 Upper Blvd|Gas In Kitchen – Off- Rm Lr Heater|demo|99.0
7|2018-11-12|419 Upper Blvd|Remove Wallpaper|demo|650.0
19|2018-10-16|3607 Smithfield|New Remote and Estimate for seals|maint|46.84
If you need more advanced date functions that is a different issue...
I set $db to global since through this process I get an error message that $db was undefined.
Where did $fd come from?
I changed the updateDb() function and other things like eliminate global $db. Here is new program if you would be so kind to look. It now works without error messages and does update the 'Date' records with 'sqlite date formatted' dates. The database will now sort properly.
Thank you!!
R
Code:
<?php
// file /var/www/rickSQL.com/public_html/renoAZID/aatest00.php
// Thu Jul 9, 17:25
// eliminated global $db;
error_reporting (E_ALL ^ E_NOTICE);
class MyDB extends SQLite3 {
function __construct() {
$this->open('test00.db');
}
}
$db = new MyDB();
if(!$db) {
echo $db->lastErrorMsg();
} else {
echo "Opened database successfully\n";
}
"DROP TABLE IF EXISTS `testdata`";
$query=
"CREATE TABLE IF NOT EXISTS `testdata` (
`Id` INTEGER PRIMARY KEY AUTOINCREMENT,
`Date` TEXT NOT NULL,
`Location` TEXT NOT NULL,
`Description` TEXT NOT NULL,
`Category` TEXT NOT NULL,
`Amount` REAL
);";
$ret = $db->exec($query);
if(!$ret){
echo $db->lastErrorMsg();
} else {
echo "Table created successfully\n";
}
$query=
"INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('04/03/2019','419 Upper Blvd', 'Kitchen Sink And Faucet','appliances',438.5);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('04/21/2019','419 Upper Blvd','Refrigerator And BR Light','appliances',1567.55);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('05/03/2019','419 Upper Blvd','Washer Dryer','appliances',1102.1);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('05/17/2019','419 Upper Blvd','Kitchen Lights','appliances',113.67);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('04/01/2019','419 Upper Blvd','Kitchen Fixtures Stove - Ect','appliances',862.82);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('04/26/2019','419 Upper Blvd','House Cleanup','cleaning', 130);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('11/12/2018','419 Upper Blvd','Remove Wallpaper','demo', 650);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('11/19/2018','419 Upper Blvd','Remove Sinks And Toilets – Baths','demo',206.85);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('11/19/2018','419 Upper Blvd','Gas In Kitchen – Off- Rm Lr Heater','demo',99);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('06/01/2019','419 Upper Blvd','Misc','tools',26.35);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('06/13/2019','419 Upper Blvd','Misc','tools',84.79);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('09/24/2019','419 Upper Blvd','Misc','tools',19.58);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('10/29/2019','3607 Smithfield','Service-New Rollers-Lube','maint', 208.2);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('03/01/2019','3607 Smithfield','Seasonal Inspection','maint',39.95);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('10/16/2020','3607 Smithfield','New Remote and Estimate for seals','maint',46.84);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('06/01/2020','419 Upper Blvd','Sprinkler Turn-on; Backflow Test','landscape',65.0);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('04/10/2020','419 Upper Blvd','Fertilize & Weed Control','landscape','0.00');
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('06/21/2020','419 Upper Blvd','Fertilize & Weed Control - paid for April also','landscape',126.0);
INSERT INTO `testdata` (Date,Location,Description,Category,Amount) VALUES ('10/16/2018','3607 Smithfield','New Remote and Estimate for seals','maint', 46.84);
";
$ret = $db->exec($query);
if(!$ret) {
echo $db->lastErrorMsg();
} else {
echo "Records created successfully\n";
}
// ================================================================================================
// UPDATE DATES HERE
// ================================================================================================
$query="SELECT * FROM testdata;";
$ret = $db->query($query);
while($row = $ret->fetchArray(SQLITE3_ASSOC) ) {
$rows[]=$row;
}
echo "Operation done successfully\n";
for($i=0; $i<count($rows); $i++) {
$val=$rows[$i]['Date'];
$index=(int)$rows[$i]['Id'];
$x=explode("/",$val);
updateDb($index, $x, $db); // added $db to parameters 16:18
/* OUTPUT INCLUDING ERROR MESSAGE
MY FATAL MESSAGE - DOES NOT CHANGE DATABASE
I USE SQLITEBROWSER TO CHECK
Opened database successfully
Table created successfully
Records created successfully
Operation done successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
1 Dates updated successfully
Selected 19 Records. Operation done successfully after update
*/
} // for
// =================================================================
// OUTPUT HERE
// =================================================================
unset($rows); // clear out selection from previous
$query="SELECT * FROM testdata ORDER BY `Date` desc;";
$ret = $db->query($query);
while($row = $ret->fetchArray(SQLITE3_ASSOC) ) {
$rows[]=$row;
}
echo "Selected ".count($rows)." Records. Operation done successfully after update \n\n";
$db->close();
echo "OUTPUT of SELECT query ORDER BY Date desc \n\n";
echo "Rec Id Date\n\n";
for ($i=0; $i<count($rows); $i++) {
echo $i." - ".$rows[$i]['Id'].", ".$rows[$i]['Date']."\n";
}
// ============================================================================
// FUNCTIONS HERE
// ============================================================================
function updateDb($index, $val, $db) { // update Dates to SQLite3 format
$query="UPDATE testdata SET Date='".$val[2]."-".$val[0]."-".$val[1]."' where Id=".$index;
//exit($query.".... bye from line 130 \n\n");
// test output from exit - UPDATE testdata SET Date='2019-04-03' where Id=1;
$ret = $db->exec($query);
if(!$ret) {
echo $db->lastErrorMsg();
} else {
echo $db->changes(), " Date updated successfully\n";
}
} // updateDb()
?>
Now, Come the second phase where I am trying to adapt the above to run in firefox. Not so good so far. Changing aatest00.php to revDateToSqlFotmat.php using test00.db and testdata table. What is really frustrating to me is why this happens and what does it all mean. Can you enlighten me? (a little bit?).
Code:
<?php
// file /var/www/rickSQL.com/public_html/renoAZID/aatest00.php ==> adapted to firefox with revDateToSqlFotmat.php
// Thu Jul 9, 11:04 rev. 17:35 aatest00.php
// Thu Jul 9, 18:51 revDateToSqlFotmat.php using test00.db
error_reporting (E_ALL ^ E_NOTICE);
$database="test00.db";
$table='testdata';
class MyDB extends SQLite3 {
function __construct() {
$this->open($database);
}
}
$db = new MyDB();
if(!$db) {
echo $db->lastErrorMsg();
} else {
echo "Opened database successfully<br>";
}
// ================================================================================================
// UPDATE DATES HERE
// ================================================================================================
$query="SELECT * FROM ".$table.";";
//exit($query."bye from line 28");
$ret = $db->query($query);
while($row = $ret->fetchArray(SQLITE3_ASSOC) ) {
$rows[]=$row;
}
echo "Operation done successfully<br>";
for($i=0; $i<count($rows); $i++) {
$val=$rows[$i]['Date'];
$index=(int)$rows[$i]['Id'];
$x=explode("/",$val);
updateDb($index, $x, $db); // added $db to parameters 16:18
} // for
/* OUTPUT INCLUDING ERROR MESSAGE
Opened database successfully
Thu Jul 09 18:41:30.284411 2020] [php7:error] [pid 5687] [client 127.0.0.1:50508]
PHP Fatal error: Uncaught Error: Call to a member function fetchArray() on boolean in
/var/www/rickSQL.com/public_html/renoAZID/revDateToSqlFormat.php:30\n
Stack trace:\n#0 {main}\n thrown in /var/www/rickSQL.com/public_html/renoAZID/revDateToSqlFormat.php on line 30,
referer: http://ricksql.com/renoAZID_Frontend.html
*/
// =================================================================
// OUTPUT HERE
// =================================================================
$query="SELECT * FROM ".$table." ORDER BY `Date` desc;";
$ret = $db->query($query);
while($row = $ret->fetchArray(SQLITE3_ASSOC) ) {
$rows[]=$row;
}
echo "Selected ".count($rows)." Records. Operation done successfully after update <br><br>";
$db->close();
echo "OUTPUT of SELECT query ORDER BY Date desc <br><br>";
echo "Rec Id Date<br><br>";
for ($i=0; $i<count($rows); $i++) {
echo $i." - ".$rows[$i]['Id'].", ".$rows[$i]['Date']."<br>";
}
// ============================================================================
// FUNCTIONS HERE
// ============================================================================
function updateDb($index, $val, $db) { // update Dates to SQLite3 format
$query="UPDATE ".$table." SET Date='".$val[2]."-".$val[0]."-".$val[1]."' where Id=".$index;
//exit($query.".... bye from line 130 <br><br>");
// test output from exit - UPDATE testdata SET Date='2019-04-03' where Id=1;
$ret = $db->exec($query);
if(!$ret) {
echo $db->lastErrorMsg();
} else {
echo $db->changes(), " Date updated successfully<br>";
}
} // updateDb()
?>
If you don't have to do it in PHP, you could do it all from the Sqlite3 client (or just call this statement once in PHP).
Code:
-- Assumes that Date is in the format of mm[SEPARATOR]dd[SEPARATOR]YYYY
UPDATE testdata SET Date=substr(Date, 7)||'-'||substr(Date, 0, 3)||'-'||substr(Date, 4, 2);
It's ugly, to be sure, but it saves a lot of code to do something relatively simple.
I had thought the same thing with the semicolon but it doesn't matter. If you go back and look at the apache logs you will find two errors. The first is table not found. The second is the fetchArray error.
The reason is the new mydb function will open a new file if the specified one does not exist. In this the case success status is misleading. If you go back to your original script the db file was automatically created in the same directory. Without a path the db file is assumed to be in the apache document root directory.
As stated apache needs access permissions to the directory where the file is located if in in document root.
I assumed the OP was trying to run the script from a web server and therefore via firefox...
I mentioned moving the DB file to document root. However, that will not work since the web server runs as user www-data which does not have permissions to write to /var/www/html...
Well ... The solution is below: All works now. Database will now produce sorted `Dates` properly!!
This "test" script is actually a small part of the real program in which I could not get the 'Dates' to sort properly.
I learned that the dates had to be formatted, in what I call, SQLite date format (YYYY-MM-DD). The input I had done for the actual database was many, many records therefore, I needed to convert my (MM/DD/YYYY) dates which led to my initial POST.
You, my teachers, have pointed out the mechanics of a few things so I will work on them to make the code more efficient.
Thank you all very much for your time in helping me!
R
Code:
<?php
// file /var/www/rickSQL.com/public_html/renoAZID/aatest00.php ==> adapted to firefox with revDateToSqlFotmat.php
// Thu Jul 9, 11:04 rev. 17:35 aatest00.php
// Thu Jul 9, 18:51 revDateToSqlFotmat.php using test00.db
error_reporting (E_ALL ^ E_NOTICE);
$database="renoAZID.db";
global $table;// <<=============== added global
$table='rdata';
class MyDB extends SQLite3 {
function __construct() {
global $database;// <<=============== added global
$this->open($database);
}
}
$db = new MyDB();
if(!$db) {
echo $db->lastErrorMsg();
} else {
echo "Opened database successfully<br>";
}
code continues ......
//
Somewhere in the hazily remember past I switched to use YYYY-MM-DD for all dates where I have the choice. They naturally sort in that format, treated as a string or number (YYYYMMDD).
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.