How can I check if a leftJoin is set in? - php

I have a form filter with few custom search fields.
In the addXXXQuery functions, I have to use join on a table which is the same for some fields.
Can I check if innerJoin for that particular table is already set in another addXXXQuery?
[EDIT] example:
public function addIsPaidColumnQuery(Doctrine_Query $query, $field, $values)
{
if ($values) {
$rootAlias = $query->getRootAlias();
$query->leftJoin($rootAlias.".Inscription i");
->andWhere("i.is_paid = ?", $values);
}
}
public function addActTypeColumnQuery(Doctrine_Query $query, $field, $values)
{
if ($values) {
$rootAlias = $query->getRootAlias();
$query->leftJoin($rootAlias.".Inscription i")
->leftJoin("i.Act a")
$query->addWhere("a.act_type_id = ?", $values);
}
}

Well, you can retrieve the $params from the query, and check if the join is already there, something like this:
public function addIsPaidColumnQuery(Doctrine_Query $query, $field, $values)
{
if ($values)
{
$rootAlias = $query->getRootAlias();
$leftjoin = $rootAlias.".Inscription i";
$params = $query->getParams();
if (!isset($params['join']) || (isset($params['join']) && !in_array($leftjoin, $params)))
{
$query->leftJoin($leftjoin);
}
$query->andWhere("i.is_paid = ?", $values);
}
}
You can see in the code, how a leftJoin in added.

I couldn't find a method, that would tell me if a join for a table is set. However the more I thought about the existence of such method, the less sence it made for it. So to check if I already used a join in the filter query I set a class variable $leftJoinInscriptionSet.
private $leftJoinInscriptionSet = false;
...
public function addIsPaidColumnQuery(Doctrine_Query $query, $field, $values)
{
if ($values) {
$this->setLeftJoinInscription($query);
$query->andWhere("i.is_paid = ?", $values);
}
}
...
private function setLeftJoinInscription(Doctrine_Query $query) {
if (!$this->leftJoinInscriptionSet) {
$rootAlias = $query->getRootAlias();
$query->leftJoin($rootAlias.".Inscription i");
$this->leftJoinInscriptionSet = true;
}
}

Related

PHP function with parameters to update all columns in MySQL table but don't require all parameters and don't always update all columns

I have a MySQL table with columns:
opID, opDateAdded, opLastUpdated, opUser, opPropertySaleID, opArray, refurbID, opRefurbCost, opViewingArranged, opOfferAccepted, opOfferAcceptedID, opPaon, opStreet, opPostcode, opPropertyType, opViewingDate, opViewingBy, opViewingPersonName, opFloorArea, opBedrooms, opBathrooms, opReceptions, opAskingPrice, opValuation, opOptMatchingBedrooms, opOptMatchingBuild, opOptMatchingType, opOptSimilarFloor, opOptDistance, opLatitude, opLongitude, opNotes
I want to have one function that allows me to update the columns of this table but sometimes only 3-4 columns will need updating, not always all of them.
I'm just wondering what the best method of approaching this is?
I could create a function like:
function updateOpportunity($opID, $opDateAdded, $opLastUpdated, $opUser, $opPropertySaleID, $opArray, $refurbID, $opRefurbCost, $opViewingArranged, $opOfferAccepted, $opOfferAcceptedID, $opPaon, $opStreet, $opPostcode, $opPropertyType, $opViewingDate, $opViewingBy, $opViewingPersonName, $opFloorArea, $opBedrooms, $opBathrooms, $opReceptions, $opAskingPrice, $opValuation, $opOptMatchingBedrooms, $opOptMatchingBuild, $opOptMatchingType, $opOptSimilarFloor, $opOptDistance, $opLatitude, $opLongitude, $opNotes) {
//update
}
And set them as optional then check if they're set or not, if they are then update those rows (using IFNULL in MySQL)
Or maybe it's better and tidier to create a property class and pass in a property:
function updateOpportunity($property) {
//update
}
I'm just wondering if there is a standard for creating a function to update a large set of columns that aren't always in need of updating at the same time.
you can create a generic function which works for all table and column.. like this.
function update($table, $data, $id)
{
$set= array();
foreach ($data as $key => $value)
{
$set[] = "{$key} ='".mysqli_real_escape_string($value)."'";
}
$sql = "UPDATE {$table} SET ".implode(', ', $set)." WHERE ID = '$id'";
mysqli_query($connection,$sql);
}
here is a function using a prepared statement.
function update($table, $data, $id)
{
$setPart = array();
$bindings = array();
foreach ($data as $key => $value)
{
$setPart[] = "{$key} = :{$key}";
$bindings[":{$key}"] = $value;
}
$bindings[":id"] = $id;
$sql = "UPDATE {$table} SET ".implode(', ', $setPart)." WHERE ID = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute($bindings);
}
Here the $connection is a mysqli_connection object which we need to create to execute any query to know about this click here.
and in second function $pdo is PDO connection object which we need to create to execute the query click here for more information.
You can read this link for more information.
to prevent SQL injection you can use mysqli_real_escape_string() function
click here for more information.
You could do that with a class.
class Table {
private $pdo;
private $table;
private $where;
private $key;
private $id;
private $values;
private $sql;
public function __construct($pdo, $table = null, $key = null, $where = array(), $id = null) {
$this->pdo = $pdo;
$this->table($table);
$this->values($values);
$this->key($key);
$this->id = $id;
}
public function table($table) {
$this->table = $table;
return $this;
}
public function where($where) {
$this->where = $where;
$this->id = null;
return $this;
}
public function key($key) {
$this->key = $key;
return $this;
}
public function id($id) {
$this->id = $id;
$this->where = array();
return $this;
}
private function resetValues() {
$this->values = array();
return $this;
}
private function getWhere() {
$where = '';
$comma = ' WHERE ';
foreach ($this->where as $key => $value) {
$where .= $comma . $key . '=?';
$values[] = $value;
$comma = ',';
}
if ($this->id) {
if (!$this->key) {
throw new \Exception('primary key required but not specified');
}
$where .= $comma . $key . '=?';
$values[] = $value;
$comma = ',';
}
return $where;
}
private function getWhat(&$values) {
$fields = '';
$comma = '';
foreach ($values as $key => $value) {
$fields .= $comma . $key . '=?';
$values[] = $value;
$comma = ',';
}
return $fields;
}
public function update(array $values) {
$this->sql = "UPDATE {$this->table} SET ";
. $this->resetValues()->getWhat()
. $this->getWhere();
return $this;
}
public function perform() {
// Check $this->sql exists ecc.
return $this->pdo->prepare($this->sql)->execute($this->values());
}
}
Then you could do:
$TUsers = new Table($pdo);
$TUsers->table('users')->key('user_id');
...
$TUsers->update(['name' => 'Leonardo'])->id(137)->perform();
Note that the class user does not know which DB interface the class is using - you could offload it via subclassing, by abstracting the connection interface (here the $pdo supplied to the constructor) and the actual execution (here perform()).
If needed you might want to cache the prepared statement by comparing the MD5 of the actual SQL (which contains no column values) against a LRU array of saved statements (I believe that PDO might already do that, though). If the statement isn't present in the cache then you prepare() it, otherwise you fetch it back from the cache:
private function getStatement() {
$key = md5($this->sql);
if (!array_key_exists($key, $this->stmtCache)) {
// Expunge the oldest or least used or less costly or...
// statement if cache is full - TODO
// ...
$this->stmtCache[$key] = [
'stmt' => $this->pdo->prepare($this->sql)
];
}
$this->stmtCache[$key]['ts'] = time();
return $this->stmtCache[$key]['stmt'];
}
The same class could be extended with methods such as INSERT, DELETE, SELECT etc., or ancillary functions such as ORDER, GROUP and so on. And it could run consistency checks on its data and/or UTF-8 clean your fields and/or log every query matching some specifications, and so on and so forth.
You could also look into Doctrine or Propel.

How make search in mysql php oop?

I have mysql database of products with id, p_name(FULL TEXT), country, company, price. i need to make dynamic search on website. for now i have such problem when i query the result i have to type exact match of name in database. i tried to put %:query% but when i execute the result is empty
Model:
public function getSearchResult($query){
$params = [
'query' => $query,
];
// Prepare statement
$search = $this->db->row("SELECT id, p_name FROM product WHERE p_name LIKE :query", $params);
return $search;
}
Controller:
public function indexAction(){
$result = $this->model->getSearchResult($_POST['search']);
$vars = [
'result' => $result,
];
$this->view->render('Search', $this->vars + $vars);
}
DB Class:
public function query($sql, $params = []){
$stmt = $this->db->prepare($sql);
if(!empty($params)){
foreach ($params as $key => $val) {
if (is_int($val)) {
$type = PDO::PARAM_INT;
} else {
$type = PDO::PARAM_STR;
}
$stmt->bindValue(':'.$key, $val, $type);
}
}
$stmt->execute();
return $stmt;
}
public function row($sql, $params = []){
$result = $this->query($sql, $params);
return $result->fetchAll(PDO::FETCH_ASSOC);
}
You can add % in your array value. Change your model code like below:
public function getSearchResult($query){
$params = [
':query' => '%'.$query.'%', // change this line
];
// Prepare statement
$search = $this->db->row("SELECT id, p_name FROM product WHERE p_name LIKE :query", $params);
return $search;
}

run multiple select quires in one page using codeigniter

Hello any one can tell that how to load two function from model class in controller one method. I want to run multiple select quires in one page using codeigniter:
Controller
public function property_detail( $id )
{
$this->load->model('insertmodel');
$select1 = $this->insertmodel->find($id);
$select2 = $this->insertmodel->detail_list();
$data = array();
$this->load->view('home/property_detail', ['select1'=>$select1], ['select2'=>$select2]);
//$this->load->view('home/property_detail', ['select2'=>$select2]);
}
Model
public function find( $id )
{
$query = $this->db->from('article')->where(['id'=> $id])->get();
if( $query->num_rows() )
return $query->row();
return false;
}
public function detail_list(){
$query1 = $this->db->query("select * from article");
return $query1->result();
}
In Controller
public function property_detail( $id )
{
$this->load->model('insertmodel');
$data['select1'] = $this->insertmodel->find($id);
$data['select2'] = $this->insertmodel->detail_list();
$this->load->view('home/property_detail', $data);
}
In Model
public function find($id)
{
$query = $this->db->get_where('article', array('id' => $id), 0, 0)->get();
if( $query->num_rows() > 0 )
{
$result = $query->result_array();
return $result;
}
else
{
return false;
}
}
public function detail_list()
{
$query1 = $this->db->query("select * from article");
$result = $query1->result_array();
return $result;
}
In View
foreach ($select2 as $item) {
# your foreach lop goes here
}
As well check empty() before passing it to the foreach loop
As an alternative to #Rijin's useful answer newMethod() can make calls to the existing model methods. This might be useful if you don't want to break the interface already created for the model because you are using find($id) and detail_list() in other code.
Model:
public function find($id)
{
$query = $this->db->from('article')->where(['id' => $id])->get();
if($query->num_rows())
return $query->row();
return false;
}
public function detail_list()
{
$query1 = $this->db->query("select * from article");
return $query1->result();
}
public function newMethod($id)
{
$result['select1'] = $this->find($id);
if($result['select1'] !== FALSE)
{
$result['select2'] = $this->detail_list();
return $result;
}
return FALSE;
}
Controller:
public function property_detail($id)
{
$this->load->model('insertmodel');
$data = $this->insertmodel->newMethod($id);
$this->load->view('home/property_detail', $data);
}
Model :
public function find( $id )
{
$query = $this->db->from('article')->where(['id'=> $id])->get();
if( $query->num_rows() )
return $query->row();
return false;
}
public function detail_list()
{
$query1 = $this->db->query("select * from article");
return $query1->result();
}
Controller :
public function property_detail( $id )
{
$this->load->model('insertmodel');
$data['select1'] = $this->insertmodel->newMethod($id);
$data['select2'] = $this->insertmodel->detail_list();
$this->load->view('home/property_detail', $data);
}

Pass Parameter to Laravel toArray() Eloquent Model

I've a method in my Controller:
function getSuggestions()
{
$query = Input::get('query');
$suggestions = Suggestion::where('word', 'LIKE', "$query%")->get()->toArray();
$return $suggestions;
}
and in Model I have:
public function toArray(){
$array = parent::toArray();
$array['matched'] = 'ok';
return $array;
}
How can I pass a variable to this toArray() method to append it to the Model?
Something like this: $array['matched'] = $query
I can't pass the $query directly to toArray($query). Any other way?
Just add the value to each matched array:
function getSuggestions()
{
$query = Input::get('query');
$suggestions = Suggestion::where('word', 'LIKE', "$query%")->get()->toArray();
return array_map(
function ($array) use ($query) { $array['matched'] = $query; return $array; },
$suggestions
);
}

Chaining methods in PHP

$db->select("users")->where(array("username", "=", "username"));
$db->update("users", array("username" => "username", "password" => "12345"))->where(array("id", "=", "14"));
Ok, I want to write the statements like above, by chain the where() method onto select, update and delete.
My problem is; how to determine if I used the select, update or delete before the where, so I can bind the right values onto the right statement.
I want something like this:
public function where() {
if($this->select()) {
// so if $db->select("users")->where(array("username", "=", "username"));
// save the where data in the select variable.
}
elseif($this->update()) {
// so if $db->update("users", array("username" => "username", "password" => "12345"))->where(array("id", "=", "14"));
// save the where data in the update variable.
}
elseif($this->delete()) {
// so if $db->delete("users")->where(array("username", "=", "username"));
// save the where data in the delete variable.
}
}
But the code above is of course not valid, and I dont use any frameworks.
public function select($table, $what = null) {
$what == null ? $what = "*" : $what;
$this->_select = "SELECT {$what} FROM {$table}";
return $this;
}
You would have to maintain that state. It's not about telling whether the previous call was a select() or an update(), that's the wrong way to think about the problem. You just need each of select/update/delete to modify $this, so that $this, always knows what kind of query it's building.
A dead simple example:
public function select() {
$this->kind == 'select';
return $this;
}
public function where() {
if ($this->kind == 'select') {
...
return $this;
}
The only thing that your chained methods share is that they each return $this, so that a subsequent method can be chained onto the end. It's all about storing up state in $this until some final method call actually evalates the built-up query.
Something like:
public function select($table, $fields = '*')
{
$this->query = "SELECT {$fields} FROM `{$table}`";
return $this;
}
public function where($conditions = [])
{
if ($this->query)
{
if ($conditions)
{
foreach ($conditions as $key => &$val)
$val = "`{$key}` = '{$val}'";
$this->query .= ' WHERE ' . implode(' AND ', $conditions);
}
$db->query($this->query);
$this->query = '';
return $this;
}
}
This would work, however, you have to notice that this structure would allow you to do things like:
$db->where();
This is perfectly valid even though doesn't make sence to call where() in the database directly.
Also, queries that don't require a WHERE clause would not run, because only where() actually makes the call.
How to solve this?
We can actually use a very interesting mechanic of OOP: The destructor method. PHP destroys objects immediately after they are no longer in use, and we can explore this feature here as a trigger to run the query. We only have to separate the query to a new object.
class dbQuery
{
private $db;
private $conditions = [];
function where($conditions = [])
{
$this->conditions = array_merge($this->conditions, $conditions);
return $this;
}
function __construct($db, $query)
{
$this->db = $db;
$this->query = $query;
}
function __destruct()
{
if ($this->conditions)
{
foreach ($this->conditions as $key => &$val)
$val = "`{$key}` = '{$val}'";
$this->query .= ' WHERE ' . implode(' AND ', $this->conditions);
}
$this->db->result = $db->query($this->query);
}
}
class Database
{
public $result = null;
protected static $instance;
function __construct()
{
if (!self::$instance)
self::$instance = new mysqli('localhost', 'user', 'password', 'dbname');
}
public function query($query)
{
return self::$instance->query($query);
}
public function select($table, $fields = '*')
{
return new dbQuery($this, "SELECT {$fields} FROM `{$table}`");
}
}
This way $db->where() won't work as it doesnt exist, and using $db->select('table') or $db->select('table')->where([...]) will both give results, and even allows extending the syntax to use where() multiple times like:
$db->select('table')->where(['id' => 100])->where(['price' => 1.99]);

Categories