What is likely to be tripping you up is that your $tableArray
doesn't have prefixes. This is evident in your query because you prepend the tablename with #__
in the FROM
clause. The resultset will be delivering the rendered prefix with the tablename, so your input array values will not match the result set values.
*Important: Always try to avoid iterated database queries as a matter of best practice. Performing multiple queries unnecessarily will result in slow page loads not to mention burden your system.
I've tested the following to be successful on my localhost. I've written this to be completely dynamic (no hardcoding the db name or table prefix).
If you don't want to filter the table names in the result set, you can use this:
$db = JFactory::getDbo();
$results = $db->setQuery('SHOW TABLES')->loadColumn();
$prefix = $db->getPrefix();
foreach ($tableArray as $t) {
echo "<br>" , (in_array($prefix.$t, $results) ? "Found " : "Missing ") , $t;
}
Otherwise, you can filter the result set by extending the query logic.
Code:
$tableArray = ["banners", "content", "cucumbers"];
try {
$db = JFactory::getDbo();
$config = JFactory::getConfig();
$dbname = $config->get('db');
$prefix = $db->getPrefix();
foreach ($tableArray as $t) {
$q_tablenames[] = $db->q($prefix.$t); // prefix and quote-wrap for the query
}
$query = $db->getQuery(true)
->select("SUBSTRING(table_name, 7)")
->from("information_schema.tables")
->where(["table_schema = " . $db->q($dbname), "table_name IN (" . implode(',', $q_tablenames) . ")"]);
// echo $query->dump(); // never show to public
$db->setQuery($query);
$found = $db->loadColumn();
foreach ($tableArray as $tablename) {
echo "<div>$tablename table " , (in_array($tablename, $found) ? "" : "not ") , "found</div>";
}
} catch (Exception $e) {
JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error'); // never show actual error to public
}
Output:
banners table found
content table found
cucumbers table not found
The reason that I am using a more verbose query is because I don't actually need to extract every table name from the database -- I only need the ones that exist in the array. This is more about "direct coding intentions" rather than micro-optimization (which I won't bother to benchmark).
The IN
data is prefixed because the $tableArray
values are not pre-fitted with prefixes. The SELECT
trims off the prefixes for simple comparisons in the foreach()
loop.
Here is an alternative approach using SHOW TABLES
which achieves the same result:
$tableArray = ["banners", "content", "cucumbers"];
try {
$db = JFactory::getDbo();
$config = JFactory::getConfig();
$dbname = $config->get('db');
$prefix = $db->getPrefix();
foreach ($tableArray as $t) {
$q_tablenames[] = $db->q($prefix . $t); // prefix and quote-wrap for the query
}
$db->setQuery("SHOW TABLES FROM " . $db->qn($dbname) . " WHERE " . $db->qn("Tables_in_$dbname") . " IN (" . implode(',', $q_tablenames) . ")");
$found = $db->loadColumn();
foreach ($tableArray as $tablename) {
echo "<div>$tablename table " , (in_array($prefix.$tablename, $found) ? "" : "not ") , "found</div>";
}
} catch (Exception $e) {
JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error'); // never show to public
}
SHOW TABLES
query that was the problem, but your php conditional that was inhibiting things -- which only my answer addresses. If you don't like my long-winded/convoluted queries, that's fine, but I would appreciate receiving an upvote for volunteering my time and delivering a comprehensive and working solution.