refactoring sql in php - php

What is a good place to put sql commands so they do not appear in the main code, how can this be done? How can sql commands such as the following be refactorised:
function select_Query($sql, $link)
{
$query = mysqli_query($link, $sql);
if (!$query)
{
echo "Failure"; # TODO: LOG THIS
}
$data = array();
while ($row = mysqli_fetch_array($query) )
{
$data[] = $row;
}
return $data;
}
$query = select_Query("SELECT thread.title, thread.id as t_id,
thread.content
FROM thread
LIMIT $start, 30", $link);
How would you factorise the $query var part to generalise it for other sql statements - as that is fairly simple sql, however when several joins are used sql commands take up several lines in my code, I don't want to mix them with my php code.

Read about ORM and MVC. You factor it out by building a layered application, and encapsulating your data models in classes.

Check out
Zend Framework
I have became to worship it.

Related

How to build a custom PHP Mysql or PDO function

Recently I seem to be writing nearly the same sql statements and I have to use PHP for looping and error reporting, so I'm trying to write something general that will shorten my code extensively. I'm still learning programming.
I don't know if I need to use classes or what, but here's an example of what I'm trying to do.
/////////q = query, f = fetch type(loop or single object), r = row;
function dbQuery($q, $f, $r){
global $con;
$query = mysqli_query($con, $q) or die(mysqli_error($con));
if ($f = 'loop'){
while($row = mysqli_fetch_array($query)){
echo $r;
}
} else if ($f='single'){
$row = mysqli_fetch_array($query);
echo $r;
}
///////////or prepared statements//////////
}
dbQuery("SELECT * FROM music WHERE perms = 'a' limit 50", $f='loop', $r="<div>".$row['title']."</div>"
);
I want something like the following, I know its not write but I want to be able to have the function above return row results to the function's arg.
dbQuery($f='loop'){ /////////// I really don't know the corrent way for this////
$q= "SELECT * FROM music WHERE perms = 'a' limit 50";
$r="<div>".$row['title']."</div>";
////////and breaking out of php////
?>
<section><?php echo $row['duration']; ?></section>
<?php
}
Please do recommend materials I can check out.
I will recommend you to use some framework like Laravel or some query builder class. There are tons of them. If for some reason, you will like to create your own, please do not use mysql function, since is deprecated. Personally, I will prefer PDO over mysqli (this is just a preference) make sure to prepare statements. Check this link out, it will help you with your project
http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers
Good luck with your project.

Can core php mysql function be used in Yii Framework?

Can we use core PHP functions in Yii framework?
Here, I have a core php function
function abc_function(){
$query=mysql_query("select emp_id, days from tmp_emp_work where comp_id='$comp_id' AND active=1");
$count=mysql_num_rows($query);
if ($count) {
$del_existing=mysql_query("DELETE from temp_t_balances where com_id='$comp_id'");
$row=mysql_fetch_array($query);
while ($row) {
$emp_id=$row['emp_id'];
$array=dis_t_bal ($emp_id,$com_id);
$start_bal=$array[0];
$taken=$array[1];
$comp_days=$array[2];
$remain_bal=$array[3];
$booked=$array[4];
$true_bal=$array[5];
$all_days=$array[6];
$insert_bal=mysql_query("INSERT into temp_t_bal values ('','$comp_id','$emp_id','$start_bal','$taken','$remain_bal','$booked','$true_bal')");
$row=mysql_fetch_array($query);
}
}
}
Is this possible? Thanks in advance
You have read all the comments about why you shouldn't do it. That's for you to evaluate.
However, the ability to submit queries directly are supported.
As an example
$sqlQuery = "SELECT employee_id, holidays
FROM employee_work
WHERE company_id='$company_id' AND emp_active=1';
$listEmployee = Yii::app()->db->createCommand($sqlQuery)->queryAll();
foreach ($listEmployee as $itemEmployee){
print_r($itemEmployee);
}
Note that the above query is not safe, and can be subject to SQL injection. Yii offers a solution to upgrade the query to a safer format by using binding.
$listEmployee = Yii::app()->db->createCommand("SELECT employee_id, holidays
FROM employee_work
WHERE company_id=:company_id
AND emp_active=1')
->bindValue(':company_id',$company_id)
->queryAll();
You also have access to the query() method for queries that do not return a resultset
Yii::app()->db->createCommand('DELETE * FROM customer')->query();
References : http://www.yiiframework.com/doc/guide/1.1/en/database.dao

symfony2 doctrine fetch while without creating complete array of results

I am looking to export to a csv file using doctrine. However the data is likely to be quite large. Therefore I dont want to ouput to the results to a complete array. I want to traverse the results iteratively.
I have tried looking here
doctrine docs
The PHP looks something like this
$result = mysql_query("SELECT * FROM bigtable");
while($row = mysql_fetch_assoc($result)) {
// do code iteratively here
}
Not sure how you do the same thing in doctrine for symfony2
This is from the doctrine documentation about batch processing:
$q = $this->_em->createQuery('select u from MyProject\Model\User u');
$iterableResult = $q->iterate();
foreach ($iterableResult AS $row) {
// do stuff with the data in the row, $row[0] is always the object
// detach from Doctrine, so that it can be Garbage-Collected immediately
$this->_em->detach($row[0]);
}
'select u ....is the equivalent to your SELECT * ...
$result = mysql_query("SELECT * FROM bigtable");
while($row = mysql_fetch_assoc($result)) {
// do code iteratively here
}
is Flat PHP and symfony2/doctrine is designed to avoid it. http://symfony.com/doc/2.0/book/from_flat_php_to_symfony2.html
kudos to Dirk his answer is correct. If you want to iterat eover entity models then thats the way to go. Sometimes you may not have a model mapped setup for the sql results you are returning. If you want to do it over a raw sql file then this is how I did it. I would be interested to hear more thoughts.
You pass the doctrine connection into the class via your controller
Controller
function indexAction(){
$className = new ClassName($this->getDoctrine()->getEntityManager());
}
You can then create raw sql lookup
Entity
function __construct($entity){
$this->connection = $entity->getConnection();
}
function saveToCSV
{
$stmt = $this->connection->prepare("SELECT * FROM bitTableExample ");
$stmt->execute();
while($row = $stmt->fetch()){
// append to csv file
}
}

Generic MySQL Select All Function

I write a lot of SELECT * FROM... kind of queries in my web sites. I'd like to write a function that looks after this for me so I can call on it more quickly, without using more advanced techniques like PDO and OOP. Im just confused on how I would call the data I retrieve from the database, particularly when looping through the array's results.
I'd love something like this:
function selectAll($tableName, $limitAmount) {
global $dbConnection;
$query = mysql_query("SELECT * FROM $tableName ORDER BY id LIMIT $limitAmount");
$row_result = mysql_fetch_assoc($query);
return $row_result;
}
Say it was a bunch of news posts. Id like to loop through the results in one of the typical ways:
// CALL THE FUNCTION
selectAll('news_table', '10');
// SOMEHOW LOOP THROUGH RESULTS??
do {
echo "<h2>".$row_result['title']."</h2>";
} while ($row_result = mysql_fetch_assoc($query));
Obviously this isn't how I loop through the bespoke results of a function. Im not even sure if my function is correct.
Any help is greatly appreciated.
EDIT: Forgot to return a result inside the function and call the actual function. My bad. Updated now.
There is no point in having such a function called like yours.
Just make it like this
function fetchAll($query) {
$res = mysql_query($query) or trigger_error("db: ".mysql_error()." in ".$query);
$a = array();
if ($res) {
while($row = mysql_fetch_assoc($res)) $a[]=$row;
}
return $a;
}
and use it with whatever query:
$data = fetchAll("SELECT * FROM news_table ORDER BY id LIMIT 10");
foreach ($data as $row) {
echo $row['title'];
}
An SQL query being a powerful program itself. Do not reduce it's power to silly selects.
Use SQL to represent data processing logic and this helper function to avoid repetitions.

What is a good wrapper/framework/libraries for dealing with interface PHP applications to an SQL database?

I have a table
$query=
"CREATE TABLE screenshot ".
"(screenshot_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, ".
"source_video_id INT UNSIGNED NOT NULL, ".
"screenshot_file_name VARCHAR(128), ".
"x_res INT, ".
"y_res INT, ".
"time INT UNSIGNED);";
mysql_query($query);
Then I insert things into that table.
I often want to do an SQL query and iterate over the result of the query, but end up doing this.
//select all screenshots from video, by video id
$q0=
"SELECT * FROM screenshot ".
"WHERE source_video_id = '$source_video_id' ".
"AND x_res = 120 ".
"AND y_res = 90 ".
"ORDER BY time ASC;";
$r0 = mysql_query($q0);
$n0_num = mysql_numrows($r0);
//for each result
for($n0=0;$n0<$n0_num;$n0++) {
$source_video_id = mysql_result($r0,$n0,'source_video_id');
$time = mysql_result($r0,$n0,'time');
$screenshot_file_name = mysql_result($r0,$n0,'screenshot_file_name');
//do stuff for each returned result!
}
This is just ugly. To get the SQL query results, I have to write this for every column!
$source_video_id = mysql_result($r0,$n0,'source_video_id');
I have to write an ugly loop, get the results for each row returned and do something for each result. Basically I want something like;
foreach($SQL_command) {
//Do for each result
}
I want the column variables for each row to be already set, so that I do not have to do
$source_video_id = mysql_result($r0,$n0,'source_video_id');
For each and every column I want to access!
I am sick of writing boiler plate code to do this for every single table in my data. Are there any frameworks or libraries that would make this less painful?
These are the very basics of a database abstraction layer. It's not hard to program your own, or you can use a generic library like Doctrine or Propel. Every notable PHP framework includes some form of database abstraction as well, you really just need to start using one.
One can suppose I'm a fan of Kohana, but I really love the thing. Get the Kohana 3 and put there the Sprig ORM (it's a fork from original Sprig ORM, but with additional ‘sugar’ :) instead of native Kohana's one. You'll understand how pretty they are together. You'll can access to your tables like this code shows:
//just the basics, updating existing record
$screenshot = Sprig::factory('Screenshot', $id)->load();
$screenshot->x_res = 240;
$screenshot->y_res = 260;
$screenshot->update();
//creating new one
$screenshot = Sprig::factory('Screenshot');
$screenshot->x_res = 300;
$screenshot->y_res = 250;
$screenshot->create();
Additional link to the discussion of the Sprig fork: http://forum.kohanaframework.org/comments.php?DiscussionID=4368
Hope, it'll help you.
If you have the PDO drivers enabled (as you should) you can use the single DB() method as a function from the phunction PHP framework. It was inspired by the DiBi database abstraction layer. The documentation is still underway, but I've posted a short summary in this answer.
function DB($query)
{
static $db = null;
static $result = array();
if (is_null($db) === true)
{
if (preg_match('~^(?:mysql|pgsql):~', $query) > 0)
{
$db = new PDO(preg_replace('~^(mysql|pgsql):(?:/{2})?([-.\w]+)(?::(\d+))?/(\w+)/?$~', '$1:host=$2;port=$3;dbname=$4', $query), func_get_arg(1), func_get_arg(2));
if (preg_match('~^mysql:~', $query) > 0)
{
self::DB('SET time_zone = ?;', 'GMT');
self::DB('SET NAMES ? COLLATE ?;', 'utf8', 'utf8_unicode_ci');
}
}
else if (preg_match('~^(?:sqlite|firebird):~', $query) > 0)
{
$db = new PDO(preg_replace('~^(sqlite|firebird):(?:/{2})?(.+)$~', '$1:$2', $query));
}
}
else if (is_a($db, 'PDO') === true)
{
if (isset($query) === true)
{
$hash = md5($query);
if (empty($result[$hash]) === true)
{
$result[$hash] = $db->prepare($query);
}
if (is_a($result[$hash], 'PDOStatement') === true)
{
if ($result[$hash]->execute(array_slice(func_get_args(), 1)) === true)
{
if (preg_match('~^(?:INSERT|REPLACE)~i', $query) > 0)
{
return $db->lastInsertId();
}
else if (preg_match('~^(?:UPDATE|DELETE)~i', $query) > 0)
{
return $result[$hash]->rowCount();
}
else if (preg_match('~^(?:SELECT|EXPLAIN)~i', $query) > 0)
{
return $result[$hash]->fetchAll(PDO::FETCH_ASSOC);
}
return true;
}
}
return false;
}
}
return $db;
}
Your example query could be written as:
// connect to the MySQL server, do this on your config file or something
DB('mysql://host:port/database_name/', 'username', 'password');
// run the query!
$results = DB('SELECT * FROM screenshot WHERE source_video_id = ? AND x_res = ? AND y_res = ? ORDER BY time ASC;', $source_video_id, 120, 90);
foreach ($results as $result)
{
print_r($result);
}
The above code uses prepared queries which means that you'll also be safe from SQL injection attacks.
PS: I'm biased here, since I'm the developer of the framework. If you run into any problems let me know.
I use RedBean in all my projects and would recommend it without hesitation. The main reasons being:
Minimum configuration required. I don't have to map the database schema into a YAML or JSON file, simply put in the connection parameters and go.
Elegant and easy to understand usage syntax.
Lots of features such as caching and tree relationships.
Pretty good performance.
And here's an example of using it:
$book = R::dispense('book');
$book->title = 'Gifted Programmers';
$book->author = 'Charles Xavier';
$id = R::store($book);

Categories