Is there anyway to minimize sql query structure? [duplicate] - php

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
PHP file cannot enter some part of code
I am building a news website and I have a function file, for all functions but, nearly all the functions made the same way as the below example:
function one(){
$query = "SELECT * FROM table WHERE id='$id'....";
$result = mysql_query($query);
while($row=mysql_num_rows($result))
{echo "$row[data]";} }
So, basically there are many functions that serve different purpose, but have the same exact template as the above, So, to save time, codding I was thinking if is would be possible, to simplify the 5 lines? to one with function like:
function(something here, and here){then the result here?}
Since the only thing that may change from the first code are: Select, table names, id,
and the $row[data], and everything will remain the same what if I assign those to variables and the rest structure will stay as it is in a function:
check this idea.
function simplify() {
$query = "$crud * FROM $table WHERE id= '$id' ";
$result = mysql_query($query);
while($row=mysql_fetch_array($result)) {echo "$row[data]";}
}
So anytime, I need to create the first code, I could just do
echo simlify(and here would be table name, id, select, create, update...) {
and here the result}
So sorry, for asking this complex question, or asking it with complexity but If anyone has any idea, about what I am talking about, I need your help.

How about this, for a simple database call:
$db = new DBAdapter(array('host' => 'localhost'));
$results = $db->Select('mytable')->Where('id > 2')->Execute();
You can achieve this by building your own database class. Put the class in a separate file and reuse it many times.
class DBAdapter extends PDO
{
public function __construct( array $params)
{
// construct the connection
}
public function Select ($table)
{
// do stuff for a table select
return $this;
}
public function Count ($table)
{
// do stuff for a table count
return $this;
}
public function Where ($condition)
{
// do stuff for a where
return $this;
}
public function Execute ()
{
// execute stuff
return $result;
}
}

Related

How to implement a good MVC pattern with PHP/MySQL without loosing SQL request time/server memory ? (good practices)

I want to implement a real pattern MVC for my php controllers. Especially, i want to split Model and API by creating java "bean" equivalent in PHP (objects made for business organization) and an API using these business objects.
For exemple, my basic object is the Member.
The question is : where i request my database ?
Do I request all the members proprities right at __construct, and i simply access them with the getters OR i do nothing in the __construct and I call the database in every getter function ?
People tell me that the 1st solution is better, though, if i want only a specific information in my controller, i will create a Member with all the informations computed right at construct (bad memory management). In the 2nd case, if i want several members proprities, i will do several SQL request which will increase my server execution time.
1st solution :
public function __construct($ID_membre,$sql)
{
$this->ID_membre = $ID_membre;
$res = mysql_get("select * from membres where ID_membre = $ID_membre",$sql);
if(!$res)
throw new Exceptions\MyDefaultException("no member for this Id");
$this->firstName = $res['first_name'];
$this->lastName = $res['last_name'];
$this->mail = $res['mail'];
$this->gender = $res['gender'];
// ....
$this->sql = $sql;
}
public function getLastName()
{
return $this->lastName;
}
public function getMail()
{
return $this->mail;
}
public function getGender()
{
return $this->gender;
}
// ....
2nd solution :
public function __construct($ID_membre,$sql)
{
$this->ID_membre = $ID_membre;
$res = mysql_get("select count(*) from membres where ID = $ID_membre",$sql);
if($res == 0)
throw new Exceptions\MyDefaultException("no member with this id");
$this->sql = $sql;
}
public function getLastName()
{
mysql_get("select name from members where ID = {$this->id}",$this->sql);
return $this->lastName;
}
public function getMail()
{
mysql_get("select mail from members where ID = {$this->id}",$this->sql);
return $this->mail;
}
public function getGender()
{
mysql_get("select gender from members where ID = {$this->id}",$this->sql);
return $this->gender;
}
In this context, good old SQL custom request within controllers are perfect to not waste time or memory, because they are customs. So, why doing such request are so poorly viewed nowsaday ? And if big organizations such as Fb or Google do MVC with database, how they manage to not waste any time/memory while splitting Model and controllers ?
This is a classic problem, which can even get worse if you want one property of many members.
The standard answer is that solution 1 is better. Requesting one row from a database doesn't take much longer than requesting one value from a database, so it makes sense to ask a whole row at once. That is unless your database rows get very big. That should however not occur in good database design. If your rows get so big that they hamper efficiency then it is probably time to split the table.
Now back to the problem I mentioned at the start of this answer. You haven't solved this. My suggestion would be to make two classes: One with solution 1, dealing with one row, and one with solution 2 dealing with multiple rows.
So both solutions have their place, it just that solution 2 is almost always inefficient for dealing with one row, and I haven't even talked about the amount of extra coding it requires.

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).

Sort alphabetically when multiple queries?

I am having difficulty sorting my data results alphabetically when matching them with the User that has placed the item in their "Locker".
I have two queries; the first one searches the database for all of the items that the user placed in their 'locker', and the second query pulls the details of the item and sorts them into a list by which brand the items are.
I feel like there is a better way to do this rather than forcing the page to run the query once for each item, but am not sure the proper way to write out the mySQL in the most efficient way that works.
I think the solution would be to pull all IDs as an array, then somehow search and sort all of their associated brands in the second query.
I currently have:
//$lockerid is pulled earlier in the code based on which locker number is associated with this user
// Pull all of the items and their ids that are in this users locker
$userlockerquery= mysql_query("SELECT DISTINCT item_id FROM lockers WHERE user_id = '$profile_userid' AND locker_id ='$lockerid' ");
while($lockeritems=mysql_fetch_array($userlockerquery)){
$indi_item=$lockeritems[item_id];
$lockeritemdetails = mysql_query("SELECT DISTINCT brand FROM inventory WHERE id = '$indi_item' ");
$brands=mysql_fetch_array($lockeritemdetails );
$brandname=$brands[brand];
echo '<div>'.$brandname.'</div>';
}
Although the results do show up with all of the brands, My problem seems to be that since the query is ran once for each items id, it cannot have the list results talk to each other, and thus cannot have them ordered by ASC alphabetically, since the query is ran once per each item.
Also because of this, the DISTINCT flag does not have any effect, since it is not matching against any other results.
As an example, my results would return in divs in order of ID instead of brand, and repeating:
Nike
Puma
Puma
Converse
Rather than
Converse
Nike
Puma
Adding the ORDER BY flag to the second query did not help, so I figured I would try to ask here for some ideas. Please let me know if any other details are needed!
Maybe try something like this class. See if it will work for your needs. It's hard to check it without trying the sql queries, but provided I've written it properly, it should work.
class MyLocker
{
// Protected means that you can't use this variable outside of the functions/class
// so you can not use $myLocker->_array; It will throw an error
protected $_array;
// Construct is basically used as an auto-function. It will execute automatically
// when you create a new instance of the class so as soon as you do this:
// $myLocker = new MyLocker($_locker); you initiate the __construct
// When you label as public, you allow it to be used outside of itself
public function __construct($_array)
{
// When you set this variable, it is now open to use in all
// other functions in this class.
$this->_array = $_array;
}
// This is the method that will do everything
public function LockerContents()
{
// Loop through query. Since the $_array was set in the __construct
// it is available in this function as $this->_array
while($lockeritems = mysql_fetch_array($this->_array)){
// $brand is something we want to use in other functions but not
// outside the class so it is set here for use in the Fetch() function
$this->brand = $lockeritems['item_id'];
// We ant to use our Fetch() function to return our brand
$_brand = $this->Fetch();
// If brand available, set it to an array
if(!empty($_brand))
$array[] = $_brand;
}
if(isset($array)) {
// Sort the array
asort($array);
// Finally, we use the Display() function for the final output
$this->Display($array);
}
else { ?>
<div>Locker is empty.</div><?php
}
}
// Establish this as an in-class variable
protected $brand;
// Establish this as a public function incase we want to use it by itself
// To do so you would write $myLocker->Fetch(); outside of the class.
// Since you need $brand for this function to work, you would need to turn
// $brand from "protected" to "public" and write $myLocker->brand = 'whatever';
// before you run the $myLocker->Fetch();
public function Fetch()
{
$query = mysql_query("SELECT DISTINCT brand FROM inventory WHERE id = '".$this->brand."'");
$brands = mysql_fetch_array($query);
// Return brand
return (isset($brands['brand']))? $brands['brand']:"";
}
protected function Display($array)
{
if(is_array($array)) {
foreach($array as $object) { ?>
<div><?php echo $object; ?></div><?php
}
}
}
}
// You should be using mysqli_ or PDO for your db connections/functions.
$_locker = mysql_query("SELECT DISTINCT item_id FROM lockers WHERE user_id = '$profile_userid' AND locker_id ='$lockerid' ");
// If there are more than 0 rows, create locker.
if(mysql_num_rows($_locker) > 0) {
// Create new instance of the locker app
$myLocker = new MyLocker($_locker);
// Display the results
$myLocker->LockerContents();
}

PHP OOP need advice

i am building this sms notification system, which will send 10 times free sms based on certain occasion to the web's member, and after a certain member reach 10 times, the system would send a last notification system saying that "this is the last free sms notification", i am currently learning PHP OOP and trying to use an OOP aproach on this
without further a do here's my code:
<?php
class SmsBonus {
//bonus_sms fields = id, member_id, counter, end_status
public static function find_member($id=0){
//query to find a certain member
}
public function add_counter($id=0){
//query to increment the value of counter field
}
public function status_check($id=0){
//query to check whether the given member's counter has reach the number 10
}
public static function send_sms($id, $message){
$found = $this->find_member($id);
$status_check = $this->status_check($id);
if(!empty($found) && !empty($status_check) && $found->counter == 10){
//send the sms notification saying that this member has reach the end of the bonus period
//update this member's end_status table to 1
}else{
//send the regular notification
}
}
}
?>
would this lines:
$found = $this->find_member($id);
$status_check = $this->status_check($id);
work as expected (i cant test this one out because i am currently building this on local)? and is this a best practice regarding OOP aproach ? or am i doing this wrong ?
i need advice, thank you very much.
EDIT:
of course on my original code i declare the class, i am sorry that by not writing it here confuses everybody :D, i am actually looking for a kind of answer (advice) that pointed the way i should implement a best approach (best practice) on my codes (in this case methods), things that i worry about is that i don't meet the requirements such as K.I.S.S or D.R.Y.
UPDATE
i manage to do some modifications based on your suggestions, how is this looks like ?
<?php
class SmsBonus{
//bonus_sms fields = id, member_id, counter, end_status
protected $max_sms = 10;
public $id;
public $member_id;
public $counter;
public $end_status;
public function find_member($id=0){
//query to find a certain member
}
public function add_counter($id=0){
//query to increment the value of counter field
}
public function status_check($id=0){
//query to check whether the given member's counter has reach the number 10
}
public function update_status($id=0){
//query to update when a certain member reach its sms bonus limit
}
protected function can_still_send_sms($member_id){
$found = $this->find_member($member_id);
$status_check = $this->status_check($id);
return !empty($found) && $found->counter < $this->max_sms && !empty($status_check);
}
public function send_sms($id, $message){
$phone = Phone::find_member($id); //
if ($this->can_still_send_sms($id)) {
//send the sms notification saying that this member has reach the end of the bonus period
$this->update_status($id);
}else{
//send the regular notification
$this->add_counter($id);
}
}
}
$sms_bonus = new SmsBonus();
?>
Well, I think OOP is mostly about creating meaningful actions that are easy to reuse and, especially, make it easy to find out what's going on when you revisit your code some months later (or when someone else reads your code, which is more or less the same). Also, when you found your member, you can then perform logic on that, instead of on the id. So, in this case it might be better to create your methods like this, for example:
protected $max_sms_messages = 10;
protected function can_still_send_sms($member){
return !empty($member) && $member->counter < $this->max_sms_messages;
}
public function send_sms($id, $message){
$found = $this->find_member($id);
if ($this->can_still_send_sms($found)) { // or even if($found->can_still_send_sms()), if you want to implement it that way
//send the sms notification saying that this member has reach the end of the bonus period
//update this member's end_status table to 1
}else{
//send the regular notification
}
}
Also, for the record, you can't call non-static methods from static methods.
You need to wrap your code in a class declaration
class SMSNotification {
...
}
And you may also want to create a constructor
function __construct() {
One reason for this is so that you can set private variables to the class when it is instantiated.
you instantiate the class like this:
$sms = SMSNotification()
Will you be connecting this to a database for the counter increment. As what you would normally do with an oop approach is have a seperate class that handles that connection, so that if you wanted to build on this whole project then everything would be connecting to a database the same way.
The two lines of code you pasted are a bit different:
$found = $this->find_member($id);
you have made find_member a static function (which is probably what i would have done) so that you can call the function without create a new class object. That being said it is not of value $this as it is not part of the current instantiated class. So you will need to call it like (using my example of SMSNotification):
$found = SMSNotification::find_member($id);
This tells php to look for a static function called find_member
The other line of code should work fine:
$status_check = $this->status_check($id);
According to OOP you can't call $this->find_member($id) on a static member function. Besides you didn't declare any class at all, so $this is meaningless (as far as I remember PHP). You probalby wanted to declare some SmsClient class which would be initialized from db query filling in member variables. Your static find_member($id=0) function would query db by id and return initialized object of SmsClient with its id = $id
class SmsClient
{
private $id;
private $nSmsSent;
public __construct($id)
{
$res = DAL->GetClient($id);
//initialize vars here
}
public send_sms(...)
{
$this->nSmsSent++;
}
}
Listen to dewi.
Anyway, a nice way to test if you're using the right syntax is commenting out the content of the find_member() and status_check() functions and make them return some arbitrary values: if the values are actually returned, you're doing it right.

Categories