Retrieving image names from MySQL DB in HTML using PHP functions - php

I'm new to coding.
I have to make a website, where images are retrieved from MySQL database using PHP functions, but I can't store images in the DB, only their names, and I can't manually put in the id as in getImage(1) etc.
So I have these two functions:
function getImage($imgid) {
$sql_command = "SELECT * FROM images WHERE id=$imgid;";
$result = mysqli_query(getConnection(), $sql_command);
if($result) {
$result = mysqli_fetch_assoc($result);
return $result;
} else {
echo "Error <br /> " . mysqli_error(getConnection());
return NULL;
}
}
function getImages() {
$sql_command = "SELECT * FROM images;";
$result = mysqli_query(getConnection(), $sql_command);
if($result) {
return $result;
} else {
echo "Error.";
return NULL;
}
}
I then included the file in my index.php but, honestly, I lack understanding on how to actually apply these functions and specify the name of the image, since it's a variable.
I don't expect someone to solve this problem for me, just to explain the logic or maybe share a link to a useful resource that would explain a situation like this.

Typically the image will be in a directory. And the name of the image will be saved in the database. You can then make a query to receive all image names and display them using a loop
$sql = "SELECT * FROM images";
$imageresult1 = mysql_query($sql);
while($rows=mysql_fetch_assoc($imageresult1))
{
$image = $rows['image'];
echo "<img src=/path/to/'$image' >";
echo "<br>";
}

I'm not sure if I understand exactly what you want to do, but in the database you have to save the path where it will be saved imagine on the server, then you can list them.
<?php
function getImages() {
$sql_command = "SELECT * FROM images;";
$result = mysqli_query(getConnection(), $sql_command);
if($result) {
$imgs = [];
while($rows=mysql_fetch_assoc($result)) {
$imgs[] = $rows;
}
return $imgs;
} else {
echo "Error.";
return NULL;
}
}
// list imgs
$imgs = getImages();
foreach($imgs as $img) {
echo "<img src'{$img['path']}' />";
}

Hopefully the following might give an idea how to use the functions you already have and, with a little work, implement the use of getImage($id) by using ajax. The code below will display the images found by querying the db ( assuming the db table has a structure similar to this )
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(512) | YES | | NULL | |
+-------------+------------------+------+-----+---------+----------------+
And also assuming that the column name stores the fullpath to the image rather than just the image name itself.
<?php
function getConnection(){
$dbhost = 'localhost';
$dbuser = 'root';
$dbpwd = 'xxx';
$dbname = 'xxx';
$db = new mysqli( $dbhost, $dbuser, $dbpwd, $dbname );
return $db;
}
function getImages(){
/*
query the database to return the ID and name of ALL images
*/
try{
/* two named fields - these will be returned later */
$sql='select `id`,`name` from `images`';
/* Get the db conn object */
$db=getConnection();
/* throw exception if we are unable to bind to db */
if( !$db or !is_object( $db ) ) throw new Exception('Failed to bind to database');
/* query the db */
$res=$db->query( $sql );
/* throw an exception if the query failed */
if( !$res ) throw new Exception('sql query failed');
/* prepare results and iterate through recordset */
$results=array();
while( $rs=$res->fetch_object() ) $results[ $rs->id ]=$rs->name;
/* return the array of results */
return $results;
}catch( Exception $e ){
echo $e->getMessage();
return false;
}
}
function getImage( $id=false ){
/*
Query the database to return single image based upon ID
*/
try{
/* If the id is not specified or empty throw exception */
if( !$id )throw new Exception('Image ID was not specified');
/* sql statement to execute */
$sql='select `name` from `images` where `id`=?';
/* get db conn object */
$db=getConnection();
/* throw exception if we are unable to bind to db */
if( !$db or !is_resource( $db ) ) throw new Exception('Failed to bind to database');
/* Create a "Prepared Statement" object - avoid SQL injection !! */
$stmt=$db->prepare( $sql );
/* If the statement failed, throw exception */
if( !$stmt )throw new Exception('Failed to prepare sql query');
/* Bind the supplied ID to the sql statement */
$stmt->bind_param( 'i', $id );
/* Execute the query */
$res=$stmt->execute();
if( $res ){
/* Prepare results */
$stmt->store_result();
$stmt->bind_result( $name );
$stmt->fetch();
/* return the name of the image */
return $name;
} else {
throw new Exception('sql query failed');
}
}catch( Exception $e ){
echo $e->getMessage();
return false;
}
}
?>
<!doctype html>
<html>
<head>
<meta charset='utf-8' />
<title>Images</title>
<style>
#images{
width:90%;
float:none;
display:block;
margin:1rem auto;
}
#images > img {
float:none;
margin:1rem;
padding:1rem;
border:1px dotted gray;
}
</style>
<script>
document.addEventListener( 'DOMContentLoaded', function(){
var col=Array.prototype.slice.call( document.getElementById('images').querySelectorAll('img') );
col.forEach(function(img){
img.onclick=function(e){
alert('You could send an ajax request, using the ID:' + this.dataset.imgid + ' and then use PHP at the server side to process the ajax request and return the specific image using "getImage(id)"')
}
});
}, false );
</script>
</head>
<body>
<div id='images'>
<?php
$images = getImages();
if( !empty( $images ) ){
foreach( $images as $id => $name ){
echo "<img data-imgid='$id' src='$name' title='This image is called $name and has db ID $id' />";
}
}
?>
</div>
</body>
</html>

Related

Image uploaded but not stored

I am trying to store image name along with other data in the database but not being able to. nothing is inserted in the database. but the image is uploaded in the directory when i close the brace } before db config. but i got call to an undefined function upload() when i close the function brace } after inserting. here is the code:
$imagesub = isset( $_FILES['image'] );
if ( $imagesub )
{
$output=upload();
}
return $output;
function upload()
{
include_once "class.php";
$uploader = new Uploader( "image" );
$uploader->saveIn("images");
$fileUploaded = $uploader->save();
$db = new mysqli("localhost", "root","","learndb");
if ($db->connect_error) {
die("Connection failed this is the error: " . $db->connect_error);
}
$stmt = $db->prepare("INSERT INTO studentrecords (Name, email, Phone, school,dob,father,feereceived,due,image) VALUES (?,?,?,?,?,?,?,?,?)");
if($stmt)
{
$stmt->bind_param("ssisssiis",$name,$email,$phone,$school,$dob,$father,$feereceived,$due,$fileUploaded);
$stmt->execute();
$out="<center>information entered.</center>";
echo "$out";
}
else
{
$out="DATABASE ERROR!!!";
echo "$out";
}
return $out;
}
Here is the function save()
public function save(){
$folderIsWriteAble = is_writable( $this->destination );
if( $folderIsWriteAble ){
$name = "$this->destination/$this->filename";
if($succes = move_uploaded_file( $this->fileData, $name ))
{
return $name;
}
}
}
#Micky you have only 9 fields defined in your insert query but you are passing 10 parameters in ´bind_param()`.
$stmt->bind_param("ssisssiis",$name,$email,$phone,$school,$dob,$father,$feereceived,$due,$fileUploaded);
should be
$stmt->bind_param($name,$email,$phone,$school,$dob,$father,$feereceived,$due,$fileUploaded);
If it doesn’t resolve your problem then var_dump your $fileUploaded variable and make sure you have compatible datatype defined for column used for storing file name.

Ajax auto refresh - PHP variables not passing correctly into auto refresh function

I'm using Eliza Witkowska's Ajax Auto Refresh code: http://blog.codebusters.pl/en/entry/ajax-auto-refresh-volume-ii
I've altered the code so I can pass variables from the url. It all works great except for one line of code. The line of code is part of a database query that checks for new records. When I try to pass my variables into the query the auto refresh stops working (all other functionality continues to work). If I use static values it works fine.
static values (this works)
$result = $this->db->query('SELECT counting FROM chats WHERE id=1 AND AgentID=3 AND UserID=25');
with variables (this doesn't work)
$result = $this->db->query('SELECT counting FROM chats WHERE id=1 AND AgentID='.$AgentID.' AND UserID='.$UserID.'');
There are no problems passing variables into another function in the same script. So I'm stuck and have been for a few days. Any help with be appreciated.
db.php
class db{
/**
* db
*
* #var $ public $db;
*/
public $db;
function __construct(){
$this->db_connect('###SERVER###','###USERNAME###','###PASSWORD###','###DATABASE###'); //my database information
}
function db_connect($host,$user,$pass,$database){
$this->db = new mysqli($host, $user, $pass, $database);
if($this->db->connect_errno > 0){
die('Unable to connect to database [' . $this->db->connect_error . ']');
}
}
//////////////////////////////
//This is the function that is having an issue when I pass it variables
//////////////////////////////
function check_changes(){
global $UserID; //Declaring my variable
global $AgentID; //Declaring my variable
$result = $this->db->query('SELECT counting FROM chats WHERE id=1 AND AgentID='.$AgentID.' AND UserID='.$UserID.'');
if($result = $result->fetch_object()){
return $result->counting;
}
return 0;
}
//////////////////////////////
//This function has no problem, even when I pass it variables
//////////////////////////////
function get_news(){
global $UserID;
global $AgentID;
if($result = $this->db->query('SELECT * FROM chats WHERE id<>1 AND AgentID='.$AgentID.' AND UserID='.$UserID.' ORDER BY add_date ASC LIMIT 50')){
$return = '';
while($r = $result->fetch_object()){
if ($r->ChatType==1) { //ChatType is a field in the table that distinguishes Agent texts from User Texts
$return .= ''.htmlspecialchars($r->title).'';
} else {
$return .= '<div align="right">'.htmlspecialchars($r->title).'</div>';
}
}
return $return;
}
}
}
Here are the other files:
index.php
<?php
$AgentID = $_REQUEST["AgentID"]; //Grabing AgentID from the URL
$UserID = $_REQUEST["UserID"]; //Grabing UserID from the URL
require('common.php');
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Admin</title>
<script src="jquery-1.10.2.min.js"></script>
<script>
/* AJAX request to checker */
function check(){
$.ajax({
type: 'POST',
url: 'checker.php?AgentID=<? echo $AgentID; ?>&UserID=<? echo $UserID; ?>', //This line has been updated by passing parameters
dataType: 'json',
data: {
counter:$('#message-list').data('counter')
}
}).done(function( response ) {
/* update counter */
$('#message-list').data('counter',response.current);
/* check if with response we got a new update */
if(response.update==true){
$('#message-list').html(response.news);
var audio = new Audio('img/solemn.mp3');
audio.play();
}
});
}
//Every 2 sec check if there is new update
setInterval(check,2000);
</script>
<style>
body {
margin:0px;
padding:0px;
vertical-align:top;
}
</style>
</head>
<body>
<?php /* Our message container. data-counter should contain initial value of counter from database */ ?>
<br>
<div id="message-list" data-counter="<?php echo (int)$db->check_changes();?>">
<?php echo $db->get_news();?>
</div>
</body>
</html>
checker.php
<?php require('common.php');
//get current counter
$data['current'] = (int)$db->check_changes();
//set initial value of update to false
$data['update'] = false;
//check if it's ajax call with POST containing current (for user) counter;
//and check if that counter is diffrent from the one in database
if(isset($_POST) && !empty($_POST['counter']) && (int)$_POST['counter']!=$data['current']){
$AgentID = $_REQUEST["AgentID"]; //passing my variable to db.php
$UserID = $_REQUEST["UserID"]; //passing my variable to db.php
$data['news'] = $db->get_news();
$data['update'] = true;
}
//just echo as JSON
echo json_encode($data);
/* End of file checker.php */
?>
common.php
<?php
require_once ('db.php'); //get our database class
$db = new db();
/* end of file common.php */
?>
I think the problem was that the variables were not available at the time of including the database connection in checker.php ~ declare the variables and then include the db connection.
Also, I'd suggest that instead of using the global expression to define the variables within your db class methods that you pass them as parameters instead. I hope the following might be of use - it's not tested though. There are, or should be, concerns with this method of using variables within sql - it is vulnerable to the dreaded sql injection ~ better would be to use prepared statements within the db class and bind the $agentID and $UserID with the bind_param() method.
<?php
/* common.php */
$dbhost = 'xxx';
$dbuser = 'xxx';
$dbpwd = 'xxx';
$dbname = 'xxx';
require_once 'db.php';
$db = new db( $dbhost, $dbuser, $dbpwd, $dbname );
?>
<?php
/* database class: db.php */
class db{
private $db;
public function __construct( $dbhost, $dbuser, $dbpwd, $dbname ){
$this->db = new mysqli( $dbhost, $dbuser, $dbpwd, $dbname );
if( $this->db->connect_errno > 0 ) exit('Unable to connect to database [' . $this->db->connect_error . ']');
}
public function check_changes( $AgentID=false, $UserID=false ){
if( $AgentID && $UserID ){
$result = $this->db->query('SELECT counting FROM chats WHERE id=1 AND AgentID='.$AgentID.' AND UserID='.$UserID.'');
if($result = $result->fetch_object()){
return $result->counting;
}
}
return 0;
}
public function get_news( $AgentID, $UserID ){
$return = '';
if( $AgentID && $UserID ){
if( $result = $this->db->query('SELECT * FROM chats WHERE id<>1 AND AgentID='.$AgentID.' AND UserID='.$UserID.' ORDER BY add_date ASC LIMIT 50' ) ){
while( $r = $result->fetch_object() ){
if ($r->ChatType==1) {
$return .= ''.htmlspecialchars($r->title).'';
} else {
$return .= '<div align="right">'.htmlspecialchars($r->title).'</div>';
}
}
}
return $return;
}
}
}
?>
<?php
/* Checker.php */
$AgentID = isset( $_REQUEST["AgentID"] ) ? $_REQUEST["AgentID"] : false;
$UserID = isset( $_REQUEST["UserID"] ) ? $_REQUEST["UserID"] : false;
if( $AgentID && $UserID ){
/* Do SOME filtering of user supplied data */
$AgentID=filter_var( $AgentID, FILTER_SANITIZE_NUMBER_INT, array( 'options' => array('default' => 0, 'min_range' => 0 ) ) );
$UserID=filter_var( $UserID, FILTER_SANITIZE_NUMBER_INT, array( 'options' => array('default' => 0, 'min_range' => 0 ) ) );
require 'common.php';
$data['current'] = (int)$db->check_changes( $AgentID, $UserID );
$data['update'] = false;
if( isset($_POST) && !empty($_POST['counter']) && (int)$_POST['counter']!=$data['current'] ){
$data['news'] = $db->get_news( $AgentID, $UserID );
$data['update'] = true;
}
echo json_encode($data);
}
?>
<?php
$AgentID = isset( $_REQUEST["AgentID"] ) ? $_REQUEST["AgentID"] : false;
$UserID = isset( $_REQUEST["UserID"] ) ? $_REQUEST["UserID"] : false;
$AgentID=filter_var( $AgentID, FILTER_SANITIZE_NUMBER_INT, array( 'options' => array('default' => 0, 'min_range' => 0 ) ) );
$UserID=filter_var( $UserID, FILTER_SANITIZE_NUMBER_INT, array( 'options' => array('default' => 0, 'min_range' => 0 ) ) );
require 'common.php';
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Admin</title>
<script src="jquery-1.10.2.min.js"></script>
<script>
<?php
echo "
var aid={$AgentID};
var uid={$UserID};";
?>
function check(){
$.ajax({
type:'POST',
url:'checker.php?AgentID='+aid+'&UserID='+uid,
dataType:'json',
data:{ counter:$('#message-list').data('counter') }
}).done( function( response ) {
/* update counter */
$('#message-list').data('counter',response.current);
/* check if with response we got a new update */
if(response.update==true){
$('#message-list').html(response.news);
var audio = new Audio('img/solemn.mp3');
audio.play();
}
});
}
setInterval(check,2000);
</script>
<style>
body {
margin:0px;
padding:0px;
vertical-align:top;
}
</style>
</head>
<body>
<br>
<div id="message-list" data-counter="<?php echo (int)$db->check_changes($AgentID, $UserID); ?>">
<?php echo $db->get_news($AgentID, $UserID);?>
</div>
</body>
</html>

fetching data invalid

problem i am facing is when i hit http://www.localhost/test1.php?user=10&num=10
irrespective of num=10&user=10. it displays all the data in the database . how to get particular data with respect to num or user for example num=5 or 6?
<?php
/* require the user as the parameter */
if(isset($_GET['user']) && intval($_GET['user'])) {
/* soak in the passed variable or set our own */
$number_of_posts = isset($_GET['num']) ? intval($_GET['num']) : 10; //10 is the default
$format = strtolower($_GET['format']) == 'json' ? 'json' : 'xml'; //xml is the default
$user_id = intval($_GET['user']); //no default
/* connect to the db */
$link = mysql_connect('localhost','username','pwd') or die('Cannot connect to the DB');
mysql_select_db('marketing',$link) or die('Cannot select the DB');
/* grab the posts from the db */
$query = "SELECT * FROM data";
$result = mysql_query($query,$link) or die('Errant query: '.$query);
/* create one master array of the records */
$posts = array();
if(mysql_num_rows($result)) {
while($post = mysql_fetch_assoc($result)) {
$posts[] = array('post'=>$post);
}
}
/* output in necessary format */
if($format == 'json') {
header('Content-type: application/json');
echo json_encode(array('posts'=>$posts));
}
else {
header('Content-type: text/xml');
echo '<posts>';
foreach($posts as $index => $post) {
if(is_array($post)) {
foreach($post as $key => $value) {
echo '<',$key,'>';
if(is_array($value)) {
foreach($value as $tag => $val) {
echo '<',$tag,'>',htmlentities($val),'</',$tag,'>';
}
}
echo '</',$key,'>';
}
}
}
echo '</posts>';
}
/* disconnect from the db */
#mysql_close($link);
}
?>
In order to have sum of 2 columns saved into the third one automatically you have 2 options:
1. save directly from the code
2. create a trigger.
If a trigger is what you want - here is the trigger
CREATE TRIGGER ins_sum BEFORE INSERT ON user
FOR EACH ROW SET NEW.s3 = NEW.s1+NEW.s2;
Reference to detailed explanation:
https://dev.mysql.com/doc/refman/5.5/en/trigger-syntax.html
And from the code:
INSERT INTO users (s1,s2,s3) values (val1, val2, val1+val2)
Of course here you should change the val1 and val2 to your actual values.

How to make echo results in table hyperlinks

I have retrieved data from DB and inserted into a html table however I want to make each value in the table a hyperlink to another page. Below I have tried making the pupil_id and link to a profile.php but all pupil_id values have now vanished!
(if (!isset($_POST['search'])) {
$pupils = mysql_query("SELECT * FROM pupil") or die("Cant find Pupils");
$count = mysql_num_rows($pupils);
if ($count == 0) {
$totalpupil = "There are currently no Pupils in the system.";
} else {
while ($row = mysql_fetch_array($pupils)) {
?>
<tr>
<td><?php echo '<a href="profile.php?id=' .$row['pupil_id'] . '"</a>' ?></td>
<td><?php echo $row['pupil_name'] ?></td>
<td><?php echo $row['class_id'] ?></td>
</tr>
<?php
}
}
})
The finishing table should display every hyperlink as a hyperlink to another page. Any help?
Because your HTML is invalid, you are missing a closing > and you have no text defined for the hyperlink
<?php echo '<a href="profile.php?id=' .$row['pupil_id'] . '"</a>' ?> //Wrong
Correct would be
<?php echo ''.$row['pupil_id'].''; ?>
Try replace this:
<?php echo '<a href="profile.php?id=' .$row['pupil_id'] . '"</a>' ?>
with this:
<?php echo "<a href='profile.php?id=".$row['pupil_id']."'>link</a>"; ?>
Also, you dont have <table> tags at all.
You don't put any text between your link tags, text here
Maybe this will help you:
<td><?php echo ''.$row['pupil_name'].'' ?></td>
http://uk3.php.net/mysql_query
Watch out, which ever resource you are learning from may well be quite old. mysql_query is now deprecated.
http://uk3.php.net/manual/en/ref.pdo-mysql.php is a replacement.
Here is a kick starter to using PDO (this is much much safer) i write a while ago.
Include this file in which ever php script needs to access your db. An example file name would be 'database.php' but that is your call. Set the namespace from 'yourproject' to whatever your project is called. Correct the database credentials to suit your database
This will save you a lot of headaches hopefully!
I have given some example uses at the bottom for you. I remember when i started out getting clear advice was sometimes hard to come by.
//***** in a database class file*****/
namespace yourproject;
class Database {
private $db_con = '';
/*** Function to login to the database ***/
public function db_login()
{
// Try to connect
try{
// YOUR LOGIN DETAILS:
$db_hostname = 'localhost';
$db_database = 'yourdatabasename';
$db_username = 'yourdatabaseusername';
$db_password = 'yourdatabasepassword';
// Connect to the server and select database
$this->db_con = new \PDO("mysql:host=$db_hostname;dbname=$db_database",
"$db_username",
"$db_password",
array(\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
// Prevent emulation of prepared statements for security
$this->db_con->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$this->db_con->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
return true;
}
// If it fails, send user to maintenance page
catch(PDOException $e)
{
header("location:http://yourwebsiteurl.com/maintenance.php");
exit();
}
}
/*** Function for database control ***/
public function db_control($query , $parameters, $returnID = false)
{
if(!is_array($query) && is_array($parameters))
{
try{
//prepare the statement
$statement = $this->db_con->prepare($query);
//execute the statement
$statement->execute($parameters);
//check whether this is a select, if it is then we need to retrieve the selected data
if(strpos($query, 'SELECT') !== false)
{
//fetch the results
$result = array();
while( $row = $statement->fetch(\PDO::FETCH_ASSOC) )
{
$result[] = $row;
}
//count the results
$count = count($result);
//return the array
return array( 'results' => $result, 'result_count' => $count );
}
//else return the number of affected rows
else{
//count the affected rows and place into a returnable array
$affected_rows = $statement->rowCount();
$returnArray = array('result_count' => $affected_rows);
//check to see if we are to return a newly inserted autoincrement ID from an INSERT
if($returnID)
{
//find the newly created ID and add this data to the return array
$insertID = $this->db_con->lastInsertId();
$returnArray['ID'] = $insertID;
}
return $returnArray;
}
}
catch(PDOException $e)
{
return false;
}
}
else{
return false;
}
}
}
// Start the database class and connect to the database then create a globally accessible function for ease of reference
$db = new \yourproject\Database();
$db->db_login();
function _db( $sql , $params , $returnID = false ){
return $GLOBALS['db']->db_control( $sql , $params , $returnID );
}
When you include this file you now have a new function: _db(). As the function is global it can be called from within any class or std file. When called into a variable as demonstrated below will result in an array like this:
array(
'result_count' => 3,
'results' => array(
array(/*row 1*/),
array(/*row 2*/),
array(/*row 3*/),
.. etc etc
)
)
Now include your database file in your php script:
//call in the database file
require_once 'database.php';
//your query as in the op
$sql = 'SELECT * FROM pupil';
//your params for the query
$params = array();
//running the query and getting the results returned into a variable called $query
$query = _db($sql,$params);
//if no results
if( $query['result_count'] == 0 )
{
echo 'sorry no pupils in the system';
}
else
{
//looping through each result and printing into a html table row
for( $i = 0 ; $i < $query['result_count'] ; ++$i )
{
echo '<tr><td><a href="profile.php?id=' . $query['results'][$i]['pupil_id'] . '"</a></td>';
echo '<td>'. $query['results'][$i]['pupil_name'] . '</td>';
echo '<td>'. $query['results'][$i]['class_id'] . '</td></tr>';
}
}
Your original query but with some parameters passed through
//Passing parameters to the query
//your query
$sql = 'SELECT * FROM pupil WHERE pupil_id = :pupil_id AND class_id = :class_id';
//your params for the query
$params = array(
':pupil_id' => 12,
':class_id' => 17,
);
//running the query and getting the results returned into a variable called $query
$query = _db($sql,$params);
//deal with the results as normal...
If you set the 3rd param as true you can return the automatic id of the row just entered eg:
//where $sql is a query that will INSERT a row
$query = _db($sql,$params, true);

Value == DisplayText in Field Options or else Fields are Blank

I've already posed this question on the jquery-jtable Github issues section here: https://github.com/hikalkan/jtable/issues/703 . There doesn't seem to be much knowledge being shared there at this time and this issue is significantly hamstringing further development of my project.
I am practically certain I am missing something relatively simple because based on the documentation here: http://www.jtable.org/ApiReference#fopt-options this really should be straightforward with no issues.
Note, this simplified version of code should demonstrate the issue and is not representative of exactly how the code is being implemented. that is, I am strictly trying to solve the reproducible issue not how best to use it in my much larger project.Here's a copy paste of the issue:
Let's make the SQL table:
--Create "employee titles" table
create table employee_titles (employeetitleid int not null IDENTITY, employeetitle varchar(50) not null,
constraint PK_employee_titles_employeetitleid
primary key clustered (employeetitleid))
go
Now let's make the jtable:
<html>
<head>
<link href="/jtabphp/themes/redmond/jquery-ui-1.8.16.custom.css" rel="stylesheet" type="text/css" />
<link href="/jtabphp/scripts/jtable/themes/lightcolor/blue/jtable.css" rel="stylesheet" type="text/css" />
<script src="/jtabphp/scripts/jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="/jtabphp/scripts/jquery-ui-1.8.16.custom.min.js" type="text/javascript"></script>
<script src="/jtabphp/scripts/jtable/jquery2.3.0.jtable.js" type="text/javascript"></script>
</head>
<body>
<div id="EmployeeTitles" style="width: 600px;"></div>
<script type="text/javascript">
$(document).ready(function () {
//Prepare jTable
$('#EmployeeTitles').jtable({
title: 'Employee Titles',
actions: {
listAction: 'PersonActions.php?action=list',
},
fields: {
employeetitleid: {
key: true,
create: false,
edit: false,
title: 'Title ID',
width: '10%'
},
employeetitle: {
title: 'Employee Title',
options: 'DropdownSelectors.php?Selector=employeetitle',
optionsSorting: 'text',
width: '45%'
}
}
});
//Load person list from server
$('#EmployeeTitles').jtable('load');
});
</script>
</body>
</html>
Let's create the personactions.php file which runs the SQL queries for action==list:
<?php
// Connect to SQL Server
include '../../phpconfig/connectstrings.php';
try
{
$conn = new PDO ( "sqlsrv:server = $serverstring; Database = $databasestring", "$usernamestring", "$passwordstring");
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch ( PDOException $e )
{
print( "Error connecting to SQL Server." );
die(print_r($e));
}
catch(Exception $e)
{
die(var_dump($e));
}
try {
//Getting records (listAction)
if($_GET["action"] == "list")
{
//Get records from database
$sql_select = "SELECT employeetitleid, employeetitle FROM employee_titles";
$stmt = $conn->query($sql_select);
//Add all records to an array
$rows = $stmt->fetchall(PDO::FETCH_ASSOC);
//Return result to jTable
$jTableResult = array();
$jTableResult['Result'] = "OK";
$jTableResult['Records'] = $rows;
print json_encode($jTableResult);
}
//Creating a new record (createAction)
else if($_GET["action"] == "create")
{
//Insert record into database
$sql_insert = "INSERT INTO employee_titles (employeetitle) VALUES (?)";
$stmt = $conn->prepare($sql_insert);
$stmt->bindValue(1, $_POST['employeetitle']);
$stmt->execute();
//Get last inserted record (to return to jTable)
$sql_select = "SELECT employeetitleid, employeetitle FROM employee_titles WHERE employeetitleid = ##IDENTITY";
$stmt = $conn->prepare($sql_select);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
//Return result to jTable
$jTableResult = array();
$jTableResult['Result'] = "OK";
$jTableResult['Record'] = $row;
print json_encode($jTableResult);
}
//Updating a record (updateAction)
else if($_GET["action"] == "update")
{
//Update record in database
$sql_update = "UPDATE employee_titles SET employeetitle = ? WHERE employeetitleid = ?;";
$stmt = $conn->prepare($sql_update);
$stmt->bindValue(1, $_POST['employeetitle']);
$stmt->bindValue(2, $_POST['employeetitleid']);
$stmt->execute();
//Return result to jTable
$jTableResult = array();
$jTableResult['Result'] = "OK";
print json_encode($jTableResult);
}
//Deleting a record (deleteAction)
else if($_GET["action"] == "delete")
{
//Delete from database
$sql_delete = "DELETE FROM employee_titles WHERE employeetitleid = ?;";
$stmt = $conn->prepare($sql_delete);
$stmt->bindValue(1, $_POST['employeetitleid']);
$stmt->execute();
//Return result to jTable
$jTableResult = array();
$jTableResult['Result'] = "OK";
print json_encode($jTableResult);
}
//Close database connection
$conn = null;
}
catch(Exception $ex)
{
//Return error message
$jTableResult = array();
$jTableResult['Result'] = "ERROR";
$jTableResult['Message'] = $ex->getMessage();
print json_encode($jTableResult);
}
?>
Finally, let's make the DropdownSelectors.php file that is going to query our dropdown contents. depending on how I construct this file I will get 2 different results with neither being satisfactory.
In this 1st example I am going to make [DisplayText] == [Value]. This will correctly display the employee title information in the jtable view and correctly populate the dropdown for create/edit. However, the [Value] reported by the dropdown is not nearly as useful for later queries as it would be if it were actually the employeetitleid as opposed to just a repeat of the employeetitle. The code as shown in both examples produces a perfect match of the type of array expected by jtable as referenced here: http://www.jtable.org/apireference#fopt-options . This should not be in dispute since the create/edit dropdown will work in either example.
Example DropdownSelectors.php #1:
<?php
// Connect to SQL Server
include '../../../phpconfig/connectstrings.php';
try
{
$conn = new PDO ( "sqlsrv:server = $serverstring; Database = $databasestring", "$usernamestring", "$passwordstring");
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch ( PDOException $e )
{
print( "Error connecting to SQL Server." );
die(print_r($e));
}
catch(Exception $e)
{
die(var_dump($e));
}
if ($_GET['Selector'] == "employeetitle") {
$sql_select = "SELECT employeetitle [DisplayText], employeetitle [Value] FROM employee_titles";
$stmt = $conn->prepare($sql_select);
$stmt->execute();
$rows= $stmt->fetchAll(PDO::FETCH_ASSOC);
$options[Result] = 'OK';
$options[Options] = $rows;
print json_encode($options);
}
?>
In this 2nd example I am going to make [DisplayText] and [Value] pull from different columns in the employee_titles table. This will cause the employee title column of the jtable to be blank but still correctly populate the dropdown for create/edit. In this case, the [Value] reported by the dropdown is very useful for later queries as it actually reports the employeetitleid as opposed to just a repeat of the employeetitle. The code as shown in both examples produces a perfect match of the type of array expected by jtable as referenced here: http://www.jtable.org/apireference#fopt-options . This should not be in dispute since the create/edit dropdown will work in either example. It is completely unacceptable that the displayed jtable column appear blank, however.
Example DropdownSelectors.php #2:
<?php
// Connect to SQL Server
include '../../../phpconfig/connectstrings.php';
try
{
$conn = new PDO ( "sqlsrv:server = $serverstring; Database = $databasestring", "$usernamestring", "$passwordstring");
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch ( PDOException $e )
{
print( "Error connecting to SQL Server." );
die(print_r($e));
}
catch(Exception $e)
{
die(var_dump($e));
}
if ($_GET['Selector'] == "employeetitle") {
$sql_select = "SELECT employeetitle [DisplayText], employeetitleid [Value] FROM employee_titles";
$stmt = $conn->prepare($sql_select);
$stmt->execute();
$rows= $stmt->fetchAll(PDO::FETCH_ASSOC);
$options[Result] = 'OK';
$options[Options] = $rows;
print json_encode($options);
}
?>
Now that you have all of the code necessary to completely reproduce this very reproducible issue can anyone tell me how to fix it so htat the listed fields display the DisplayText and the dropdown options issue the vlaue that equates to an ID #? I am beginning to believe there is a display bug in jtable itself and that a small fix somewhere would cause the information to appear in the jtable view.
See the linked github issue for some of the workarounds I have attempted and why they do not work.
Okay! I solved this one. Holy cow do I feel dumb. I had a faulty understanding of how Value relates to the record and field name. I had assumed Value was strictly the information passed when a dropdown selection was made. However, as I see now, Value also corresponds to the the record that is contained in the jtable field. Thus, the fieldname will have to correspond to the column name the data comes under just like a standard jtable field does. Value must correspond to that column. So, to fix the provided example we do the following:
if ($_GET['Selector'] == "employeetitleid") {
$sql_select = "SELECT employeetitle [DisplayText], employeetitleid [Value] FROM employee_titles";
$stmt = $conn->prepare($sql_select);
$stmt->execute();
$rows= $stmt->fetchAll(PDO::FETCH_ASSOC);
$options[Result] = 'OK';
$options[Options] = $rows;
print json_encode($options);
}
and
employeetitleid: {
title: 'Employee Title',
dependsOn: 'anotherfield',
options: function (data) { if (data.source == 'list') { return 'DropdownSelectors.php?Selector=employeetitleid&filter=>0'; }
return './../DropdownSelectors.php?Selector=employeetitleid&filter==' + data.dependedValues.anotherfield },
optionsSorting: 'text',
width: '45%'
}
The above example also includes the logic to operate the DepndsOn feature for cascaded dropdowns which is how I ran into this issue to begin with (having [Value]==[DisplayText] "worked well until then). In this example the jtable will show a column name of "Employee title" and the fields will show the text strings that correlate to the title id number. However the actual data being worked with is the title id number which, not surprisingly, makes all of the queries and the field configurations must easier and more efficient.

Categories