So, I've been having a bit of trouble getting MySQL to work.
My Apache server is up and running, PHP is properly installed, and my MySQL server status is running.
When I call phpinfo() it tells me where the mysql.sock is located, both the folder and file exist.
I'm running OSX 10.8.4
I'm following this tutorial to try to get a grasp of how chats would work: http://www.ibm.com/developerworks/library/x-ioschat/
So when I run my php script, the page loads with errors. I'm new to PHP, and am having a difficult time debugging, installation was particularly troublesome.
So if I keep content-type: text/xml uncommented I get this error:
error on line 2 at column 1: Document is empty
It also tells me that the page is rendered up to the first error, so it makes sense that the page is blank when I load it.
When it is commented, the errors begin to make a bit more sense; however, given my absolute newbish nature to PHP I'm not really sure how to navigate them.
Here are the errors:
Notice: Undefined index: past in /messages.php on line 6
-- This makes sense, I think. I haven't built the client side yet, so there should be no past variable provided.
Warning: mysql_fetch_assoc() expects parameter 1 to be resource,
boolean given in /messages.php on line 16
--So, my background is client side, so what this tells me is that my $result variable has a boolean stored in it, instead of whatever is supposed to be in it for the mysql_fetch_assoc() function call. Since the else statement should trigger, that means that either mysql_query() is not working how properly, or my parameter for it is incorrect. I don't know which (if either), nor do I know the solution to either.
Warning: mysql_free_result() expects parameter 1 to be resource,
boolean given in /messages.php on line 24
--Again, same as above; semi-makes sense, very unsure how to go about fixing it.
So, after the errors, nothing is displayed below. Which makes sense because the conditions are written under the assumption they'll have a resource in it, not a boolean (I think??)
In my php file, if you compare it with the tutorial you'll see I took out the htmlentities() calls because I read on StackOverflow that they are not needed, and they didn't change the state of the errors I was getting either way.
Anyway, thanks so much for any advice/help given!
Here is my code so far:
chat.sql:
DROP TABLE IF EXISTS chatitems;
CREATE TABLE chatitems (
id BIGINT NOT NULL PRIMARY KEY auto_increment,
added TIMESTAMP NOT NULL,
user VARCHAR(64) NOT NULL,
message VARCHAR(255) NOT NULL
);
messages.php:
<?php
ini_set('display_errors','1');
//header( 'Content-type: text/xml' );
mysql_connect( 'localhost:/private/var/mysql/mysql.sock', 'root', '' );
mysql_select_db( 'http://localhost/Documents/JoistChat/chat.sql' );
if ( $_REQUEST['past'] ) {
$result = mysql_query('SELECT * FROM chatitems WHERE id > '.
mysql_real_escape_string( $_REQUEST['past'] ).
' ORDER BY added LIMIT 50');
} else {
$result = mysql_query('SELECT * FROM chatitems ORDER BY added LIMIT 50' );
}
?>
<chat>
<?php
while ($row = mysql_fetch_assoc($result)) {
?>
<message added="<?php echo( $row['added'] ) ?>" id="<?php echo( $row['id'] ) ?>">
<user><?php echo( $row['user'] ) ?></user>
<text><?php echo( $row['message'])?></text>
</message>
<?php
}
mysql_free_result($result);
?>
</chat>
test.html:
<html>
<head>
<title>Chat Message Test Form</title>
</head>
<body>
<form action="http://localhost/JoistChat/messages.php"
method="POST">
User: <input name="user" /><br />
Message: <input name="message" /><br />
<input type="submit" />
</form>
</body>
</html>
$past = '';
if ( !empty($_REQUEST['past']) ) {
$past = 'WHERE id > '.intval($_REQUEST['past']);
}
$sql = 'SELECT * FROM chatitems $past ORDER BY added LIMIT 50'
$result = mysql_query($sql) or trigger_error(mysql_error()." [$sql]");
You need to learn basic coding culture. Basic guidelines are
Do no repeat yourself. You are writing all the stuff twice
Always check for error
Do not stack too much code in one line. Make your code distinct, step by step. Need a program to create an SQL query? Okay. get the product of this code in a variable and pass it over. Do not fold all the program in a single line.
Format your SQL properly
This way you'll always know the reason of the problem and have your code run smooth and easier to maintain.
Also just noted that your way of selecting a database is quite a... strange. 'chat.sql' is a file with table creation code, not database. You have to create a database first, then create a table in it, then select newly created database.
As you have been told already, mysql ext is obsoleted. You have to use use PDO instead, as it's the only choice for PHP users whose only idea of database interaction is direct calls to API.
First, create a file with connection options, pdo.php
<?php
$dsn = "mysql:host=localhost;dbname=test;charset=utf8";
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
$pdo = new PDO($dsn,'root','', $opt);
Then make your code this way
<?php
ini_set('display_errors','1');
//header( 'Content-type: text/xml' );
include 'pdo.php';
$past = '';
$bind = array();
if ( !empty($_REQUEST['past']) ) {
$past = 'WHERE id > ?';
$bind = array($_REQUEST['past']);
}
$sql = 'SELECT * FROM chatitems $past ORDER BY added LIMIT 50'
$stm = $pdo->prepare($sql);
$stm->execute($bind);
$data = $stm->fetchAll();
?>
<chat>
<?php foreach ($data as $row) { ?>
Since the 'past' index is not set, the boolean condition in the if-statement evaluates to false. As a result the else part is executed.
Your error messages tell you that the query
SELECT * FROM chatitems ORDER BY added LIMIT 50
resulted in a SQL error. Try running that query in your MySql client directly to see what the error is. My guess is that the table/database you are accessing is not created/selected.
Related
I must be missing something really obvious here I think, but what I am trying to do is use MySQL 5.6 and return values through memcache
So I have set up MYSQL to use the memcache plugin, set up the details in the innodb_memcache.containers table
I now have two items in that table, the default ones entered by MySQL and my own settings, both of them have table names.
To get the data via php I use:
$memcache->get($key);
Where $key is the data in the db column
However this returns nothing, I suspect the reason is that, according to the MySQL Docs if no table name is specified, it choose the first one in the list, which is not the one I want, what I don't understand is how I specify the correct table name in the key, so it knows which table to look for the key in.
Additional Information:
table design:
table: codes
id INT PK
code VARCHAR UNIQUE
codeval VARCHAR
innodb_memcache.containers :
name: mycode
db_schema: databaseName
db_table: codes
key_columns: code
value_columns: codeval
flags: id
cas_column: null
expire_time_column: null
unique_idx_name_on_key: code
Code:
$table = "mycode";
$key = "123456";
$memcache = new Memcache;
$memcache->connect($this->CONNECTURL, $this->CONNECTPORT) or die ("Could not connect");
$version = $memcache->getVersion();
echo "Server's version: ".$version."<br/>\n";
$key = "##" . $table . "." . $key . "." . $table;
$get_result = $memcache->get($key);
print_r($get_result);
The above code returns the server version without issue, so the connection is working.
print_r($get_result) returns blank, when it should be returning a value
It does throw a notice: Trying to get property of non-object
So if someone could let me know how I specify with the $key which table I am using to query through memcache, I would be much appreciated!
The table name (table_id in ##table_id) must be the value from your mappings (innodb_memcache.containers), not the actual table name, if that varies.
And if you table name in mappings is mycode, then the resulting query through memcache should look like this:
$table = 'mycode';
$key = '123456';
$memcache->get( '##' . $table . '.' . $key );
There is no extra '.' . $table at the end.
Some details are available from InnoDB memcached Plugin documentation page.
To name a few of importance here:
Use select * from innodb_memcache.containers; to get defined mappings;
Note the queries organization:
For example, ##t1.some_key and ##t2.some_key have the same key value,
but are stored in different tables and so do not conflict.
From: http://dev.mysql.com/doc/refman/5.6/en/innodb-memcached-intro.html
Namespaces: memcached is like a single giant directory, where to keep files from conflicting with each other you might give them elaborate names with prefixes and suffixes. The integrated InnoDB / memcached server lets you use these same naming conventions for keys, with one addition. Key names of the format ##table_id.key.table_id are decoded to reference a specific a table, using mapping data from the innodb_memcache.containers table. The key is looked up in or written to the specified table.
The ## notation only works for individual calls to the get, add, and set functions, not the others such as incr or delete. To designate the default table for all subsequent memcached operations within a session, perform a get request using the ## notation and a table ID, but without the key portion. For example:
get ##table_x
Subsequent get, set, incr, delete and other operations use the table designated by table_x in the innodb_memcache.containers.name column.
If you still have the default tables, you can try using telnet.
Note: This was used on an AWS RDS instance with memcached, it should be the same for any MySQL implementation using memcached, but I'm not sure.
telnet localhost 11211
stats
#=> should return a long list of stats including pid, uptime, etc
get AA
#=> should return
VALUE AA 8 12
HELLO, HELLO
END
quit #exit telnet session
I know this doesn't answer your question, but it might help in troubleshooting.
<?php
$memc = new Memcache;
$memc->addServer('localhost','11211');
if(empty($_POST['film'])) {
?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Simple Memcache Lookup</title>
</head>
<body>
<form method="post">
<p><b>Film</b>: <input type="text" size="20" name="film"></p>
<input type="submit">
</form>
<hr/>
<?php
} else {
echo "Loading data...\n";
$film = htmlspecialchars($_POST['film'], ENT_QUOTES, 'UTF-8');
$mfilms = $memc->get($film);
if ($mfilms) {
printf("<p>Film data for %s loaded from memcache</p>", $mfilms['title']);
foreach (array_keys($mfilms) as $key) {
printf("<p><b>%s</b>: %s</p>", $key, $mfilms[$key]);
}
} else {
$mysqli = mysqli('localhost','sakila','password','sakila');
if (mysqli_connect_error()) {
sprintf("Database error: (%d) %s", mysqli_connect_errno(), mysqli_connect_error());
exit;
}
$sql = sprintf('SELECT * FROM film WHERE title="%s"', $mysqli->real_escape_string($film));
$result = $mysqli->query($sql);
if (!$result) {
sprintf("Database error: (%d) %s", $mysqli->errno, $mysqli->error);
exit;
}
$row = $result->fetch_assoc();
$memc->set($row['title'], $row);
printf("<p>Loaded (%s) from MySQL</p>", htmlspecialchars($row['title'], ENT_QUOTES, 'UTF-8');
}
}
?>
</body>
</html>
With PHP, the connections to the memcached instances are kept open as long as the PHP and associated Apache instance remain running. When adding or removing servers from the list in a running instance (for example, when starting another script that mentions additional servers), the connections are shared, but the script only selects among the instances explicitly configured within the script.
I'm trying to create a variable which is dependent on some information from the database. I'm trying to generate a $path variable which stores a path, depending on what information is recovered from the database.
$linkid = mysql_connect('localhost','user','password');
mysql_select_db("table", $linkid);
$variable = "00001";
$groupID = null;
$temp = mysql_query("SELECT groupID FROM table WHERE memberID='$variable'", $linkid);
while ($row = mysql_fetch_row($temp)){
global $groupID;
foreach ($row as $field){
$groupID = $field;
}
}
....
$path = "C:\WAMP\www\project\\" . $groupID;
$dir_handle = #opendir($path) or die('Unable to open $path');
The idea behind this is that $variable is set before the PHP is run, however it's set to 00001 for testing. The ideal situation is that $path should equal C:\WAMP\www\project\00001\. Currently, when I echo back the $path all I get is the original path without the $groupID added to the end.
I also receive the message "mysql_fetch_row() expects parameter 1 to be resource" but I've used this method for retrieving information before and it worked just fine, and I set up my table in the same way so I don't think the issue is there.
I have a feeling I'm missing something obvious, so any help is appreciated. It's not for an assignment or anything school related (just trying stuff out to learn more) so knock yourselves out with correcting it and explaining why :)
In addition, only one memberID will ever be a match to the $variable, so if there's an alternative way to fetch it I'd appreciate knowing.
Oh, and I know my variable names are shocking but they're only that on here, on my actual code they're different so no criticism please :p
EDIT: The SQL query is correct, after following BT634's advice and when running it on phpMyAdmin I get the groupID I want and expect.
mysql_select_db("table", $linkid)
should actually be
mysql_select_db("database_name", $linkid)
since you are connecting to the database that contains the table and not the table itself.
Also, try mysql_result($temp,0) instead of the while loop
First of all, you're not specifying what database to connect to in your connection - you're specifying what table. You might also want to check how many rows your query is returning:
$temp = mysql_query("SELECT groupID FROM table WHERE memberID='$variable'", $linkid);
echo mysql_num_rows($temp);
If it's still complaining about $temp not being a valid resource, change your MySQL connection code to:
// Establish connection
$con = mysql_connect("localhost","peter","abc123");
if (!$con) die('Could not connect: ' . mysql_error());
mysql_select_db("my_db", $con);
// Make your query
$result = mysql_query("SELECT groupID FROM table WHERE memberID='$variable'");
// Find out what the value of the query is (i.e. what object/resource it is)
var_dump($result);
Once you know that MySQL is returning valid data, extract the values you want. You don't have to use globals:
while ($row = mysql_fetch_row($temp)){
$groupId = $row[0];
}
// Use $groupId however you please...
One thing to bear in mind is that mysql_fetch_row will return
array
(
0 => '...'
)
Whilst mysql_fetch_assoc will return:
array
(
'groupId' => '...'
)
Find out what query it's definitely running, and paste that into a normal MySQL client to make sure your query is correct.
Just do this after defining "$variable"
exit("SELECT groupID FROM table WHERE memberID='$variable'");
Then copy the output into a MySQL client (or MySQL from the command line).
Try something like this:
global $groupID;
$linkid = mysql_connect('localhost','user','password');
mysql_select_db("table", $linkid);
$variable = "00001";
$groupID = null;
$sql = "SELECT groupID FROM table WHERE memberID='$variable'";
$temp = mysql_query($sql, $linkid) or die(mysql_error());
$row = mysql_fetch_row($temp);
if ($row) {
$groupID = $row['groupID'];
}
If you are retrieving a single value, and it is guaranteed to be unique, then the loop structures are unnecessary. I've added a check to ensure the query exits with an error if there's a problem - it is ideal to do this everywhere, so for example do it with mysql_select_db too.
I have a header.php and a footer.php file being included on the same page, they both return some of the same information. Specifically I use this query in each file.
<?php
$q3 = "SELECT page_id, show_id, link_title FROM pages as p WHERE show_id = 1";
$r3 = #mysqli_query ($dbc, $q3); // Run the Query.
while ($nav = mysqli_fetch_array($r3, MYSQLI_ASSOC)) {
echo"<li>{$nav['link_title']}</li>"
}
?>
This is to show the pages in both the header and footer.
However SOMETIMES the second query in the footer returns a "Couldn't fetch mysqli", sometimes it works, sometimes it doesn't. I was wondering should I be using something like mysqli_free_result() would that be better practice?
Even more, is it good practice to free the result after every query? Is there a better way to use the same result from different pages and <?php // ?> tags?
Also, I get the error "too many mysql connections error" every now and then? Is this because I am not closing connections after queries are ran?
You could begin with removing the # from your code. Error suppression is slow and harmful practice.
If you inlcude's are in same scope, you can just save the value of first in some variable, and check in second , if variable has been set.
content of header.php
$storage = '';
$query = "SELECT page_id, show_id, link_title FROM pages as p WHERE show_id = 1";
if ( $result = mysqli_query ($dbc, $query))
{
while ($nav = mysqli_fetch_array($result, MYSQLI_ASSOC))
{
$item = "<li>{$nav['link_title']}</li>";
$storage .= $item;
echo $item;
}
}
else
{
echo 'Query has failed !';
}
content of footer.php
if ( isset( $storage ) && count( $storage ))
{
echo $storage;
}
else
{
echo 'Query has failed !';
}
Read about include() in the fine manual.
And please , stop writing that this procedural perversion. Learn how to do OOP and read about PDO.
Run the query only once, prior to including the header and footer and store the results in a variable - you can use them as many times as you want after that.
mysqli_free_result() should be used only if you have a really large result set, as PHP would take care of free-ing it after it's no longer needed and manually doing this every time just creates extra overhead.
You are getting the "too many connections" error because you're probably opening multiple connections as you do with repeating the same query - create just one before including any other script and just reuse it. You should use the standard mysql extension with mysql_pconnect() for an even better solution to this one ... otherwise - yes, close the connection after you no longer need it.
Sorry if this question may seem easy to some but i cannot seem to figure it out. i was told that i could come here because the guys here are very helpful. i am having problem with the following code. when the uid is call into the url for example page.php?uid=5 i get "some code" if i do page.php?uid=letters i get redirected to page.php?uid=1. that works fine. but if a user should enter page.php?uid=1letters i get this error..Unknown column '1gh' in 'where clause'
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\wamp\www\page.php on line 173.
i only get this error if the user enters unwanted characters at the end of get url id. How can i prevent this from happen how can i have it redirect to page.php?uid=1... see code below
$id = mysql_real_escape_string(#$_GET['uid']);
$query = mysql_query("SELECT user.* FROM user WHERE id = '$id'");
if ((mysql_num_rows($query)==0)) {
header("location:page.php?uid=1");
die();
}
else {
while($rows = mysql_fetch_array($query)){
$foo = $row['foo'];
echo "some code";
mysql_query returns false on error. You should check what it returns:
$query = "SELECT user.* FROM user WHERE id = '$id'"
$result = mysql_query($query);
if ($result === false) {
die($query.'<br/>'.mysql_error());
}
Then you can understand why it failed. I've added the query to the die() statement so you can try the query manually as well.
The error given is unknown column of a string, which suggests you are not enclosing the value with single quotes in the SQL query, even though the code in the question does.
In production you should be taking all steps you can to ensure errors are handled gracefully. In this case you will probably want the same behaviour as not finding a user:
header("location:page.php?uid=1");
Drupal version 6.12
I have a page whose input format is PHP.
I simply want to update a database table. The SQL code appears to be too complex for db_query. I can not make db_query work nor does including php nor does dropping custom php code into the “Body” seem to work either. Any advise on how I can make the following code work inside Drupal?
Here is the code we put in the body. I tried creating a PHP file and just including the PHP file with an INCLUDE statement too.
I know the PHP is error free. it was taken from a site that does not use Drupal!
<?php
if( isset( $_GET['file'] ) )
{
$fileno = $_GET['file'];
$client = $_POST["Client"];
$DBLink = pg_connect("host=XXXX dbname=XXXX user=XXX password=XXXX" );
$sql = "update
webform_submitted_data sd set data = 'A'
where
sd.nid = '27' and
sd.cid = (select wc.cid from webform_component wc where wc.nid = sd.nid and wc.form_key = 'status') and
sd.sid = (select wd.sid from webform_submitted_data wd, webform_component wc
where wc.nid = sd.nid and wc.form_key = 'your_file_' and wd.nid = wc.nid and
wd.data = '$fileno');"
if( ! pg_query($DBLink, $sql) )
{
print( "Database Connection Failure: " . pg_last_error($DBLink));
exit;
}
else
{
print "File: $fileno is now Assigned to $client";
}
pg_close($DBLink);
}
?>
I also tried calling the Drupal APIs for sending an update to the database with no luck either, see code that follows. I actually tried this method first before giving up and trying the code above.
I also tried two versions of the db_query. The one you see below and one where I replaced %s with $fileno in the $sql string and called db_query($sql).
<?php
if( isset( $_GET['file'] ) )
{
$fileno = $_GET['file'];
$client = $_POST["Client"];
$sql = "update
webform_submitted_data sd set data = 'A'
where
sd.nid = '27' and
sd.cid = (select wc.cid from webform_component wc where wc.nid = sd.nid and wc.form_key = 'status') and
sd.sid = (select wd.sid from webform_submitted_data wd, webform_component wc
where wc.nid = sd.nid and wc.form_key = 'your_file_' and wd.nid = wc.nid and
wd.data = '%s');"
db_query($sql, $fileno);
print "File: $fileno is now Assigned to $client";
}
?>
I also put my database in full logging mode, logging connections and all statements and neither query hits the database. In the first case, if I INCLUDE the PHP I get just a white/blank screen -- it's like the PHP code is running but drupal is parsing the code before running it. I just want the code to run AS-IS.
Also, I'm really not interested in creating drupal modules. If it's possible to make this work without a lot of Drupal customizattion, that's what I'm after. This is a short-term tactical fix while we work on a more strategic goal...
Thanks all!
A couple of questions and thoughts:
Are there any database errors that appear on the screen? They usually appear in red 'warning' message boxes at the top of the content after an error has occurred.
Instead of webform_component you should be using {webform_component}. All table names should be in brackets.
The proper way to use data from a form input is to use $form_values[] for a form or $node for a node (if the data is part of a node). Additionally, if you are using the webform module, you can add steps to the submission of a webform. There are some tutorials here.
Last, does php actually reach the if if( isset( $_GET['file'] ) )? Drupal will complain heavily about database errors. So if you don't receive an error message, it means that the query was not executed (never got to that step) or it executed cleanly (but perhaps not with the intended effect).
In my experience, there haven't been queries that have been too complex for drupal because you are entering SQL (sanitized and parametrized) directly.