Uploading And Deleting Photos - php

I have an app that I can upload and delete photos from. Right now I am either able to upload a photo, or I'm able to delete it. But I can't do both for some reason and here's what I mean:
In the code below, in the Photograph class, the variable $db_fields is an array of the columns in the photograph database. If I leave the id field out of the $db_fields array, I am able to upload a photo. But I cannot delete a photo. If I include the id field, I am able to then delete a photo, but now I can't upload one.
What do I need to do here? And if you need to see anything else please let me know.
Thanks,
CM
photograph.php
<?php
require_once(LIB_PATH . DS . 'database.php');
class Photograph extends DatabaseObject {
protected static $table_name = "photographs";
protected static $db_fields = array('id','filename', 'type', 'size', 'caption');
public $id;
public $filename;
public $type;
public $size;
public $caption;
private $temp_path;
protected $upload_dir = "images";
public $errors = array();
protected $upload_errors = array(
UPLOAD_ERR_OK => "No errors.",
UPLOAD_ERR_INI_SIZE => "Larger than upload_max_filesize.",
UPLOAD_ERR_FORM_SIZE => "Larger than form MAX_FILE_SIZE.",
UPLOAD_ERR_PARTIAL => "Partial upload.",
UPLOAD_ERR_NO_FILE => "No file.",
UPLOAD_ERR_NO_TMP_DIR => "No temporary directory.",
UPLOAD_ERR_CANT_WRITE => "Can't write to disk.",
UPLOAD_ERR_EXTENSION => "File upload stopped by extension."
);
public function attach_file($file) {
if (!$file || empty($file) || !is_array($file)) {
$this->errors[] = "No file was uploaded.";
return false;
} elseif ($file['error'] != 0) {
$this->errors[] = $this->upload_errors[$file['error']];
return false;
} else {
$this->temp_path = $file['tmp_name'];
$this->filename = basename($file['name']);
$this->type = $file['type'];
$this->size = $file['size'];
return true;
}
}
public function save() {
if (isset($this->id)) {
$this->update();
} else {
if (!empty($this->errors)) {
return false;
}
if (strlen($this->caption) > 255) {
$this->errors[] = "The caption can only be 255 characters long.";
return false;
}
if (empty($this->filename) || empty($this->temp_path)) {
$this->errors[] = "The file location was not available.";
return false;
}
$target_path = SITE_ROOT . DS . 'public' . DS . $this->upload_dir . DS . $this->filename;
if (file_exists($target_path)) {
$this->errors[] = "The file {$this->filename} already exists.";
return false;
}
if (move_uploaded_file($this->temp_path, $target_path)) {
if ($this->create()) {
unset($this->temp_path);
return true;
}
} else {
$this->errors[] = "The file upload failed, possibly due to incorrect permissions on the upload folder.";
return false;
}
}
}
public function destroy() {
if ($this->delete()) {
$target_path = SITE_ROOT . DS . 'public' . DS . $this->image_path();
return unlink($target_path) ? true : false;
} else {
return false;
}
}
public function image_path() {
return $this->upload_dir . DS . $this->filename;
}
public function size_as_text() {
if ($this->size < 1024) {
return "{$this->size} bytes";
} elseif ($this->size < 1048576) {
$size_kb = round($this->size / 1024);
return "{$size_kb} KB";
} else {
$size_mb = round($this->size / 1048576, 1);
return "{$size_mb} MB";
}
}
public function comments() {
return Comment::find_comments_on($this->id);
}
public static function count_all() {
global $database;
$sql = "SELECT COUNT(*) FROM ".self::$table_name;
$result_set = $database->query($sql);
$row = $database->fetch_array($result_set);
return array_shift($row);
}
}
?>
database_object.php
require_once(LIB_PATH . DS . 'database.php');
class DatabaseObject {
private static $table_name;
public static function find_all() {
global $database;
$query = "SELECT * FROM ".static::$table_name;
return static::find_by_sql($query);
}
public static function find_by_id($id=0) {
global $database;
$query = "SELECT * FROM " . static::$table_name . " WHERE id =".$database->escape_value($id)." LIMIT 1";
$result_array = static::find_by_sql($query);
return !empty($result_array) ? array_shift($result_array) : false;
}
public static function find_by_sql($sql = "") {
global $database;
$result_set = $database->query($sql);
$object_array = array();
while ($row = $database->fetch_array($result_set)) {
$object_array[] = static::instantiate($row);
}
return $object_array;
}
private static function instantiate($record) {
$object = new static();
foreach ($record as $attribute => $value) {
if ($object->has_attribute($attribute)) {
$object->$attribute = $value;
}
}
return $object;
}
private function has_attribute($attribute) {
$object_vars = $this->attributes();
return array_key_exists($attribute, $object_vars);
}
protected function attributes() {
$attributes = array();
foreach (static::$db_fields as $field) {
if (property_exists($this, $field)) {
$attributes[$field] = $this->$field;
}
}
return $attributes;
}
protected function sanitized_attributes() {
global $database;
$clean_attributes = array();
foreach ($this->attributes() as $key => $value) {
$clean_attributes[$key] = $database->escape_value($value);
}
return $clean_attributes;
}
public function save() {
return isset($this->id) ? $this->update() : $this->create();
}
public function create() {
global $database;
$attributes = $this->attributes();
$sql = "INSERT INTO ".static::$table_name." (";
$sql .= join(", ", array_keys($attributes));
$sql .= ") VALUES ('";
$sql .= join("', '", array_values($attributes));
$sql .= "')";
if($database->query($sql)) {
$this->id = $database->insert_id();
return true;
} else {
return false;
}
}
public function update() {
global $database;
$attributes = $this->sanitized_attributes();
$attribute_pairs = array();
foreach ($attributes as $key => $value) {
$attribute_pairs[] = "{$key}='{$value}'";
}
$sql = "UPDATE " . static::$table_name . " SET ";
$sql .= join(", ", $attribute_pairs);
$sql .= " WHERE id=" . $database->escape_value($this->id);
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}
public function delete() {
global $database;
$sql = "DELETE FROM " . static::$table_name;
$sql .= " WHERE id=" . $database->escape_value($this->id);
$sql .= " LIMIT 1";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}
}
?>
photo_upload.php
<?php
require_once('../../includes/initialize.php');
if (!$session->is_logged_in()) {
redirect_to("login.php");
}
?>
<?php
$max_file_size = 10485760; // expressed in bytes
// 10240 = 10 KB
// 102400 = 100 KB
// 1048576 = 1 MB
// 10485760 = 10 MB
//2e+6
$message="";
if (isset($_POST['submit'])) {
$photo = new Photograph();
$photo->caption = $_POST['caption'];
$photo->attach_file($_FILES['file_upload']);
if ($photo->save()) {
// Success
$session->message("Photograph uploaded successfully.");
redirect_to('list_photos.php');
} else {
// Failure
$message = join("<br />", $photo->errors);
}
}
?>
<?php include_layout_template('admin_header.php'); ?>
<h2>Photo Upload</h2>
<?php echo output_message($message); ?>
<form action="photo_upload.php" enctype="multipart/form-data" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $max_file_size; ?>" />
<p><input type="file" name="file_upload" /></p>
<p style="font-color:#000;">Caption: <input type="text" name="caption" value="" /></p>
<input type="submit" name="submit" value="Upload" />
</form>
<?php include_layout_template('admin_footer.php'); ?>
from 'database_object.php'
public function create() {
global $database;
$attributes = $this->attributes();
$sql = "INSERT INTO ".static::$table_name." (";
$sql .= join(", ", array_keys($attributes));
$sql .= ") VALUES ('";
$sql .= join("', '", array_values($attributes));
$sql .= "')";
if($database->query($sql)) {
$this->id = $database->insert_id();
return true;
} else {
return false;
}
}

A summary of the temporary solution, so you can file this question completed.
In the method of create, you would grab all attributes (fields) using $attributes = $this->attributes();, then use the array keys and values to generate the SQL statement.
This would also include the id field.
The problem then occurred from trying to do an INSERT operation and including the id field (which appears to be an auto_increment unique indexed field). This was causing a big problem on create.
A temporary solution, was to drop that field from the $attributes you use to build the query, using unset($attributes['id']); after $attributes = $this->attributes(); would accomplish this, but its not pretty and can be developed better later at your leisure.
I hope I helped, and merry coding ;)

Related

OOP PHP - proper way to pass $_POST values from form to database_write function

I have trouble understanding OOP...
Lets say I wanted to create a page that adds a new user to a database and wanted to work with classes.
For that scenario i'd create a form with a function.
There are forms for each CRUD functionality - renderHTMLFormAddUser() :
...
<form action="" method="POST" >;
<label>Shopname*</label><br>;
<input type="text" name="shopname" class="input_wide" required><br>;
<label>Username*</label><br>;
<input type="text" name="username" class="input_wide" required><br>;
<input type="submit" value="add" name="submit" >
...
a DataBaseConnector class:
class DataBaseConnector
{
protected $con;
public function __construct()
{
$this->con=mysqli_connect('mariaDB','root','123456','produktmuster');
}
public function getConnection()
{
return $this->con;
}
public function __destruct()
{
$this->con->close();
}
}
and a QueryDatabase class that requires the DataBaseConnector connection as a transfer parameter in its constructor:
class QueryDatabase
{
private $con;
public function __construct(DataBaseConnector $con)
{
$this->con = $con;
}
public function addUser($shopname,$username)
{
$sql = "INSERT INTO `brandportal_manager`( `Shopname`, `Username`) VALUES ($shopname,$username)";
$result = mysqli_query($this->con->connect(), $sql);
return $result;
}
To get the $_POST values in the QueryDatabase add User function, i'd need to declare variables like so:
$shopname= $_POST['shopname'];
$username= $_POST['username'];
But is there a better way to do so?
Like maybe renderHTMLFormAddUser()->'shopname'.
Im just trying to understand what is the cleanest way to code in this scenario.
Because using a function to render the forms the adduser.php would look something like this:
$createuserform=new Forms();
$createuserform->renderHTMLFormAddUser();
$shopname= $_POST['shopname']; // this is what confuses me, you'd have to look into the
$username= $_POST['username']; // renderHTMLFormAddUser() function to see the code
$db = new DataBaseConnector();
$query= new QueryDatabase();
$query->addUser($shopname,$username)
Should I just create an own page that posts the form to a page that then uses the data?
In the beginning i simply used no transfer parameters with the addUser function, and it started with declaring the $_POSTs:
$shopname= $_POST['shopname'];
$username= $_POST['username'];
$sql = "INSERT INTO `brandportal_manager`( `Shopname`, `Username`) VALUES ($shopname,$username)";
...
But I was told it was unsafe to do so - in that regard, I sanitize my data but for the sake of easier example i stripped away all the unnecessary code.
Should I take a completely different approach, just would like to know the cleanest way to add form input data into a database.
Well, there are many approaches to do this. You can also do my OOPs approach:
Make a define.php to set the constant variables & database connection variables:
define.php
define("DB_HOSTNAME", "localhost");
define("DB_USERNAME", "your_username");
define("DB_PASSWORD", "your_password");
define("DB_NAME", "your_databasename");
define("custom_variable", "custom_variable_value");
define("baseurl", "https://localhost/myproject/");
Then, make dbase.php, to create a dynamic SQL function:
You don't need to change this file. You just need to call this class. This file work as the core file of the system.
Dbase.php
<?php session_start();
date_default_timezone_set("Asia/Karachi");
require_once("define.php");
Class Dbase
{
private $Host = DB_HOSTNAME;
private $UserName = DB_USERNAME;
private $Password = DB_PASSWORD;
private $DBname = DB_NAME;
private $connDb = false;
public $LastQuery = null;
public $AffectedRows = 0;
public $InsertKey = array();
public $InsertValues = array();
public $UpdateSets = array();
public $id;
public function __construct()
{
$this->connect();
}
protected function connect()
{
$this->connDb = #mysqli_connect($this->Host, $this->UserName, $this->Password);
if (!($this->connDb)) {
die('Database Connection Failed.<br>' . mysql_error($this->connDb));
} else {
$Select = mysqli_select_db($this->connDb,$this->DBname);
if (!$Select) {
die('Database Selection Failed.<br>' . mysql_error($this->connDb));
}
}
mysqli_set_charset($this->connDb,'utf8');
}
public function close()
{
if (!mysqli_close($this->connDb)) {
die('Closing Connection Failed.<br>');
}
}
public function escape($value)
{
if (function_exists('mysql_real_escape_string')) {
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
$value = mysql_real_escape_string($value);
} else {
if (!get_magic_quotes_gpc()) {
$value = addcslashes($value);
}
}
return $value;
}
public function query($sql)
{
$query = $sql;
$result = mysqli_query($this->connDb,$sql);
// $this->displayQuery($result);
return $result;
}
public function displayQuery($result)
{
if (!$result) {
$output = 'Database Query Failed' . mysql_error($this->connDb) . '<br>';
$output .= 'Last Query was' . $this->LastQuery;
die($output);
} else {
$this->AffectedRows = mysqli_affected_rows($this->connDb);
}
}
public function fetchAll($sql)
{
$result = $this->query($sql);
$output = array();
while ($row = mysqli_fetch_assoc($result)) {
$output[] = $row;
}
// mysql_free_result($result);
return $output;
}
public function fetchOne($sql)
{
$output = $this->fetchAll($sql);
return $output;
// return array_shift($output);
}
public function prepareInsert($array = null)
{
if (!empty($array)) {
foreach ($array as $key => $value) {
$this->InsertKey[] = $key;
$this->InsertValues[] = $this->escape($value);
}
}
}
public function insert($table = null)
{
if (!empty($table) && !empty($this->InsertKey) && !empty($this->InsertValues)) {
$sql = "insert into '{$table}' ('";
$sql .= implode("','", $this->InsertKey);
$sql .= "') values ('";
$sql .= implode("','", $this->InsertValues);
$sql .= "')";
if ($this->query($sql)) {
$this->id = $this->lastId();
return true;
}
return false;
} else {
return false;
}
}
public function prepareUpdate($array = null)
{
if (!empty($array)) {
foreach ($array as $key => $value) {
$this->UpdateSets[] = "`{$key}` = '" . $this->escape($value) . "'";
}
}
}
public function update($table = null, $id = null, $whereId)
{
if (!empty($table) && !empty($id) && !empty($this->UpdateSets)) {
$sql = "update `{$table}` set";
$sql .= implode(",", $this->UpdateSets);
// $sql.="where id='".$this->escape($id)."'";
$sql .= "where '" . $whereId . "'='" . $this->escape($id) . "'";
return $this->query($sql);
} else {
return false;
}
}
public function lastId()
{
return mysqli_insert_id($this->connDb);
}
public function TotalNumberOfRecords($sql)
{
$result = $this->query($sql);
$output = mysqli_num_rows($result);
return $output;
}
public function GetServerInfo()
{
return mysqli_get_server_info();
}
}
Create a Query.php file. This file work as your model file as in MVC.
Query.php
<?php include "Dbase.php";
Class Query extends Dbase
{
public function __construct()
{
$this->connect();
date_default_timezone_set("Asia/Karachi");
}
public function getData($idlevelOne)
{
$sql = "SELECT * FROM `table` where level_one_id=$idlevelOne ORDER BY `sorting` ASC";
$result = $this->fetchAll($sql);
return $result;
}
/*For Insert & Edit, use this fucntion*/
public function editMember($email, $phone, $address, $city, $country, $zipcode, $id)
{
$sql = "UPDATE `members` SET `email` = '" . $email . "', `phone` = '" . $phone . "', `address` = '" . $address . "'
, `city` = '" . $city . "', `country` = '" . $country . "', `zip_code` = '" . $zipcode . "'
WHERE `id` = '$id'";
$result = $this->query($sql);
return $result;
}
}
Now, you just need to call the Query class in your PHP files to get the data.
<?php
include "Query.php";
$ObjQuery = new Query();
$ObjQuery->getData(1);

Value of $_GET Superglobal Not Being Passed To Processing Page

Ultimately I am trying to delete an admin by id. I know the id of the admins are making it to the list admins page because I am printing the admin id in the table next to each admin username and seeing the id. But when the delete admin link is clicked, the delete admin page is not receiving the id from the GET superglobal.
Why not?
Thanks,
CM
list_admins.php (contains the delete button at the bottom for deleting an admin)
<?php require_once("../../includes/initialize.php"); ?>
<?php //if (!$session->is_logged_in()) {redirect_to("login.php");} ?>
<?php confirm_logged_in(); ?>
<?php
$admin_set = User::find_all();
$message = "";
?>
<?php $layout_context = "admin"; ?>
<?php include("../layouts/admin_header.php"); ?>
<div id="main">
<div id="navigation">
<br />
« Main menu<br />
</div>
<div id="page">
<?php echo output_message($message); ?>
<h2>Manage Admins</h2>
<table style="border: 1px solid #000; color:#000;">
<tr>
<th style="text-align: left; width: 200px;">Username</th>
<th style="text-align: left; width: 200px;">User Id</th>
<th colspan="2" style="text-align: left;">Actions</th>
</tr>
<?php foreach($admin_set as $admin) : ?>
<tr>
<td><?php echo $admin->username; ?></td>
<td><?php echo $admin->id; ?></td>
<td>Edit</td>
<td>Delete</td>
</tr>
<?php endforeach ?>
</table>
<br />
Add new admin
</div>
</div>
<?php include("../layouts/footer.php"); ?>
delete_admin.php
<?php require_once("../../includes/initialize.php"); ?>
<?php if (!$session->is_logged_in()) { redirect_to("login.php"); } ?>
<?php
//$admin_set = User::find_all();//This works, var_dump shows me the users are
//being returned
//var_dump($admin_set);
$admin = User::find_by_id($_GET['id']);//This returns database query failed.
var_dump($admin);
?>
user.php
<?php
// If it's going to need the database, then it's
// probably smart to require it before we start.
require_once(LIB_PATH.DS.'database.php');
class User extends DatabaseObject {
protected static $table_name="admins";
protected static $db_fields = array('id', 'username', 'password', 'first_name', 'last_name');
public $id;
public $username;
public $password;
public $first_name;
public $last_name;
public function full_name() {
if(isset($this->first_name) && isset($this->last_name)) {
return $this->first_name . " " . $this->last_name;
} else {
return "";
}
}
public static function authenticate($username="", $password="") {
global $database;
$username = $database->escape_value($username);
$password = $database->escape_value($password);
$sql = "SELECT * FROM users ";
$sql .= "WHERE username = '{$username}' ";
$sql .= "AND password = '{$password}' ";
$sql .= "LIMIT 1";
$result_array = self::find_by_sql($sql);
return !empty($result_array) ? array_shift($result_array) : false;
}
// Common Database Methods
public static function find_all() {
return self::find_by_sql("SELECT * FROM ".self::$table_name);
}
public static function find_by_id($id=0) {
$result_array = self::find_by_sql("SELECT * FROM ".self::$table_name." WHERE id={$id} LIMIT 1");
return !empty($result_array) ? array_shift($result_array) : false;
}
public static function find_by_sql($sql="") {
global $database;
$result_set = $database->query($sql);
$object_array = array();
while ($row = $database->fetch_array($result_set)) {
$object_array[] = self::instantiate($row);
}
return $object_array;
}
public static function count_all() {
global $database;
$sql = "SELECT COUNT(*) FROM ".self::$table_name;
$result_set = $database->query($sql);
$row = $database->fetch_array($result_set);
return array_shift($row);
}
private static function instantiate($record) {
// Could check that $record exists and is an array
$object = new self;
// Simple, long-form approach:
// $object->id = $record['id'];
// $object->username = $record['username'];
// $object->password = $record['password'];
// $object->first_name = $record['first_name'];
// $object->last_name = $record['last_name'];
// More dynamic, short-form approach:
foreach($record as $attribute=>$value){
if($object->has_attribute($attribute)) {
$object->$attribute = $value;
}
}
return $object;
}
private function has_attribute($attribute) {
// We don't care about the value, we just want to know if the key exists
// Will return true or false
return array_key_exists($attribute, $this->attributes());
}
protected function attributes() {
// return an array of attribute names and their values
$attributes = array();
foreach(self::$db_fields as $field) {
if(property_exists($this, $field)) {
$attributes[$field] = $this->$field;
}
}
return $attributes;
}
protected function sanitized_attributes() {
global $database;
$clean_attributes = array();
// sanitize the values before submitting
// Note: does not alter the actual value of each attribute
foreach($this->attributes() as $key => $value){
$clean_attributes[$key] = $database->escape_value($value);
}
return $clean_attributes;
}
public function save() {
// A new record won't have an id yet.
return isset($this->id) ? $this->update() : $this->create();
}
public function create() {
global $database;
// Don't forget your SQL syntax and good habits:
// - INSERT INTO table (key, key) VALUES ('value', 'value')
// - single-quotes around all values
// - escape all values to prevent SQL injection
$attributes = $this->sanitized_attributes();
$sql = "INSERT INTO ".self::$table_name." (";
$sql .= join(", ", array_keys($attributes));
$sql .= ") VALUES ('";
$sql .= join("', '", array_values($attributes));
$sql .= "')";
if($database->query($sql)) {
$this->id = $database->insert_id();
return true;
} else {
return false;
}
}
public function update() {
global $database;
// Don't forget your SQL syntax and good habits:
// - UPDATE table SET key='value', key='value' WHERE condition
// - single-quotes around all values
// - escape all values to prevent SQL injection
$attributes = $this->sanitized_attributes();
$attribute_pairs = array();
foreach($attributes as $key => $value) {
$attribute_pairs[] = "{$key}='{$value}'";
}
$sql = "UPDATE ".self::$table_name." SET ";
$sql .= join(", ", $attribute_pairs);
$sql .= " WHERE id=". $database->escape_value($this->id);
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}
public function delete() {
global $database;
// Don't forget your SQL syntax and good habits:
// - DELETE FROM table WHERE condition LIMIT 1
// - escape all values to prevent SQL injection
// - use LIMIT 1
$sql = "DELETE FROM ".self::$table_name;
$sql .= " WHERE id=". $database->escape_value($this->id);
$sql .= " LIMIT 1";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
// NB: After deleting, the instance of User still
// exists, even though the database entry does not.
// This can be useful, as in:
// echo $user->first_name . " was deleted";
// but, for example, we can't call $user->update()
// after calling $user->delete().
}
}
?>
database.php
<?php
require_once(LIB_PATH.DS."config.php");
class MySQLDatabase{
private $connection;
function __construct(){
$this->open_connection();
}
public function open_connection(){
$this->connection = mysqli_connect(DB_SERVER, DB_USER, DB_PASS,DB_NAME);
if(mysqli_connect_errno()) {
die("Database connections failed: " .
mysqli_connect_error() .
" (" . mysqli_connect_errno() . ")"
);
}
}
public function close_connection(){
if(isset($this->connection)){
mysqli_close($this->connection);
unset($this->connection);
}
}
public function query($sql){
$result = mysqli_query($this->connection, $sql);
$this->confirm_query($result);
return $result;
}
private function confirm_query($result_set) {
if (!$result_set) {
die("Database query failed yo.");
}
}
public function escape_value($string) {
$escaped_string = mysqli_real_escape_string($this->connection, $string);
return $escaped_string;
}
//database neutral functions
public function fetch_array($result_set){
return mysqli_fetch_array($result_set);
}
public function num_rows($result_set){
return mysqli_num_rows($result_set);
}
public function insert_id(){
return mysqli_insert_id($this->connection);
}
public function affected_rows(){
return mysqli_affected_rows($this->connection);
}
}//End class MySQLDatabase
$database = new MySQLDatabase();
?>
Simple answer on this one ;)
You have:
<a href="edit_admin.php?id=<?php $admin->id; ?>"> ...
<a href="delete_admin.php?id=<?php $admin->id; ?>" ...
When it should be:
<a href="edit_admin.php?id=<?php echo $admin->id; ?>">...
<a href="delete_admin.php?id=<?php echo $admin->id; ?>" ...
^^^^

making abstract pdo class

i'm just switching from mysql_* to PDO since i read that mysql_* will be removed in the future and now i have no idea to abstract my current class for insert,update,and delete operation to PDO, maybe some one can point me out how to translate it to PDO based?
this is my connection class for handling all connection and other related function (i already making this one PDO so there is no problem with this)
<?php
require_once(folder.ds."constants.php");
class MySQLDatabase {
private $dbh;
private $host = DB_SERVER;
private $dbname = DB_NAME;
private $stmt;
public $query_terakhir;
public $error_text;
function __construct(){
$this->open_connection();
}
public function open_connection(){
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
try{
$this->dbh = new PDO($dsn,DB_USER,DB_PASS,$options);
}
catch(PDOException $e) {
date_default_timezone_set('Asia/Jakarta');
$dt = time();
$waktu = strftime("%Y-%m-%d %H:%M:%S", $dt);
$log = array_shift(debug_backtrace());
file_put_contents('PDOErrors.txt',$waktu. ": " .$e->getMessage(). ": " .$log['file']. ": line " .$log['line']. "\n", FILE_APPEND);
}
}
public function query($sql){
$this->stmt = $this->dbh->prepare($sql);
}
public function bind($param, $value, $type = null){
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
public function execute(){
return $this->stmt->execute();
}
public function fetchall(){
return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function fetch(){
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
public function rowCount(){
return $this->stmt->rowCount();
}
public function lastInsertId(){
return $this->dbh->lastInsertId();
}
public function beginTransaction(){
return $this->dbh->beginTransaction();
}
public function endTransaction(){
return $this->dbh->commit();
}
public function cancelTransaction(){
return $this->dbh->rollBack();
}
public function debugDumpParams(){
return $this->stmt->debugDumpParams();
}
}
$database = new MySQLDatabase();
?>
and here is one of my class that help me to do saving(create or update), delete and others, with this class i only need to change $nama_tabel for table name, $db_fields for my table fields and public $xxxxx that match with my table fields and create, update and delete function can work perfectly...
but with pdo i just can't figure out how to make it work for create, update and delete with the same method as above....
<?php
require_once('database.php');
class staff{
public static $nama_tabel="staff";
protected static $db_fields = array('id','name','job');
public $id;
public $name;
public $job;
private function has_attribute($attribute){
$object_var = $this->attributes();
return array_key_exists($attribute,$object_var);
}
protected function attributes(){
$attributes = array();
foreach(self::$db_fields as $field){
if(property_exists($this, $field)){
$attributes[$field] = $this->$field;
}
}
return $attributes;
}
protected function sanitized_attributes(){
global $database;
$clean_attributes = array();
foreach($this->attributes() as $key => $value){
$clean_attributes[$key] = $database->escape_value($value);
}
return $clean_attributes;
}
public function create(){
global $database;
$attributes = $this->sanitized_attributes();
$sql = "INSERT INTO " .self::$nama_tabel." (" ;
$sql .= join(", ", array_keys($attributes));
$sql .=")VALUES('";
$sql .= join("', '", array_values($attributes));
$sql .= "')";
if($database->query($sql)){
$this->id_kategori = $database->insert_id();
return true;
}else{
return false;
}
}
public function update(){
global $database;
$attributes = $this->sanitized_attributes();
$attribute_pairs = array();
foreach($attributes as $key => $value){
$attribute_pairs[] = "{$key}='{$value}'";
}
$sql ="UPDATE " .self::$nama_tabel." SET ";
$sql .= join(", ", $attribute_pairs);
$sql .=" WHERE id=" . $database->escape_value($this->id);
$database->query($sql);
return($database->affected_rows() == 1) ? true : false;
}
public function delete(){
global $database;
$sql = "DELETE FROM " .self::$nama_tabel;
$sql .= " WHERE id=". $database->escape_value($this->id);
$sql .= " LIMIT 1";
$database->query($sql);
if(!empty($this->gambar)){
$target = website .ds. $this->upload_dir .ds. $this->gambar;
unlink($target);
}
return($database->affected_rows() == 1) ? true : false;
}
}
?>
updated: this is my approach for create function after tweaking from update function from GolezTrol, but not inserting the value instead it inserting name=:name and content=:content and so on
Updated:its already fixed! here is the right one
public function create(){
global $database;
$attributes = $this->attributes();
$attribute_pairs = array();
foreach($attributes as $key => $value){
$attribute_pairs[] = ":{$key}";
}
$sql = "INSERT INTO " .self::$nama_tabel." (" ;
$sql .= join(", ", array_keys($attributes));
$sql .=")VALUES(";
$sql .= join(", ", $attribute_pairs);
$sql .= ")";
$database->query($sql);
foreach($attributes as $key => $value){
$database->bind(":$key", $value);
}
if($database->execute()){
$this->id = $database->lastInsertId();
return true;
}else{
return false;
}
}
2nd update : i experiencing some weird thing in while loop operation where i doing while and inside the while i check if this field id is equal with my other table id then i will show that id name field... and it show, but stoping my while loop, so i only get 1 row while loop (it supposed to show 40 row)
$database->query($sql_tampil);
$database->execute();
while($row = $database->fetch()){
$output = "<tr>";
if(!empty($row['id']))
$output .="<td><a data-toggle=\"tooltip\" data-placement=\"top\"
title=\"Tekan untuk mengubah informasi kegiatan ini\"
href=\"ubah_cuprimer.php?cu={$row['id']}\"
>{$row['id']}</a></td>";
else
$output .="<td>-</td>";
if(!empty($row['name'])){
$y = "";
$x = $row['name'];
if(strlen($x)<=40)
$y = $x;
else
$y=substr($x,0,40) . '...';
$output .="<td><a data-toggle=\"tooltip\" data-placement=\"top\"
title=\"{$row['name']}\"
href=\"ubah_cuprimer.php?cu={$row['id']}\"
> {$y} </td>";
}else
$output .="<td>-</td>";
$wilayah_cuprimer->id = $row['wilayah'];
$sel_kategori = $wilayah_cuprimer->get_subject_by_id();
if(!empty($sel_kategori))
$output .="<td><a href=\"#\" class=\"modal1\"
data-toggle=\"tooltip\" data-placement=\"top\"
title=\"Tekan untuk mengubah kategori artikel ini\"
name={$row['id']}>{$sel_kategori['name']}</a></td>";
else
$output .="<td><a href=\"#\" class=\"modal1\"
data-toggle=\"tooltip\" data-placement=\"top\"
title=\"Tekan untuk mengubah kategori artikel ini\"
name={$row['id']}>Tidak masuk wilayah</a></td>";
if(!empty($row['content'])){
$content = html_entity_decode($row['content']);
$content = strip_tags($content);
$z = "";
$v = $content;
if(strlen($v)<=40)
$z = $v;
else
$z=substr($v,0,40) . '...';
$output .="<td><a data-toggle=\"tooltip\" data-placement=\"top\"
title=\"{$content}\"
href=\"ubah_cuprimer.php?cu={$row['id']}\"
>{$z}</a> </td>";
}else
$output .="<td>-</td>";
if(!empty($row['tanggal']))
$output .="<td>{$row['tanggal']}</td>";
else
$output .="<td>-</td>";
if(!empty($row['id']))
$output .="<td><button class=\"btn btn-default modal2\"
name=\"{$row['id']}\"
data-toggle=\"tooltip\" data-placement=\"top\"
title=\"Tekan untuk menghapus layanan ini\" ><span
class=\"glyphicon glyphicon-trash\"></span></button></td>";
else
$output .="<td>-</td>";
$output .="</tr>";
echo $output;
}
And here is my $wilayah_cuprimer->get_subject_by_id(); function
public function get_subject_by_id(){
global $database;
$sql = "SELECT * ";
$sql .= "FROM ".self::$nama_tabel;
$sql .= " WHERE id = :id" ;
$sql .= " LIMIT 1";
$database->query($sql);
$database->bind(":id",$this->id);
$database->execute();
$array = $database->fetch();
return $array;
}
Good that you make the transition to PDO. It's better to do it now, then to find out some day that you can't upgrade PHP, because it would break your application.
As far as I can tell, $database->query($sql); only prepares a statement. That is the first step, but after that you need to execute it as well. You already have the $database->execute() method for that, but you don't call it in your insert, update and delete functions.
Apart from that issue, it would even be better if you used bind parameters for the updates too, and leave escaping strings up to the database.
It's hard to test your class in its entirety, but I hope this gives you some ideas. I added comments to describe the steps.
public function update(){
global $database;
// Don't need 'clean' attributes if you bind them as parameters.
// Any conversion you want to support is better added in $database->bind,
// but you don't need, for instance, to escape strings.
$attributes = $this->attributes();
// Place holders for the parameters. `:ParamName` marks the spot.
$attribute_pairs = array();
foreach($attributes as $key => $value){
$attribute_pairs[] = "{$key}=:{$key}";
}
$sql ="UPDATE " .self::$nama_tabel." SET " .
join(", ", $attribute_pairs) .
" WHERE id = :UPDATE_ID";
$database->query($sql);
// Bind the ID to update.
$database->bind(':UPDATE_ID', $this->id);
// Bind other attributes.
foreach($attributes as $key => $value){
$database->bind(":$key", $value);
}
// Execute the statement.
$database->execute();
// Return affected rows. Note that ->execute also returns false on failure.
return($database->affected_rows() == 1) ? true : false;
}

class which generates all queries in php

I'm creating a class in which MySQL queries will be generated automatically , but I've some problem ...
here is my Database class...
<?php
class Database {
var $host="localhost";
var $username="";
Var $password="";
var $database="";
var $fr_query;
var $row= array() ;
public function connect()
{
$conn= mysql_connect($this->host,$this->username,$this->password);
if(! $conn )
{
die('Could not connect: ' . mysql_error());
}
}
public function db()
{
$conn_db = mysql_select_db($this->database);
if(! $conn_db )
{
echo 'Could Not Connect the Database';
}
}
public function run_query($sql)
{
$run = mysql_query($sql);
if(!$run)
{
throw new Exception("!!!!!Invalid query!!!!!!!");
}
$newId = mysql_insert_id();
if($newId)
{
return $newId;
}
return true;
}
public function fetchRow($fr)
{
if($fr)
{
$run = mysql_query($fr);
if($run)
{
return mysql_fetch_assoc($run);
}
}
return null;
}
function fetchAll($fr_query)
{
if($fr_query)
{
$run = mysql_query($fr_query);
if($run)
{
$data=array();
while($row=mysql_fetch_assoc($run))
{
$data[]=$row;
}
return $data;
}
}
return null;
}
}
$n = new Database();
$n->connect();
$n->db();
?>
and this is my test.php
<?php
include("database.php");
class Model_Abstract
{
protected $_data = array();
protected $_tableName = null;
protected $_primaryKey = null;
public function getTableName()
{
return $this->_tableName;
}
public function getPrimaryKey()
{
return $this->_primaryKey;
}
public function __set($key, $value = NULL)
{
$key = trim($key);
if(!$key)
{
throw new Exception('"$key" should not be empty.');
}
$this->_data[$key] = $value;
return $this;
}
public function __get($key)
{
$key = trim($key);
if(!$key)
{
throw new Exception('"$key" should not be empty.');
}
if(array_key_exists($key, $this->_data))
{
return $this->_data[$key];
}
return NULL;
}
public function insert()
{
print_r($this->_data);
$keyString = "`".implode("`,`", array_keys($this->_data))."`";
$valueString = "'".implode("','", array_keys($this->_data))."'";
echo $query = "INSERT INTO `{$this->getTableName()}` ({$keyString}) VALUES ({$valueString})";
$this->adpater()->run_query($query);
echo 'Inserted';
}
public function setData($data)
{
if(!is_array($data))
{
throw new Exception('"$data" should not be empty.');
}
$this->_data = $data;
return $this;
}
public function load($id, $key = null)
{
if(!is_int($id) && $id)
{
throw new Exception('"$id" should not be blank.');
}
if($id)
{
echo $query = "SELECT * FROM `{$this->getTableName()}` WHERE `{$this->getPrimaryKey()}` = '{$id}'";
$data[] = $this->adpater()->fetchRow($query);
$tabelName = $this->getTableName();
foreach($data as &$_data)
{
print_r($_data);
$object = new $tabelName();
$object->setData($_data);
$_data = $object;
}
print_r($data);
return $this;
/*
$query = "SELECT * FROM `{$this->getTableName()}` WHERE `{$this->getPrimaryKey()}` = '{$id}'";
$this->_data = $this->adpater()->fetchRow($query);
return $this; */
}
}
public function loadAll()
{
$query = "SELECT * FROM `{$this->getTableName()}`";
$data[] = $this->adpater()->fetchAll($query);
return $data;
}
public function delete($id, $key = null)
{
if(!is_int($id) && $id)
{
throw new Exception('"$id" should not be blank.');
}
if($id)
{
echo $query = "DELETE FROM `{$this->getTableName()}` WHERE `{$this->getPrimaryKey()}` = '{$id}'";
$data[] = $this->adpater()->run_query($query);
$tabelName = $this->getTableName();
$msg = 'Deleted Successfully....';
return $msg;
}
}
public function update()
{
print_r($this->_data);
$keyString = "`".implode("`,`", array_keys($this->_data))."`";
$valueString = "'".implode("','", array_keys($this->_data))."'";
echo $query = "UPDATE`{$this->getTableName()}` SET ({$keyString}) = ({$valueString}) WHERE `{$this->getPrimaryKey()}` = '{$id}'";
$this->adpater()->run_query($query);
echo 'Updated';
}
public function adpater()
{
return new Database();
}
}
class Product extends Model_Abstract
{
protected $_tableName = 'product';
protected $_primaryKey = 'product_id';
}
$product = new Product();
echo $product->name;
$product->insert();
print_r($product);
$product = new Product();
$product->name = 'Nokia Lumia';
$product->description = 'Windows';
$product->price = '15000';
$product->quantity = '12';
$product->sku = 'x2';
$product->status = '2';
$product->created_date = '0000-00-00 00:00:00';
$product->updated_date = ' ';
?>
So in here my problem is in Insert query, the values are same the column_name ...
I'm having Problem in loadAll();
the browser says "Catchable fatal error: Object of class Product could not be converted to string in"
$keyString = "`".implode("`,`", array_keys($this->_data))."`";
$valueString = "'".implode("','", array_keys($this->_data))."'";
Same lines, same value. Perhaps you meant
$keyString = "`".implode("`,`", array_keys($this->_data))."`";
$valueString = "'".implode("','", $this->_data) ."'";
Which would take the array keys for $keyString and the array values for $valueString.
Depreciation warning
mysql_* are deprecated functions. Use mysqli_* or PDO
Warning
This class does not protect you against SQL injections.

PHP/MySQL, How to update just some records in database, not all at once?

Can anyone tell me how not to update all my records in table.
This is my update statement.
public function update() {
try {
$form = new Form();
$form ->post('id')
->post('username')
->val('minlenght', 4)
->val('maxlenght', 20)
->post('role')
->post('first_name')
->post('last_name')
->post('birthdate')
->post('email')
->val('email');
$form->submit();
// sett variables after
$this->model->id = $_POST['id'];
$this->model->username = $_POST['username'];
$this->model->pass = $_POST['pass'];
$this->model->role = $_POST['role'];
$this->model->first_name = $_POST['first_name'];
$this->model->last_name = $_POST['last_name'];
$this->model->email = $_POST['email'];
$this->model->join_date = $_POST['join_date'];
$this->model->birthdate = $_POST['birthdate'];
$this->model->country = $_POST['country'];
$this->model->status = $_POST['status'];
// here i call the method from model
$this->model->update();
$_SESSION['message'] = '<span class="label label-success">Saved</span>';
redirect_to(URL."user/edit/".$this->model->id);
} catch (Exception $e) {
$_SESSION['message'] = '<span class="label label-important">' . $e->getMessage() . '</span>';
redirect_to(URL . 'user?page=1');
}
}
Here is the code for the model.
public function update() {
$attributes = $this->sanitized_attributes();
$attribute_pairs = array();
foreach ($attributes as $key => $value) {
$attribute_pairs[] = "{$key}='{$value}'";
}
$sql = "UPDATE " . self::$table_name . " SET ";
$sql .= join(", ", $attribute_pairs);
$sql .= " WHERE id=" . $this->database->escape_value($this->id);
$this->database->query($sql);
return ($this->database->affected_rows() == 1) ? true : false;
}
The attributes are
private static $db_fields = array('id', 'role', 'username', 'pass', 'role', 'first_name', 'last_name', 'email', 'join_date', 'birthdate', 'country', 'avatar', 'status');
private static $table_name = "user";
public $id;
public $username;
public $pass;
public $role;
public $first_name;
public $last_name;
public $email;
public $join_date;
public $birthdate;
public $country;
public $avatar;
public $status;
When I try to update, even if I put only username, it updates all records in database.
What need to be change in this code so that I can update only records I specify?
I tried couple of hours to try to figure it out, but I came at the conclusion that I need to remake my user class, not to be so automatic.
Here is the updated version of the update() method that you have listed above
public function update() {
$attributes = $this->sanitized_attributes();
$attribute_pairs = array();
foreach ($attributes as $key => $value) {
if(empty($value))
{
continue;
}
else
{
$attribute_pairs[] = "{$key}='{$value}'";
}
}
$sql = "UPDATE " . self::$table_name . " SET ";
$sql .= join(", ", $attribute_pairs);
$sql .= " WHERE id=" . $this->database->escape_value($this->id);
$this->database->query($sql);
return ($this->database->affected_rows() == 1) ? true : false;
}

Categories