Zend Framework Complex Where Statement - zend-framework

This method is published as offical example
->where("price < $minimumPrice OR price > $maximumPrice")
is such method safe?
want to write it as
->where("price < ? OR price > ?", $minimumPrice, $maximumPrice)
are there any poissibility?
and I can't split it into 2 where statements because plan to write query
->where("1 OR 2")
->where("3 OR 4")

Try this:
$query->where('(price < ?', $minPrice)
->orWhere('price > ?)', $maxPrice)
->where('some = ?', $some_other_variable);
will result:
where ((price < $minPrice) OR (price > $maxPrice)) AND (some = $some_other_variable)
Note the double (( )) in OR part

If I have complex WHERE clauses I use the db adapters' ->quoteInto() method like:
$where = '('
. $dbAdapter->quoteInto('price1 < ?', $price1)
. ' OR '
. $dbAdapter->quoteInto('price1 > ?', $price1)
. ')'
. ' AND '
. '('
. $dbAdapter->quoteInto('price2 < ?', $price2)
. ' OR '
. $dbAdapter->quoteInto('price2 > ?', $price2)
. ')'
;
$select->where($where);

Some times you will want to make SQL queries which have parenthesis around multiple where conditions that would be easily parsed with foreach, but you do not want to be bothered about string manipulation. For example, you would have a list of users with id's and that have to be of certain type, you can try this:
$select = $this->select();
$subWhere = $this->select();
foreach(array_keys($idArr) as $key => $value) {
$subWhere->orWhere('id=?', $value);
}
$select->where(implode(' ', $subWhere->getPart('WHERE')))->where('type=?', 'customer');
This will result in "SELECT * FROM table WHERE ((id=X) OR (id=Y) OR (id=Z)...) AND (type='customer');"
The idea developed a bit further, you could extend the Zend_Db_Table_Abstract:
public function subWhere($col, $binds, $operands, $andOr = 'OR' )
{
$subWhere = $this->select();
if(strtolower($andOr) == 'or') {
foreach($binds as $key => $value) {
$subWhere->orWhere($col.$operands[$key].'?', $value);
}
return implode(' ', $subWhere->getPart('WHERE'));
}
elseif (strtolower($andOr) == 'and') {
foreach ($binds as $key => $value) {
$subWhere->where($col.$operands[$key].'?', $value);
}
return implode(' ', $subWhere->getPart('WHERE'));
}
else {
return false;
}
}
And use it as:
$this->select()->where($this->subWhere($col, $binds, $operands));
Of course you should allow mixed $cols, $operands = array() defaulting as '=?' etc. but for the sake of simplicity I left that out. But I believe we should use native SQL functions like IN(), BETWEEN ... AND ..., NOT BETWEEN ... AND ...? Zend Framework doesn't make your life very easy though.

$select->where($db->quoteInto('field1 < ? OR', $minPrice)
. $db->quoteInto('field1 > ?', $maxPrice))
->where($db->quoteInto('field2 < ? OR', $value2)
. $db->quoteInto('field2 > ?', $value3));

Related

Sort order list view by 'logged in user' in SuiteCRM

Removing default sort order in list view and sorting by 'Logged in user' in SuiteCRM.
Add the following code in custom/modules/Prospects(your module)/views/view.list.php
function listViewProcess() {
global $current_user;
$user_name = $current_user->user_name;
$id = $current_user->id;
$this->processSearchForm();
$this->params['custom_order_by'] = ' ORDER BY FIELD(assigned_user_id, "'.$id.'") DESC';
$this->lv->setup($this->seed, 'include/ListView/ListViewGeneric.tpl', $this->where, $this->params);
$savedSearchName = empty($_REQUEST['saved_search_select_name']) ? '' : (' - ' . $_REQUEST['saved_search_select_name']);
echo $this->lv->display();
}
custom_order_by will be considered as second order by field
so declare
$ret_array['order_by']=''; in include/ListView/ListViewData.php
before
$main_query = $ret_array['select'] . $params['custom_select'] . $ret_array['from'] . $params['custom_from'] . $ret_array['inner_join']. $ret_array['where'] . $params['custom_where'] . $ret_array['order_by'] . $params['custom_order_by'];
Without customizing the code in include/listView/ListViewDate.php, just add the following code in custom/modules/(your module)/views/view.list.php
function listViewProcess() {
global $current_user;
$user_name = $current_user->user_name;
$id = $current_user->id;
$this->processSearchForm();
$this->params['overrideOrder']='1';
$this->params['orderBy']='1';
$this->params['custom_order_by'] = ' ORDER BY FIELD(accounts.assigned_user_id, "'.$id.'") DESC';
$this->lv->setup($this->seed, 'include/ListView/ListViewGeneric.tpl', $this->where, $this->params);
$savedSearchName = empty($_REQUEST['saved_search_select_name']) ? '' : (' - ' . $_REQUEST['saved_search_select_name']);
echo $this->lv->display();
}

How to prevent SQL injection in PhalconPHP when using sql in model?

Let's say I am building a search that finds all the teacher and got an input where the user can put in the search term. I tried reading the phalcon documentation but I only see things like binding parameters. I read the other thread about needing prepare statements do I need that in Phalcon as well?
And my function in the model would be something like this:
public function findTeachers($q, $userId, $isUser, $page, $limit, $sort)
{
$sql = 'SELECT id FROM tags WHERE name LIKE "%' . $q . '%"';
$result = new Resultset(null, $this,
$this->getReadConnection()->query($sql, array()));
$tagResult = $result->toArray();
$tagList = array();
foreach ($tagResult as $key => $value) {
$tagList[] = $value['id'];
....
}
}
My question is for the Phalcon framework is there any settings or formats I should code for this line $sql = 'SELECT id FROM tags WHERE name LIKE "%' . $q . '%"';
And also any general recommendation for preventing SQL Injection in PhalconPHP controllers and index would be appreciated.
For reference:
My controller:
public function searchAction()
{
$this->view->disable();
$q = $this->request->get("q");
$sort = $this->request->get("sort");
$searchUserModel = new SearchUsers();
$loginUser = $this->component->user->getSessionUser();
if (!$loginUser) {
$loginUser = new stdClass;
$loginUser->id = '';
}
$page = $this->request->get("page");
$limit = 2;
if (!$page){
$page = 1;
}
$list = $searchUserModel->findTeachers($q, $loginUser->id, ($loginUser->id)?true:false, $page, $limit, $sort);
if ($list){
$list['status'] = true;
}
echo json_encode($list);
}
My Ajax:
function(cb){
$.ajax({
url: '/search/search?q=' + mapObject.q + '&sort=<?php echo $sort;?>' + '&page=' + mapObject.page,
data:{},
success: function(res) {
//console.log(res);
var result = JSON.parse(res);
if (!result.status){
return cb(null, result.list);
}else{
return cb(null, []);
}
},
error: function(xhr, ajaxOptions, thrownError) {
cb(null, []);
}
});
with q being the user's search term.
You should bind the query parameter to avoid an SQL injection. From what I can remember Phalcon can be a bit funny with putting the '%' wildcard in the conditions value so I put them in the bind.
This would be better than just filtering the query.
$tags = Tags::find([
'conditions' => 'name LIKE :name:',
'bind' => [
'name' => "%" . $q . "%"
]
])
Phalcon\Filter is helpful when interacting with the database.
In your controller you can say, remove everything except letters and numbers from $q.
$q = $this->request->get("q");
$q = $this->filter->sanitize($q, 'alphanum');
The shortest way for requests:
$q = $this->request->get('q', 'alphanum');

how to implement concatenate mysql queries in zend framework Model

Hi i am new in zend framework.
I want to know that it is possible to use concatinate queries in zend model.
example like this we do in core php
$abc ="SELECT * FROM emp"
if ($_post ['a'] != '')
{
$abc =$abc ." WHERE code=$_post ['a']";
}
if ($_post ['b'] != '')
{
$abc =$abc ." WHERE name=$_post ['b']";
}
$abc.=" ORDER BY datetime;";
If possible I want to implement above code in Zend model.
Yes you can do such in zend. Here is the dummy idea for you.
First create the object of the model of emp table.
$emp = new Application_Model_Emp();
$select = $emp->select();
In model $_POST is not working so you need to pass the arguments from the controller. Here I am using that as variable.
if($a != '') {
$select->where("code = ?", $a);
}
if($b != '') {
$select->where("name = ?", $b);
}
$select->order("datetime");
$rows = $emp->fetchAll($select);

Magento - Get list of all Manufacturers with product count

I am using the following code to list all the manufacturers and it works like a charm:
$attribute = Mage::getModel('eav/entity_attribute')
->loadByCode('catalog_product', 'manufacturer');
$valuesCollection = Mage::getResourceModel('eav/entity_attribute_option_collection')
->setAttributeFilter($attribute->getData('attribute_id'))
->setStoreFilter(0, false);
$preparedManufacturers = array();
foreach($valuesCollection as $value) {
$preparedManufacturers[$value->getOptionId()] = $value->getValue();
}
if (count($preparedManufacturers)) {
echo "<h2>Manufacturers</h2><ul>";
foreach($preparedManufacturers as $optionId => $value) {
echo "<li>" . $value . " - (" . $optionId . ")</li>";
}
echo "</ul>";
}
What I am looking for is a way to display the number of products associated with each of the manufacturers. Can someone please tell me the way of doing this?
Many thanks
Not all mine, but works for me in 1.6+?
<?php
include_once 'app/Mage.php';
Mage::app();
$attribute = Mage::getModel('eav/entity_attribute')
->loadByCode('catalog_product', 'manufacturer');
$valuesCollection = Mage::getResourceModel('eav/entity_attribute_option_collection')
->setAttributeFilter($attribute->getData('attribute_id'))
->setStoreFilter(0, false);
$preparedManufacturers = array();
foreach ($valuesCollection as $value) {
$preparedManufacturers[$value->getOptionId()] = $value->getValue();
}
if (count($preparedManufacturers)) {
echo "<h2>Manufacturers</h2><ul>";
foreach ($preparedManufacturers as $optionId => $value) {
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addFieldToFilter(array(array('attribute' => 'manufacturer', 'eq' => $optionId)));
$mumberOfProducrt = count($collection);
echo "<li>" . $value . " - (" . $mumberOfProducrt . ")</li>";
}
echo "</ul>";
}
?>
This would work but won't be the most efficient:
foreach($valuesCollection as $value) {
$preparedManufacturers[$value->getOptionId()] = $value->getValue();
$collection = Mage::getModel('catalog/product')->getCollection();
$collection
->addAttributeToSelect('*') // '*' not efficient though
->addAttributeToFilter('manufacturer', array('eq' => $value->getOptionId()))
//->addAttributeToFilter('manufacturer', $value->getOptionId())
;
$count = $collection->->getSize();
}
It's an extra query for each manufacturer so it's not great, if you have some caching etc it won't be too bad though.
Working code should do it
$collection = Mage::getModel('catalog/product')->getCollection()->groupByAttribute('manufacturer')
->addFieldToFilter('status',Mage_Catalog_Model_Product_Status::STATUS_ENABLED)
->addExpressionAttributeToSelect("count",'COUNT({{entity_id}})', 'entity_id');
Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($collection);

CodeIgniter: how to return data from a form validation callback

Here is my CI form validation rule:
$datetime_string = $this->form_validation->set_rules('event_date', 'Select', 'callback_date_validate');
Here is my callback:
function date_validate($select_value)
{
$year = '';
$month = '';
$day = '';
$hour = '';
$minutes = '';
$datetime = $this->input->post('event_date');
if (strpos($datetime, ' # ') !== 'FALSE' && $datetime != '')
{
$datetime_explode = explode(' # ', $datetime);
if (strpos($datetime_explode[0], '/') !== 'FALSE' && $datetime_explode != '')
{
$date_explode = explode('/', $datetime_explode[0]);
$year = $date_explode[2];
$month = $date_explode[1];
$day = $date_explode[0];
}
if (strpos($datetime_explode[1], ':') !== 'FALSE')
{
$time_explode = explode(':', $datetime_explode[1]);
$hour = $time_explode[0];
if (strpos($time_explode[1], ' ') !== 'FALSE')
{
$minutes_explode = explode(' ', $time_explode[1]);
$minutes = $minutes_explode[0];
$am_pm = $minutes_explode[1];
if ($am_pm == 'PM' || $am_pm == 'pm')
$hour += 12;
}
}
}
$datetime_string = $year . '-' . $month . '-' . $day . ' ' . $hour . ':' . $minutes . ':00';
if (!preg_match('/^\d{4}-\d{2}-\d{2} 2[0-3]|[01][0-9]:[0-5][0-9]:[0-5][0-9]$/', $datetime_string))
{
$this->form_validation->set_message('date_validate', 'Oops');
}
else // user picked something
{
return $datetime_string;
}
}
According to the CI documentation, you can return data from a form validation callback, but by setting the rule equal to a variable, I get this error:
Object of class CI_Form_validation could not be converted to string
What am I doing wrong?
I think the problem is in this line:
$datetime = $this->input->post('event_date');
The value of event_date field is captured in a parameter of your function $select_value try using your parameter instead of post data.
$this->form_validation->set_rules(...); should be called inline and not assigned to a variable. You have assigned it to $datetime_string. Remove this assignment.
I don't know if you ever solved this but I was scratching around the documentation wondering the same thing as your question.
First of all, you just want...
$this->form_validation->set_rules('event_date', 'Select', 'callback_date_validate');
Don't assign it to a variable.
Next, you want to run your validation rules/callbacks...
if ($this->form_validation->run() == TRUE) {
// VALIDATION OK, CHECK OUR CALLBACK DATA
var_dump($this->input->post());
}
Now you should see your data returned from the callback in... $this->input->post('event_date');
The thing that confused me about returning data from callbacks was this thread on the official CI forums... http://codeigniter.com/forums/viewthread/191087/ where people are suggesting that the callback doesn't change the POSTed data. They are only partially correct. It doesn't change it under $_POST['whatever'] but it does change it in $this->input->post('whatever')
As this was the 3rd result in Google I hope this helps someone out.