Having trouble with PHP classes and MySQL insertion/updating - php

I'm having some trouble updating a MySQL database via a PHP class (this is my first real foray into PHP classes, so I might be missing some very basic elements). I've included the code that is relevant to the problems I am having (that is, not properly updating the MySQL table).
To quickly explain my code, I pull a user's information from the database when an object is constructed. Then, I call the function modify_column() to increase or decrease a numeric value from the data I've pulled. Finally, I run save() to update the MySQL table.
I am having two problems: (1) $this->info is not being updated properly by the modify function (for example, if I modify_column('age', '1'), a var_dump shows age int(3) rather than age string(2) = 10 (assuming the original age was 9). And (2), the update query is not working. I'm assuming it's because I have an improperly-sized variable stemming from the first issue.
A snippet of the code (my database functions are based on a PDO wrapper and they have always worked just fine):
class user {
public $id;
public function __construct($id) {
global $db;
/* pull the user's information from the database */
$bind = array(':id' => $id);
$result = $db->select('user', 'id = :id', $bind, '*', SQL_SINGLE_ROW);
$this->id = $result['id'];
$this->info = $result;
}
/*
* Update the user's MySQL table, thereby saving the data.
*/
public function save() {
global $db;
$bind = array($this->id);
$db->update('users', $this->info, 'id = ?', $bind);
}
public function modify_column($column, $amount) {
$this->info[$column] += $amount;
}
}
Also, please let me know if there is a neater way to do what I am trying to accomplish (that is, quickly modify numeric values in a table using class functions.
Thanks!

You seem to not have any provision for typing of your variables. When you add your data to $this->info all the value are going to be set as strings. You don't want to do incremental math (i.e. +=, -= etc.) on strings. You need to cast to these values as integer. What I suggest would be to add a class property having an array of your class properties and their types. You will then be able to cast all you values according to their types when setting the $info array.
So something like this
protected $fields = array(
'age' => 'integer',
'name' => 'string',
// etc.
}
Then you can add a function like this
protected function type_cast(&$value, $key) {
// field type to use
$type = $this->fields[$key];
if ($type === 'integer') {
$value = (integer)$value;
} else if ($type === 'string') {
$value = (string)$value;
} // etc.
}
And in your constructor, just walk $result through the type_cast function:
array_walk(&$result, array($this, 'type_cast'));
$this->info = $result;
You probably also need to make sure your id value cast as an integer if you are using an integer in the DB.
I am not sure how you DB abstraction works, so hard to tell what is happening. I would suggest echoing out the query itself and trying it against the database, or taking a look at the MySQL errors that are being returned to get a feel fro what is going wrong there.

Related

How can i access a variable outside that function in codeigniter

I am sorry for asking this basic level question. I have fetched some data from DataBase and stored it to a variable inside a function, and wanted to get the value of that variable outside the function?
public function getemailData()
{
$email_id_investors = $this->db
->select('value')
->get_where('common_email_settings', ['name' => investors_email])
->row()->value;
}
I wish to get the value of the $email_id_investors outside the function. Again I am apologizing for this basic question
Database table name - common_email_settings
fields are Id, title, name, value
1 Greeting Mail, greeting_email ,Greetings#investorsloanservicing.com
2 Loan Service Mail, loan_service_email ,LoanServicing#investorsloanservicing.com
3 Processing Mail, processing_email ,processing#investorsloanservicing.com
To strictly answer the question, you could store the value in a scoped global $this variable, though I don't know why you wouldn't just query the function and have it return a value.
public function getemailData($investors_email)
{
$this->email_id_investors = $this->db
->select('value')
->get_where('common_email_settings', ['name' => $investors_email])
->row()->value;
}
// then in another function called later in the chain, you can grab it
public function doSomethingElse() {
$investors = $this->email_id_investors;
}
It's probably better just to create a getter function for that variable.
This doesn't look useful given your scenario. This might be useful if the variable you're storing is something processor intensive (and you're using $this like a cache), you need to access it in multiple functions called during a given state, and you don't want to rewrite your function chain to accept this parameter (so as to pass it along). However, that is a clear sign you need to refactor your logic and make it more flexible (pass object or arrays rather than single variables for example).
You are not returning your variable.
Try returning your variable like this,
public function getemailData()
{
$email_id_investors = $this->db
->select('value')
->get_where('common_email_settings', ['name' => investors_email])
->row()->value;
return $email_id_investors;
}
function getemailData($name)
{
$email_id_investors = $this->db
->get_where('common_email_settings', ['name' => $name])
->result()[0];
return $email_id_investors->value;
}
This one worked for me. I have given this function in the common model page and called this on other pages.Thank you for your help
$email = $this->common->getemailData('account_email'); -> getting data in this variable
echo $email;
// exit();

php/mysql best practice for selecting items

I'm requesting the community's wisdom because I want to avoid bad coding practices and/or mistakes.
I'm having a php class wich is an objects manager. It does all the work with the database: inserting new data, updating it, getting it and deleting it (I've read it's called CRUD...). So it has a function that gets an element by id.
What I want to write is a function that gets a list of objects from the table.
I will then use a mysql query that goes something like
SELECT * FROM mytable WHERE column1='foo'
And then some order by and limit/offset.
However, in my application there are different cases in which I will need different lists from this table. The WHERE clause will then be different.
Should I write different functions, one per type of list?
Or should I write one generic function to which I will send arguments that then dynamically creates the query? If so, do you have any advice on how to do this properly?
EDIT:
Thanks for all your answers! I should tell that I'm not using any framework (maybe wasn't the best idea...), so I didn't know about query builders. I'll investigate that (either finding a standalone uery builder or migrating to a framework or writing my own, I don't know yet). That will be useful any time I need to execute a mysql query :-)
Although I'm still confused:
Let's say I need several lists of clients (objects), for example all clients, clients over 18, clients currently online...
What approach would be best to retrieve those lists? I can either have 3 functions in my clients manager
allClients() {//execute a specific query and return list of objects}
allClientsOver18() {//execute specific query and return list of objects}
allClientsOnline() {//execute specific query and return list of objects}
or I can have one function tht builds the query based on parameters
listClients($some, $parameters)
{
//Build the query based on the parameters (definitely need a query builder!)
//Execute the query
//return list of objects
}
Which approach would be best (I guess it depends on circumstances) and mostly, why?
Thanks in advance!
Rouli
Thanks for all the info on query builders, I didn't even know it existed! :-) However I'm still confused as to wether I should write one specific function for each case (that function can still use the query builder to write its specific query), or write one generic function that builds dynamically the query based onf parameters. Which would be better in which case? I've added an example in my question, hope it makes it clearer!
This depends on how often you use each of these isolated queries, how complex the conditions are and how often you my need to combine the conditions with other queries. For eaxample if each the "online" and "over18" are just simple conditions then you could just use the normal findBy logic from my example:
$table = new MyTable($db);
$onlineOnly = $table->findBy(array('is_online' => true), null, null);
$over18Only = $table->findBy(array('is_over_18' => true), null, null);
$onlineOver18 = $table->findBy(array('is_over_18' => true, 'is_online' => true), null, null);
If the query is more complex - for example to get over 18 clients you have to do:
select client.*, (YEAR(CURDATE()) - YEAR(client.birthdate)) as age
FROM client
WHERE age >= 18
Then its probably better to make this into a separate method or create methods to work on Query objects directly to add complex conditions for example - especially if you will need this condition in a few different queries in the app:
$table = new MyTable($db);
// creates a basic query defaulted to SELECT * FROM table_name
$query = $table->createQuery();
// adds the complex condition for over 18 resulting in
// SELECT table_name.*, (YEAR(CURDATE()) - YEAR(table_name.birthdate)) as age WHERE age >= 18
$over18 = $table->applyOver18Query($query)->execute();
This way you can apply your over 18 condition easily to any query with out manually manipulating the builder ensure that your over 18 condition is consistent. But for simplicity you could also have a convenience method like the following:
public function findOver18By(array $criteria, $limit = null, $offest = null) {
$query = $this->findBy($criteria, $limit, $offset);
$this->applyOver18Query($query);
return $query->execute();
}
Normally you would use some kind of query builder at the lower level like:
$query = $db->createQuery()
->select($fields)
->from($tableName)
->where($fieldName, $value);
$results = $query->execute();
Then you might have a class that makes use of this like:
class MyTable
{
protected $tableName = 'my_table';
protected $db;
public function __construct($db) {
$this->db = $db;
}
public function findBy(array $criteria, $limit = null, $offset = null) {
$query = $this->db->createQuery();
$query->select('*')->from($this->tableName);
foreach ($criteria as $col => $value) {
// andWhere would determine internally whether or not
// this is the initial WHERE clause or an AND clause
// something similar would happen with an orWhere method
$query->andWhere($col, $value);
}
if (null !== $limit) {
$query->limit($limit);
}
if (null !== $offset) {
$query->offset($offset);
}
return $query->execute();
}
}
Usage would look like:
$table = new MyTable($db);
$result = $table->findBy(array('column1' => 'foo'), null, null);
This is a lot to implement on your own. Most people use an ORM or a DBAL to provide these features and those are often included with a framework like Eloquent with Laravel, or Doctrine with Symfony.
I guess at start you should need some main data like
$main = [
'from' = '`from_table`',
]
Then you should add selects if had
$selects = ['fields1','field2'];
$where = ['some condition', 'other condition'];
Then you could
$query = "SELECT ".implode(',', $selects ." FROM ".$main['from']."
WHERE ".implode('AND ', $where .";";
That's some approaches for simple one table query.
If you need Joins, then $selects better would be make with aliasos, so no field will be lost if they are not different, like
select temp.id as temp_id , temp2.id temp2_id from temp
left join temp2 on temp2.temp_id = temp.id
Feel free to ask some questions, maybe i haven't told , but you should also check bound parameters with some functions to avoid sql injections
I suggest using a CLASS for your database which holds all your database accessing functions as it makes your code cleaner making it more easier to look through for errors or modifications.
class Database
{
public function connect() { }
public function disconnect() { }
public function select() { }
public function insert() { }
public function delete() { }
public function update() { }
}
sample connect function for connecting to a selected database.
private db_host = ‘’;
private db_user = ‘’;
private db_pass = ‘’;
private db_name = ‘’;
public function connect()
{
if(!$this->con)
{
$myconn = mysqli_connect($this->db_host,$this->db_user,$this->db_pass);
if($myconn)
{
$seldb = mysqli_select_db($this->db_name,$myconn);
if($seldb)
{
$this->con = true;
return true;
} else
{
return false;
}
} else
{
return false;
}
} else
{
return true;
}
}
with this approach will make creating CRUD functions easier. Heres a sample insert function.
public function insert($table,$values,$rows = null)
{
if($this->tableExists($table))
{
$insert = 'INSERT INTO '.$table;
if($rows != null)
{
$insert .= ' ('.$rows.')';
}
for($i = 0; $i < count($values); $i++)
{
if(is_string($values[$i]))
$values[$i] = '"'.$values[$i].'"';
}
$values = implode(',',$values);
$insert .= ' VALUES ('.$values.')';
$ins = #mysql_query($insert);
if($ins)
{
return true;
}
else
{
return false;
}
}
}
heres a quick view on using this.
;<?php;
$db->insert('myDataBase',array(3,"Name 4","this#wasinsert.ed")); //this takes 3 paramteres
$result = $db->getResult(); //Assuming you already have getResult() function.
print_r($result);
?>
EDIT
there are more purist approach to handling database operations. I highly suggest it because handling information is very delicate and should be fronted with many safety measures But it requires deeper php knowledge. Try PDO for php and this article by matt bango on prepared statements and its significance.

How to use sql queries in classes

I have a question on what is the best way of implementing SQL queries in PHP classes. I want to keep the queries as low as possible.
This was my first attempt:
class NewsArticle
{
//attributes
private $newsArticleID;
//methodes
//constructoren
public function __construct($newsArticleID)
{
$this->newsArticleID = $newsArticleID;
}
//getters
public function getGeneralData()
{
$query = mysql_query("SELECT author, title, content, datetime, tags FROM news WHERE news_id = '$this->newsArticleID'");
$result = mysql_fetch_array($query);
$data = array(
'author' => $result['author'],
'title' => $result['title'],
'content' => $result['content'],
'datetime' => $result['datetime'],
'tags' => $result['tags']
);
return $data;
}
//setters
}
Now I'm wondering if it would be better to create a setter for generalData and for each item I retrieve from the database create a variable and assign the proper value. Then I could create a getter for each variable. So like this.
class NewsArticle
{
//attributen
private $newsArticleID;
private $author;
private $title;
// more variables
//methodes
//constructoren
public function __construct($newsArticleID)
{
$this->newsArticleID = $newsArticleID;
}
//getters
public function getAuthor()
{
return $this->author;
}
public function getTitle()
{
return $this->title;
}
//setters
public function setGeneralData()
{
$query = mysql_query("SELECT author, title, content, datetime, tags FROM news WHERE news_id = '$this->newsArticleID'");
$result = mysql_fetch_array($query);
$this->author = $result['author'];
$this->author = $result['author'];
//other variables
}
}
The point of using setters and getters is that by forcing the developer to use these you can implement more complex access mechanisms, for example setting a flag when a value is set so that your class knows to write it back into the database (although this is a rather bad example as the objective can be acheived without having to force access via a method).
BTW
news_id = '$this->newsArticleID'
No.
Numbers shouldn't be quoted (breaks the optimizer) and strings should be escaped at the point where they are used in a query.
My advice for you would be to start using PHP-PDO and stored procedures of MySQL. Although you will see a small time difference in using direct queries in php code and in using stored procedures (a difference of milliseconds), you will have less code to write in php. To my opinion that way you would have a more BALANCED application. Also use getData and setData functions that should return anything you want in a form of array or json (i think you will find this very interesting in case you want to use a browser's local storage).

Advice extending PDO with basic CRUD functions

Just recently I started rewriting a previously procedurally written website by myself, I chose PDO as the wrapper since I'm also getting used to the OOP way of doing things. I would like some advice about the structure of the classes.
Mostly everything is database-driven, like adding categories and subcategories, brands of products, products, users, etc. I suppose each of them could be one class and since I need CRUD operations on all of them, I need a generic way of inserting, updating, deleting records in the MySql database. The problem is not the code, I'd like to (and already have) coded some of the CRUD operations by myself according to my needs, the real problem is the structure and how would I go to correctly distribute and extend those classes.
Right now I've coded 3 different approaches:
A class called 'Operations' which will be extended by all the other classes that need CRUD functions, this class contains pretty generic properties such as $id, $atributes, $fields and $table, and of course the generic methods to insert, update, delete. That way I can create, let's say my Product object with some parameters (name, category, price) and immediately Product->insert() it into the database, without passing any parameters to the insert function. The CRUD functions in this class don't accept parameters, they depend on the created object's properties.
Same as above but the CRUD functions accept parameters, making them (I suppose) more generic, in case I just need to insert something without creating an object with useless properties previously.
The 'Operations' class extends PDO, the way of working is similar to 2, but now they can be directly accessed when I create the database connection, not depending of other objects.
I'm leaning towards the first option because I think, for the most part, that it will satisfy everything I'll do with this website, again the website is already coded but procedurally, which has been a mess to maintain, so basically I need to re-do things but OO.
CMSs or already coded wrappers aside (the purpose of doing this is to learn PDO and getting used to OOP), which would be the best way to do that? not limited to the options I mentioned.
Here's the 'Operations' class I've managed to code so far, where I've been doing tests sandbox-like, don't mind the spanish variable names. Advices on the code are welcome too.
class Operaciones {
private $database;
protected $id;
protected $atributos;
protected $tabla;
protected $campos;
public function __construct($link) {
$this->database = $link;
}
public function insertar() {
if (!$this->verificarCamposNulos($this->atributos, $this->campos))
echo 'Campos nulos<br />';
else {
$this->prepararCampos();
$placeholders = $this->generarPlaceholders();
$stmt = $this->database->prepare("INSERT INTO {$this->tabla} ({$this->campos}) VALUES ({$placeholders})");
$valores = array_values($this->atributos);
$stmt->execute($valores);
$stmt = NULL;
echo 'Se ha insertado exitosamente';
}
}
public function modificar() {
if (!$this->verificarCamposNulos() || empty($this->id))
echo 'Campos nulos<br />';
else {
$this->prepararCampos('=?');
$stmt = $this->database->prepare("UPDATE {$this->tabla} SET {$this->campos} WHERE id = {$this->id}");
$valores = array_values($this->atributos);
$stmt->execute($valores);
$stmt = NULL;
echo 'Se ha modificado exitosamente';
}
}
private function generarPlaceholders() {
for($i=0;$i<count($this->atributos);$i++)
$qmarks[$i] = '?';
return implode(',', $qmarks);
}
// Check if the values to be inserted are NULL, depending on the field format given
private function verificarCamposNulos() {
$n_campos = explode(',', $this->campos);
$valores = array_values($this->atributos);
foreach($n_campos as $i => $result) {
if (strstr($result, '#'))
if (empty($valores[$i]))
return false;
}
return true;
}
// Removes the '#' from each field, used to check which fields are NOT NULL in mysql
private function prepararCampos($sufijo = NULL) {
$n_campos = explode(',', $this->campos);
foreach($n_campos as $i => $result)
$n_campos[$i] = str_replace('#', '', $result) . $sufijo;
$this->campos = implode(',', $n_campos);
}
}

Setting object data in an Active Record pattern, before sql commit

I am using the Active Record design pattern in my web app, and after looking at the code in my class that handles CRUD (create, read, update and delete) on a table in the DB, i'm wondering if there's a better way to set the data.
Let's say my table has around 15 columns, and my class has 15 member variables to represent the columns. I have a form which allows a user to input data for each of those variables, and on submit, my script reads everything from _POST and _GET and compiles it into an array called $params.
Currently my class setter methods looks like this:
public function setData($data1, $data2, $data3,...,$dataN-1){
$this->data1 = $data1;
$this->data2 = $data2;
$this->data3 = $data3;
...
$this->dataN-1 = $dataN-1;
}
I was wondering, what the problems would be if I changed the setData argument to be an array, specifically the array containing the _POST and _GET values, so something like this
public function setData($data){
$this->data1 = $data['data1'];
$this->data2 = $data['data2'];
$this->data3 = $data['data3'];
...
$this->dataN-1 = $data['dataN-1'];
}
Assume that all the form element names are correct. Obviously, the time will be saved when I call the method, not having to list 15 arguments. I am going to be using prepared statements for all INSERTs and UPDATEs. Are there any other pitfalls that I should be aware of doing this?
Thanks a lot for your help.
Why don't you use an array too for $this->data[] in your class?
You could this way use a foreach and could maintain/automatize it more easily, fetching data or setting it in your DB.
EDIT : this way you fill your array
in your class :
private $data = array(
'db_column_name_1' => null,
'db_column_name_2' => null,
'db_column_name_3' => null,
...
'db_column_name_n' => null
);
public function setData($data){
foreach ( $this->data as $key => $value )
$this->data[$key] = $data[$key] ;
}
Symmetrically you could as easily make the right INSERT/UPDATE query

Categories