I'm trying to do a pagination page with this tutorial, but keep getting errors.
Here is my code:
<?php include "common.php"; ?>
<?php
$query = "SELECT COUNT(id) FROM actiongame";
try
{
// These two statements run the query against your database table.
$stmt = $db->prepare($query);
$stmt->execute();
}
catch(PDOException $ex)
{
// Note: On a production website, you should not output $ex->getMessage().
// It may provide an attacker with helpful information about your code.
die("Failed to run query: " . $ex->getMessage());
}
$rows = $stmt->fetchAll();
foreach($rows as $row):
$total_records = $row;print_r($total_records);
//just to see what is the $total_records
// i get this reult with print_r : Array ( [COUNT(id)] => 2969 )
$total_pages = ceil($total_records / 48);
//but i get fatal error = =
//Fatal error: Unsupported operand types in C:\wamp\www\category.php on line
print_r($total_pages);
endforeach;
unset($row);
?>
My question is, how do I set the $total_records
to 2969 and use the ceil($total_record / 48)?
Here is my db connect script common.php code:
// These variables define the connection information for your MySQL database
$username = 'root';
$password = '';
$host = 'localhost';
$dbname = 'minigame';
// UTF-8 is a character encoding scheme that allows you to conveniently store
// a wide varienty of special characters, like ¢ or €, in your database.
// By passing the following $options array to the database connection code we
// are telling the MySQL server that we want to communicate with it using UTF-8
// See Wikipedia for more information on UTF-8:
// http://en.wikipedia.org/wiki/UTF-8
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
// A try/catch statement is a common method of error handling in object oriented code.
// First, PHP executes the code within the try block. If at any time it encounters an
// error while executing that code, it stops immediately and jumps down to the
// catch block. For more detailed information on exceptions and try/catch blocks:
// http://us2.php.net/manual/en/language.exceptions.php
try
{
// This statement opens a connection to your database using the PDO library
// PDO is designed to provide a flexible interface between PHP and many
// different types of database servers. For more information on PDO:
// http://us2.php.net/manual/en/class.pdo.php
$db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
}
catch(PDOException $ex)
{
// If an error occurs while opening a connection to your database, it will
// be trapped here. The script will output an error and stop executing.
// Note: On a production website, you should not output $ex->getMessage().
// It may provide an attacker with helpful information about your code
// (like your database username and password).
die("Failed to connect to the database: " . $ex->getMessage());
}
// This statement configures PDO to throw an exception when it encounters
// an error. This allows us to use try/catch blocks to trap database errors.
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// This statement configures PDO to return database rows from your database using an associative
// array. This means the array will have string indexes, where the string value
// represents the name of the column in your database.
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// This block of code is used to undo magic quotes. Magic quotes are a terrible
// feature that was removed from PHP as of PHP 5.4. However, older installations
// of PHP may still have magic quotes enabled and this code is necessary to
// prevent them from causing problems. For more information on magic quotes:
// http://php.net/manual/en/security.magicquotes.php
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
{
function undo_magic_quotes_gpc(&$array)
{
foreach($array as &$value)
{
if(is_array($value))
{
undo_magic_quotes_gpc($value);
}
else
{
$value = stripslashes($value);
}
}
}
undo_magic_quotes_gpc($_POST);
undo_magic_quotes_gpc($_GET);
undo_magic_quotes_gpc($_COOKIE);
}
// This tells the web browser that your content is encoded using UTF-8
// and that it should submit content back to you using UTF-8
header('Content-Type: text/html; charset=utf-8');
// This initializes a session. Sessions are used to store information about
// a visitor from one web page visit to the next. Unlike a cookie, the information is
// stored on the server-side and cannot be modified by the visitor. However,
// note that in most cases sessions do still use cookies and require the visitor
// to have cookies enabled. For more information about sessions:
// http://us.php.net/manual/en/book.session.php
session_start();
// Note that it is a good practice to NOT end your PHP files with a closing PHP tag.
// This prevents trailing newlines on the file from being included in your output,
// which can cause problems with redirecting users.
You're trying to ceil an array, you can do it on a numeric value.
Try editing your query like this:
$query = "SELECT COUNT(id) AS tot FROM actiongame";
And then your PHP code like this:
$total_records = $row['tot'];
Related
I have a simple question. I'm not too good at programming yet but is this safe and correct?
Currently I am using functions to grab the username, avatars, etc.
Looks like this:
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
config.php ^^
function getUsername($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT username FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$name = $stmt->fetch();
return $name["username"];
}
function getProfilePicture($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$image = $stmt->fetch();
return $image["profilepicture"];
}
Is this correct and even more important, is this safe?
Yes, it's safe with respect to SQL injections.
Some other answers are getting off topic into XSS protection, but the code you show doesn't echo anything, it just fetches from the database and returns values from functions. I recommend against pre-escaping values as you return them from functions, because it's not certain that you'll be calling that function with the intention of echoing the result to an HTML response.
It's unnecessary to use is_int() because MySQL will automatically cast to an integer when you use a parameter in a numeric context. A non-numeric string is interpreted as zero. In other words, the following predicates give the same results.
WHERE id = 0
WHERE id = '0'
WHERE id = 'banana'
I recommend against connecting to the database in every function. MySQL's connection code is fairly quick (especially compared to some other RDBMS), but it's still wasteful to make a new connection for every SQL query. Instead, connect to the database once and pass the connection to the function.
When you connect to your database, you catch the exception and echo an error, but then your code is allowed to continue as if the connection succeeded. Instead, you should make your script die if there's a problem. Also, don't output the system error message to users, since they can't do anything with that information and it might reveal too much about your code. Log the error for your own troubleshooting, but output something more general.
You may also consider defining a function for your connection, and a class for your user. Here's an example, although I have not tested it:
function dbConnect() {
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
error_log("PDO connection failed: " . $e->getMessage());
die("Application failure, please contact administrator");
}
}
class User {
protected $row;
public function __construct($userid) {
global $conn;
if (!isset($conn)) {
$conn = dbConnect();
}
$stmt = $conn->prepare("SELECT username, profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$this->row = $stmt->fetch(PDO::FETCH_ASSOC);
}
function getUsername() {
return $this->row["username"]
}
function getProfilePicture() {
return $this->row["profilepicture"]
}
}
Usage:
$user = new User(123);
$username = $user->getUsername();
$profilePicture = $user->getProfilePicture();
That looks like it would work assuming that your config file is correct. Because it is a prepared statement it looks fine as far as security.
They are only passing in the id. One thing you could do to add some security is ensure that the $userid that is passed in is the proper type. (I am assuming an int).
For example if you are expecting an integer ID coming in and you get a string that might be phishy (possible SQL injection), but if you can confirm that it is an int (perhaps throw an error if it isn't) then you can be sure you are getting what you want.
You can use:
is_int($userid);
To ensure it is an int
More details for is_int() at http://php.net/manual/en/function.is-int.php
Hope this helps.
It is safe (at least this part of the code, I have no idea about the database connection part as pointed out by #icecub), but some things you should pay attention to are:
You only need to require your config.php once on the start of the file
You only need to prepare the statement once then call it on the function, preparing it every time might slow down your script:
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. - PHP Docs
(Not an error but I personally recommend it) Use Object Orientation to help organize your code better and make easier to mantain/understand
As stated by #BHinkson, you could use is_int to validate the ID of the user (if you are using the IDs as numbers)
Regarding HTML escaping, I'd recommend that you already register your username and etc. HTML escaped.
I have a PHP file included but everything after the <?php include 'RandomFile.php' ?> gets thrown away, I have no clue why! I need help with this.
RandomFile.php has the contents of:
require 'cons.php';
mysql_connect($URL, $USER, $PASS, $DBN);
$strSQL = "SELECT * FROM song";
// Execute the query (the recordset $rs contains the result)
$rs = mysql_query($strSQL);
// Loop the recordset $rs
// Each row will be made into an array ($row) using mysql_fetch_array
if($rs === FALSE) {
die(mysql_error()); // TODO: better error handling
}
while($row = mysql_fetch_array($rs)) {
// Write the value of the column FirstName (which is now in the array $row)
echo $row['url'] . "<br />";
}
// Close the database connection
mysql_close();
So Basically after the <?php include 'randomfile.php' ?> is included all my html after that isn't showing up visually in my browser but if I go back and edit the file it is there???
I'm guessing that cons.php is the connection file for your database. You need to specify the full path to cons.php. From the PHP Manual for require:
require is identical to include except upon failure it will also
produce a fatal E_COMPILE_ERROR level error. In other words, it will
halt the script whereas include only emits a warning (E_WARNING) which
allows the script to continue.
So this example shows the file at the root.
require ($_SERVER['DOCUMENT_ROOT'].'/cons.php');
If it's below the DocumentRoot then you would do this:
require ($_SERVER['DOCUMENT_ROOT'].'/../cons.php');
On another note, replace all of the mysql_ functions with mysqli_. New versions of PHP will not include it as mysql_ has been deprecated.
Since you are trying a SQL query without selecting a database first, mysql fails with the error "No database selected"
The error is displayed with the code die(mysql_error());. die aborts further execution of the script. If you'd like it to continue you should just print it instead like this
if($rs === FALSE) {
print(mysql_error() . "\n"); // TODO: better error handling
}
else {
while($row = mysql_fetch_array($rs)) {
// Write the value of the column FirstName (which is now in the array $row)
echo $row['url'] . "<br />";
}
// Close the database connection
mysql_close();
}
The key is this line:
die(mysql_error()); // TODO: better error handling
If there is an error connecting to the database (as you described in your comment: "no database selected"), the execution will "die" and no more of the page will be sent to the browser.
As the code comment says, you need better error handling, but you might conceivably temporarily change the die to an echo and then the execution will continue.
Are you missing the semicolon (;) in the include?
Btw, you could set
<?php error_reporting(E_ALL);
ini_set('display_errors', '1'); ?>
this will show you the errors in your script.
I'm making chat in flash as3 with php and mysql database.
However I don't know php at all, and got problem with updating messages.
for now my php file looks like this:
$caster = $_POST['caster'];
$msgText = $_POST['msgText'];
$sendTime = $_POST['sendTime'];
$query = "INSERT INTO chat VALUES ('','$sendTime','$caster','$msgText')"
mysql_query($query);
$query="SELECT * FROM chat";
$result=mysql_query($query);
$cast=mysql_result($result,1,"caster");
mysql_close();
$returnVars = array();
$returnVars['success'] = $success;
$returnVars['caster'] = $cast;
$returnString = http_build_query($returnVars);
echo $returnString;
And my question is how to loop for all already sent chat messages to send them to flash.
I can only do it with one, but I need whole bunch of them to be loaded.
Thanks
What you are looking for is "fetchAll". Note that your code is open to SQL injection, it is very easy to drop your database by passing evil values to the PHP script. I have changed the code therefore from the deprecated Mysql extension to PDO. PDO will to the escaping of the values for you.
Read more on PDO in the PHP manual (Lots of examples over there).
Also note that you have to adapt the following code snipped as I could not guess how the field names of the chat table in your database are named. So you have to adapt the insert statement below.
// database config parameters
$dbhost = "localhost";
$dbname = "test";
$dbuser = "root";
$dbpass = "";
try {
// try to set up a db connection
$db = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
// insert the data using PDO's prepared statements
// you have to adapt this line to the field names of your chat table!!
$sql = "INSERT INTO chat (sendtime,caster,msg) VALUES (:sendtime,:caster,:msg)";
$sth = $db->prepare($sql);
$sth->execute(array(
':caster' => $_POST['caster'],
':sendtime' => $_POST['sendTime'],
':msg' => $_POST['msgText']
));
// Get everything
$sth = $db->prepare("SELECT * FROM chat");
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
// your code to format and return the data goes here
print json_encode($result);
}
catch (PDOException $e) {
// if anything related to the database goes wrong, catch the exceptions
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
$db = null;
The Actionscript will receive a JSON object looking similar to this:
[
{
"sendtime":"2013-04-14",
"caster":"person1",
"msg":"Message 1"
},
{
"sendtime":"2013-04-15",
"caster":"person2",
"msg":"Message 2"
}
]
As you can see the JSON has no specific variable name like in the version with GET used in the question (the method used in the question does not work for large result lists).
So how do you work with the JSON document in Actionscript? I am not an actionscript programmer, but this Stackoverflow post looks like a reasonable answer to this problem:
Get and parse JSON in Actionscript
I believe I have the syntax correct, at least according to my textbook. This is just a piece of the file as the other info is irrelevant to my problem. The table name is user, as well as the column name is user. I don't believe this to be the problem, as other sql statements work. Though it isn't the smartest thing to do I know :) Anyone see an error?
try {
$db=new PDO("mysql:host=$db_host;dbname=$db_name",
$db_user,$db_pass);
} catch (PDOException $e) {
exit("Error connecting to database: " . $e->getMessage());
}
$user=$_SESSION["user"];
$pickselect = "SELECT game1 FROM user WHERE user='$user' ";
$pickedyet = $db->prepare($pickselect);
$pickedyet->execute();
echo $pickselect;
if ($pickedyet == "0")
{
echo '<form method="post" action="makepicks.php">
<h2>Game 1</h2>......'
Since you're seemingly using prepared statements, I'd recommend using them to their fullest extent so that you can avoid traditional problems like SQL injection (this is when someone passes malicious SQL code to your application, it's partially avoided by cleansing user inputs and/or using bound prepared statements).
Beyond that, you've got to actually fetch the results of your query in order to display them (assuming that's your goal). PHP has very strong documentation with good examples. Here are some links: fetchAll; prepare; bindParam.
Here is an example:
try
{
$db = new PDO("mysql:host=$db_host;dbname=$db_name",
$db_user, $db_pass);
}
catch (PDOException $e)
{
exit('Error connecting to database: ' . $e->getMessage());
}
$user = $_SESSION['user'];
$pickedyet = $db->prepare('SELECT game1 FROM user WHERE user = :user');
/* Bind the parameter :user using bindParam - no need for quotes */
$pickedyet->bindParam(':user', $user);
$pickedyet->execute();
/* fetchAll used for example, you may want to just fetch one row (see fetch) */
$results = $pickedyet->fetchAll(PDO::FETCH_ASSOC);
/* Dump the $results variable, which should be a multi-dimensional array */
var_dump($results);
EDIT - I'm also assuming that there is a table called 'user' with a column called 'user' and another column called 'game1' (i.e. that your SQL statement is correct aside from the usage of bound parameters).
<?php
session_start();
$db_user = 'example';
$db_pass = 'xxxxx';
try
{
// nothing was wrong here - using braces is better since it remove any confusion as to what the variable name is
$db=new PDO( "mysql:host={$db_host}dbname={$db_name}", $db_user, $db_pass);
}
catch ( Exception $e ) // catch all exceptions here just in case
{
exit( "Error connecting to database: " . $e->getMessage() );
}
// this line is unecessary unless you're using it later.
//$user = $_SESSION["user"];
// no need for a new variable here, just send it directly to the prepare method
// $pickselect = '...';
// also, I changed it to a * to get the entire record.
$statement = $db->prepare( "SELECT * FROM user WHERE user=:user" );
// http://www.php.net/manual/en/pdostatement.bindvalue.php
$statement->bindValue( ':user', $_SESSION['user'], PDO::PARAM_STR );
$statement->execute();
// http://www.php.net/manual/en/pdostatement.fetch.php
// fetches an object representing the db row.
// PDO::FETCH_ASSOC is another possibility
$userRow = $statement->fetch( PDO::FETCH_OBJ );
var_dump( $userRow );
echo $userRow->game1;
Change this user=$user with this user='$user'. Please, note the single quotes.
Moreover, you are executing the query $pickedyet->execute(); but then you do echo $pickselect; which is nothing different from the string that contains the query.
Little hints:
You've to retrieve the result of the query execution.
You're using prepared statement which are very good but you're not really using they because you're not doing any binding.
I'm trying to write php script that would:
connect to mysql
create database
create user and password
add user to database
import prepared sql file to database
The thing is that it'll be on shared host (and I'm trying to make it universal and work with different hosts). I guess database and db user will be prefixed with my account name (what I use for ftp, to login to control panel, etc) on shared hosts? Something like mylogin_dbname and mylogin_dbuser. It's visible for example in cpanel - when I add database I enter its name and after it's created cpanel shows it as mylogin_somedb. How do I make my script work with this on multiple different shared hosts - add my prefix automatically depending on my main login?
Now working with such code (don't have a clue if it works, that's just what came to my mind):
<?php
mysql_connect("host", "user", "password"); // Connection to MySQL
$query = "CREATE DATABASE somedb;
USE somedb;
SOURCE path/to/sqlfile.sql;
CREATE USER someuser IDENTIFIED BY PASSWORD 'somepass';
GRANT SELECT,INSERT,UPDATE,DELETE ON somedb.* TO 'someuser'#'host';";
$arr= explode( ';', $query );
foreach( $arr as $command )
{
mysql_query( $command );
}
mysql_close(); // Disconnection from MySQL
?>
KISS principle: just use phpMyAdmin? It's almost certainly installed. If it's not, install it.
Its import capability is magnificent. If your database is by any chance too big, gzip it. If it's still to big, try splitting it up in a few pieces. I doubt you need to transfer it as a single big transaction. Do you?
After the explanation in first comment, well, here goes. This is my very simplistic script which does what you want. Except it doesn't take a look at the separators: one query == one line.
<link rel="stylesheet" href="style/contents.css"/>
<?
function timesanitize($v) {
if ($v > 0)
return round($v, 4);
else
return 0;
}
$startmt = microtime();
include_once 'include/db.php';
$f = fopen("db.sql","r");
echo dbGetEngine() . "<br>";
echo "<ul>";
do {
$l = rtrim(fgets($f));
if (strlen($l) == 0)
continue;
if (substr($l, 0, 1) == '#')
continue;
$l = str_replace(
array("\\n"),
array("\n"),
$l);
if (dbGetEngine() == "pgsql")
$l = str_replace(
array("IF NOT EXISTS", "LONGBLOB"),
array("", "TEXT"),
$l);
try {
echo "<li>".nl2br(htmlspecialchars($l));
$mt = microtime();
$db->query($l);
echo "<ul><li>ok - " . timesanitize(microtime() - $mt) . "</ul>";
} catch (PDOException $e) {
echo "<ul><li>".$e->getMessage() . "</ul>";
}
} while (!feof($f));
fclose($f);
echo 'total: ' . timesanitize(microtime() - $startmt);
?>
It also outputs a small statistic of how long each query took. It's based around PDO; I believe PDO was introduced in PHP5.1 or PHP5.2. I think it should be trivial to modify it to work directly with mysql_*() functions, if for some reason you prefer that.
And once again: yes, I know it sucks. But as long as it Works For Me (tm), and possibly You... :-)
To complete the code, here are include/db.php and a sample include/config.php:
include/db.php:
<?
include_once 'include/config.php';
try {
$attribs =
array(
PDO::ATTR_PERSISTENT => $config['db']['persistent'],
PDO::ATTR_ERRMODE => $config['db']['errormode']
);
$db = new PDO(
$config['db']['uri'],
$config['db']['user'],
$config['db']['pass'],
$attribs
);
$db->query("SET NAMES 'utf8'");
$db->query("SET CHARACTER SET 'utf8'");
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
function dbGetEngine() {
global $config;
return substr($config['db']['uri'], 0, strpos($config['db']['uri'], ':'));
}
?>
include/config.php:
<?
//$config['db']['uri'] = 'sqlite:' . realpath('.') . '/site.db'; // PDO's database access URI
$config['db']['uri'] = 'mysql:host=localhost;dbname=sitedb'; // server should be : 195.78.32.7
//$config['db']['uri'] = 'pgsql:host=localhost;dbname=sitedb';
$config['db']['user'] = 'user_goes_here'; // database username
$config['db']['pass'] = 'pass_goes_here'; // database password
$config['db']['persistent'] = false; // should the connection be persistent
$config['db']['errormode'] = PDO::ERRMODE_EXCEPTION; // PDO's error mode
?>
Included are sample connection strings for SQLite, MySQL and PostgreSQL.
The fact that this is on a shared host shouldn't make that much of a difference in my opinion. Whatever your environment, you'll have to use your username and either the database name gets prefixed with that or it doesn't according to hosting setup. That said it is probably smart to adopt a naming convention with your username as a prefix or some other prefix naming convention.
As to what you're trying to do I have some suggestions:
You should run each statement separately (as you do) but add error checking between each step so you don't attempt to source the file if the database wasn't created for instance.
Maybe create separate functions for each kind of operation and send in parameters for the values. This would clean up the code in the longer run.
If you have a situation where something is automatically prefixed to the name you provide and you have to detect the final name, you can probably do a "show databases;" query and search for the name you gave in the results. Then use the complete name for the resulting queries.
Use mysql_error()
http://us3.php.net/manual/en/function.mysql-error.php
So you can see what went wrong.
eg:
if (mysql_query( $command ) === false) {
echo mysql_error();
die;
}
The same for mysql_connect()
if (($link = mysql_connect("host", "user", "password")) === false) {
echo mysql_error();
die;
}
You have to make sure the user you are using has privileges to create databases.
For CPanel I believe you have to use your account username and pass. Then like you said prefix your db name with your username, or it will fail to create.
Regarding import, if upload limit is an issue, there are at least one alternative to phpMyAdmin that allows you to select a file on the webserver instead of uploading it. For example adminer (adminer.org) allows that. In adminer, click "SQL command" and then click "from server"