How do query with a OR and AND operator in CI? - php

I try to make query in Codeigniter via Active Records:
if (isset($data['where']['and'])) {
$this->db->where($data['where']['and']);
}
if (isset($data['where']['or'])) {
$this->db->or_where_in('idSpec', $data['where']['or']);
}
I want to get:
WHERE name = 1 AND (idSpec = 2 OR idSpec = 3 OR idSpec = 4);
But now I get:
WHERE name = 1 OR idSpec = 2 OR idSpec = 3 OR idSpec = 4;

Use below code.
if (isset($data['where']['and'])) {
$this->db->where($data['where']['and']);
}
if (isset($data['where']['or'])) {
$this->db->where("(idSpec = 2 OR idSpec = 3 OR idSpec = 4;)", NULL, FALSE);
}

I assume your $data['where']['or'] contains some ids.
This may help you.
if (isset($data['where']['or']))
{
$or_conditions='(idSpec ='.implode(' OR idSpec = ',$data['where']['or']).')';
$this->db->where($or_conditions);//if this produce error use bellow one
//$this->db->where($or_conditions,'',false);
}

This is the basic method to select data from database I'm using well for a long time..
/**
* Le wild function to make a life better.
* Doing abrakadabra
*
* #param $table
* #param bool $selector
* #param string $order
* #param bool $start
* #param bool $limit
* #param $return
*
* #return mixed
*/
public function _getCustomTableData($table, $selector = FALSE, $order = 'id DESC', $start = FALSE, $limit = FALSE, $return = FALSE, $group_by = FALSE)
{
$query = $return ? $this->db->select($return) : $this->db->select('*');
if ( $selector ) {
if ( isset($selector['mixed_selection']) && $selector['mixed_selection'] == TRUE ) {
$query = $this->db->where($selector['mixed_selection']);
} else {
foreach ( $selector as $select_array ):
$query = $this->db->where($select_array);
endforeach;
}
}
if ( $group_by ) {
$query = $this->db->group_by($group_by);
}
$query = $this->db->order_by($order);
if ( $start && $limit ) {
$query = $this->db->limit($limit, $start);
}
if ( ! $start && $limit ) {
$query = $this->db->limit($limit);
}
// proceed
$query = $this->db->get($table);
if ( $limit == TRUE && $limit == 1 ) {
$query = $query->row_array();
if ( $return ) {
return $query[$return];
} else {
return $query;
}
} else {
$query = $query->result_array();
return $query;
}
}
and query looks like:
$this->_getCustomTableData('table', array(array('selector' => '1', 'time >=' => time())), 'id DESC', FALSE, 1, 'id');
it's like:
SELECT 'id' FROM `table` WHERE `selector` = 1 AND `time` >= 1472582... ORDER BY id DESC LIMIT 1
or you can use "mixed selection"
$this->_getCustomTableData('table', array('mixed_selection' => 'selector = 1 AND time >= 1472582...'), 'id DESC', FALSE, 1, 'id');
and the result will be the same. I have wrote this method when I was beginner with CI and it helped me a lot :)

Related

How to filter based on I18n content with pagination component?

I have comeup with strange problem in cakephp 3.4. I am running filter query on i18n content like this.
if($this->request->query("q")){
$this->paginate["conditions"][$this->ContractTypes->translationField('title').' LIKE'] = '%'.$this->request->query("q").'%';
}
but following call is ending up in Database error
$records = $this->paginate($this->ContractTypes);
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ContractTypes_title_translation.content' in 'where clause' SELECT (COUNT(*)) AS `count` FROM contract_types ContractTypes WHERE ContractTypes_title_translation.content like :c0
The paginator's count query is not joing i18n table. What is the best approach to solve this problem.
Thanks in advance,
I have solved this by creating my custom paginator component by editing the paginate function. My paginator contains following code incase somebody else is facing the same problem.
namespace Console\Controller\Component;
use Cake\Controller\Component\PaginatorComponent as BasePaginator;
class PaginatorComponent extends BasePaginator
{
public function paginate($object, array $settings = [])
{
$query = null;
if ($object instanceof QueryInterface) {
$query = $object;
$object = $query->repository();
}
$alias = $object->alias();
$options = $this->mergeOptions($alias, $settings);
$options = $this->validateSort($object, $options);
$options = $this->checkLimit($options);
$options += ['page' => 1, 'scope' => null];
$options['page'] = (int)$options['page'] < 1 ? 1 : (int)$options['page'];
list($finder, $options) = $this->_extractFinder($options);
if (empty($query)) {
$query = $object->find($finder, $options);
} else {
$query->applyOptions($options);
}
$cleanQuery = clone $query;
// My Modification Starts Here
$table = $cleanQuery->repository();
$results = $query->all();
$numResults = count($results);
$count = $numResults ? $cleanQuery->select([
"count"=>$cleanQuery
->func()
->count($table->alias().'.'.$table->primaryKey())
])->first()->count : 0;
// My Modification ends Here
$defaults = $this->getDefaults($alias, $settings);
unset($defaults[0]);
$page = $options['page'];
$limit = $options['limit'];
$pageCount = (int)ceil($count / $limit);
$requestedPage = $page;
$page = max(min($page, $pageCount), 1);
$request = $this->_registry->getController()->request;
$order = (array)$options['order'];
$sortDefault = $directionDefault = false;
if (!empty($defaults['order']) && count($defaults['order']) == 1) {
$sortDefault = key($defaults['order']);
$directionDefault = current($defaults['order']);
}
$paging = [
'finder' => $finder,
'page' => $page,
'current' => $numResults,
'count' => $count,
'perPage' => $limit,
'prevPage' => $page > 1,
'nextPage' => $count > ($page * $limit),
'pageCount' => $pageCount,
'sort' => key($order),
'direction' => current($order),
'limit' => $defaults['limit'] != $limit ? $limit : null,
'sortDefault' => $sortDefault,
'directionDefault' => $directionDefault,
'scope' => $options['scope'],
];
if (!$request->getParam('paging')) {
$request->params['paging'] = [];
}
$request->params['paging'] = [$alias => $paging] + (array)$request->getParam('paging');
if ($requestedPage > $page) {
throw new NotFoundException();
}
return $results;
}
}

CakePHP custom query paginator: custom paginate function is not called

I build a custom query and tried use the default paginator, like this:
WodsController.php
$userId = $this->Auth->user('id');
$connection = ConnectionManager::get('default');
$result = $connection->execute("SELECT wods.id, wods.titulo , wods.dia , wods.tempo, wods.repeticoes ,userwods.user_id FROM wods
LEFT JOIN userwods ON userwods.wod_id = wods.id WHERE userwods.user_id is null or userwods.user_id=4 order by wods.dia desc limit 50")->fetchAll('assoc');
$results = array();
foreach ($result as $r) {
$entity = $this->Wods->newEntity($r);
array_push($results, $entity);
}
$wods = $this->paginate($results);
$this->set('_serialize', ['wods']);
I got this error "Unable to locate an object compatible with paginate".
Now I'm tryng implement custom query paginator, but it's not working.
I implemented paginate and paginateCount functions in the model.
Wods.php file:
public function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = array()) {
$recursive = -1;
$this->useTable = false;
$sql = '';
$sql .= "SELECT wods.id, wods.titulo , wods.dia , wods.tempo, wods.repeticoes ,userwods.user_id FROM wods LEFT JOIN userwods ON userwods.wod_id = wods.id WHERE userwods.user_id is null or userwods.user_id=4 order by wods.dia desc limit ";
// Adding LIMIT Clause
$sql .= (($page - 1) * $limit) . ', ' . $limit;
$results = $this->query($sql);
return $results;
}
public function paginateCount($conditions = null, $recursive = 0, $extra = array()) {
$sql = '';
$sql .= "SELECT wods.id, wods.titulo , wods.dia , wods.tempo, wods.repeticoes ,userwods.user_id FROM wods LEFT JOIN userwods ON userwods.wod_id = wods.id WHERE userwods.user_id is null or userwods.user_id=4 order by wods.dia desc";
$this->recursive = $recursive;
$results = $this->query($sql);
return count($results);
}
In the controller WodsController.php
public function index()
{
$this->Wods->recursive = 0;
$this->paginate = array('Wods'=>array('limit'=>10));
$this->set('wods', $this->paginate('Wods'));
}
But the custom paginator is not called, it continues calling the default paginate function. Why ?
Following dragmosh advise (thanks), I investigate CakePHP ORM custom queries builder.
In this solution I used find() function with specific options, after I called the default paginator:
$query = $this->Wods->find()
->select(['Wods.id', 'Wods.titulo','Wods.dia','Wods.rounds','Wods.tempo','Wods.repeticoes','Userwods.user_id'])
->join([
'table' => 'Userwods',
'alias' => 'Userwods',
'type' => 'LEFT',
'conditions' => 'Userwods.wod_id = Wods.id',
])
->where(function ($exp, $q) {
return $exp->isNull('Userwods.user_id');})
->orWhere(['Userwods.user_id' => 4])
->contain(['Userwods'])
->autoFields(true);
$wods = $this->paginate($query);
$this->set(compact('wods'));
$this->set('_serialize', ['wods']);

Refactor if statements in PHP or another solution for if statements (not switch case)

I have some if statements in my code.
e.g:
if($option[0]->posts == 1 && $option[0]->pages == 1){
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND (post_type="page" OR post_type="post") ORDER BY post_title ASC', OBJECT );
}
if($option[0]->pages == 1 && $option[0]->posts == 0){
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND post_type="page" ORDER BY post_title ASC', OBJECT );
}
if($option[0]->pages == 0 && $option[0]->posts == 1){
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND post_type="post" ORDER BY post_title ASC', OBJECT );
}
a bit pseudo code of the code above:
if foo = 1 and bar = 1 -> return foo and bar
if foo = 0 and bar = 1 -> return only bar
if foo = 1 and bar = 0 -> return only foo
if foo = 0 and bar = 0 -> return false
You see:
00
10
01
11
00
If I insert another variable I'll get a lot of more opportunities and that is realy bad. Because I'll get realy big if statements.
Can somebody tells me another opportunitie to achive the same result?
Thank you.
I'd do it like this:
$sql_condition = '( 1=2 '; // one fake-condition, just to make it possible to start with 'OR' later
foreach($option[0] as $key => $value) { // iterate through all possible conditions
if($value===1) { // maybe exclude $keys that should not be used here
$sql_condition.=' OR post_type="'.$key.'"';
}
}
$sql_condition.=')';
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND '.$sql_condition.' ORDER BY post_title ASC', OBJECT );
Please try this code :
$sub_query = $operator = '';
if($option[0]->posts == 1)
{
$sub_query = 'post_type="page"';
$operator = ' OR';
}
if($option[0]->pages == 1)
{
$sub_query .= $operator.' post_type="post"';
}
if(empty($sub_query))
{
return false;
}
else
{
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND ('.$sub_query.') ORDER BY post_title ASC', OBJECT );
}
Create an array($arr) and set the key like "0,0" and value like "$sql";
and your code will be like this:
$tempKey = $option[0]->pages . "," . $option[0]->posts;
if(isset($arr[$tempKey]) {
$results = $wpdb->get_results($arr[$tempKey]);
}
So when you want to add more pages and posts all you will do is to change the arr.
$types = [];
if ($option[0]->posts)
$types[] = '"post"';
if ($option[0]->pages)
$types[] = '"page"';
if (!$types)
return null;
$results = $wpdb->get_results( 'SELECT * FROM '.$wpdb->prefix.'posts WHERE post_status="publish" AND (post_type IN ('. implode(',', $types) .')) ORDER BY post_title ASC', OBJECT );

Adding additional search for reference in Joomla component

I am using a real estate component that has a front-end admin area to view property listings. An additional field was added to a section called custom fields that is named Ref (Reference). In the admin listings I am trying to add an additional search that searches for that reference. There are three tables involved here:
1j0_cddir_jomestate Which holds the property listings information such as title and description.
1j0_cddir_fields which is the custom fields created.
1j0_cddir_content_has_fields and this holds the values of the custom fields
I would need to join 1j0_cddir_content_has_fields "fields_id" with 1j0_cddir_fields "id" and 1j0_cddir_jomestate "id" must join 1j0_cddir_content_has_fields "content_id"
I am struggling to figure out how to add this function to the models/admin_listings.php so that I may add that search input to the admin_listings view.
<?php
protected $text_prefix = 'COM_JOMESTATE';
protected $user;
function __construct()
{
parent::__construct();
$this->user=JFactory::getUser();
$this->planID=$this->getPlanID();
}
protected function getListQuery()
{
// Initialise variables.
$db = $this->getDbo();
$query = $db->getQuery(true);
if ($this->planID->profile=='company'){
$query->select(
$this->getState(
'list.select',
'a.id AS id, a.title AS title, a.date_created, a.featured, a.users_id, a.published, '.
'c.title as category_title,a.date_publish,a.date_publish_down,ag.first_name,ag.last_name'
)
);
}else{
$query->select(
$this->getState(
'list.select',
'a.id AS id, a.title AS title, a.featured, a.date_created, a.users_id, a.published, '.
'c.title as category_title,a.date_publish,a.date_publish_down'
)
);
}
$query->from($db->quoteName('#__cddir_jomestate').' AS a');
$query->select('COUNT(l.id) AS viewHow, SUM(l.view_item) AS viewSum');
$query->join('LEFT', '#__cddir_statistic AS l ON (l.item_id = a.id AND l.extension=\'com_jomestate\')');
// Join over the categories.
$query->join('LEFT', '#__cddir_categories AS c ON c.id = a.categories_id');
$query->join('LEFT', '#__cddir_categories AS e ON e.id = a.categories_address_id');
if ($this->planID->profile=='company'){
$query->join('LEFT', '#__cddir_agent AS ag ON a.users_id = ag.users_id');
$query->join('LEFT', '#__cddir_company AS co ON co.id = ag.company_id');
}
$query->join('LEFT', '#__users AS u ON u.id = a.users_id');
// Filter by published published
$published = $this->getState('filter.published');
if (is_numeric($published)) {
$query->where('a.published = '.(int) $published);
}
// Filter by category.
$categoryId = $this->getState('filter.categories_id');
if (is_numeric($categoryId) && $categoryId!=0) {
$cat_tbl = JTable::getInstance('Category', 'JomcomdevTable');
$cat_tbl->load($categoryId);
$rgt = $cat_tbl->rgt;
$lft = $cat_tbl->lft;
$baselevel = (int) $cat_tbl->level;
$query->where('c.lft >= '.(int) $lft);
$query->where('c.rgt <= '.(int) $rgt);
}
$search = $this->getState('filter.search');
if (!empty($search)) {
if (stripos($search, 'id:') === 0) {
$query->where('a.id = '.(int) substr($search, 3));
} else {
$search = $db->Quote('%'.$db->escape($search, true).'%');
$query->where('(a.title LIKE '.$search.' OR a.alias LIKE '.$search.')');
}
}
if ($this->planID->profile=='company'){
$query->where('(a.users_id ='.(int) $this->user->id.' or co.users_id='.(int) $this->user->id.')');
}
else $query->where('a.users_id ='.(int) $this->user->id);
$sort = $this->getState('list.sort');
switch($sort) {
case 'most_viewed':
$query->order($db->escape('viewSum DESC, a.date_publish DESC'));
break;
case 'alfa':
$query->order($db->escape('a.title, a.date_publish DESC'));
break;
case 'featured':
$query->order($db->escape('a.featured DESC, a.date_publish DESC'));
break;
case 'latest':
default:
$query->order($db->escape('a.date_publish DESC'));
}
$query->group($db->escape('a.id'));
return $query;
}
function getCategories()
{
$cat_array = array(array('v'=>'','t'=>JText::_('COM_JOMESTATE_ADM_ALL')));
$query = "SELECT title, id, level FROM #__cddir_categories WHERE extension='com_jomestate.jomestate' ORDER BY lft";
$data = $this->_getList($query);
foreach ($data as $row):
for ($i=1;$i<$row->level;$i++) $row->title="   ".$row->title;
$temp_array=array('v'=>$row->id,'t'=>$row->title);
array_push($cat_array,$temp_array);
endforeach;
return $cat_array;
}
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* #since 1.6
*/
protected function populateState($ordering = null, $direction = null)
{
// Initialise variables.
$app = JFactory::getApplication('site');
// Load the parameters.
// $params = $app->getParams();
$params = JComponentHelper::getParams('com_jomestate');
$menu = $app->getMenu();
$this->active = $menu->getActive();
if ($this->active) {
$menuParams = $this->active->params;
$global = $menuParams->get('global_option');
if(!$global) {
$paramsa = $menuParams->toArray();
$paramsb = $params->toArray();
foreach($paramsa AS $key=>$p) $paramsb[$key] = $p;
$newObject = (object) $paramsb;
$newObject->activeItemid = $this->active->id;
$params->loadObject($newObject);
}
}
$this->setState('params', $params);
$limit = $this->getUserStateFromRequest($this->context.'.list.limit', 'jdItemsPerPage', $params->get('listing_per_page'), 'uint');
$this->setState('list.limit', $limit);
$value = $app->getUserStateFromRequest($this->context . '.list.limitstart', 'limitstart', 0);
$limitstart = ($limit != 0 ? (floor($value / $limit) * $limit) : 0);
$this->setState('list.start', $limitstart);
$search = $this->getUserStateFromRequest($this->context.'.filter.search', 'filter_search', '', 'string');
$this->setState('filter.search', $search);
$categoryId = $this->getUserStateFromRequest($this->context.'.filter.categories_id', 'filter_category', '', 'string');
$this->setState('filter.categories_id', $categoryId);
$sort = $this->getUserStateFromRequest($this->context.'.list.sort', 'jdItemsSort', 'latest', 'string');
$this->setState('list.sort', $sort);
}
public function getUserStateFromRequest($key, $request, $default = null, $type = 'none', $resetPage = true)
{
$app = JFactory::getApplication();
$old_state = $app->getUserState($key);
$cur_state = (!is_null($old_state)) ? $old_state : $default;
$new_state = JRequest::getVar($request, $old_state, 'default', $type);
if (($cur_state != $new_state) && ($resetPage))
{
JRequest::setVar('limitstart', 0);
}
// Save the new value only if it is set in this request.
if ($new_state !== null)
{
$app->setUserState($key, $new_state);
}
else
{
$new_state = $cur_state;
}
return $new_state;
}
public function getUser()
{
return $this->user;
}
public function getToolbar()
{
$document = JFactory::getDocument();
$document->addStyleSheet('administrator/templates/system/css/system.css');
$document->addStyleSheet('components/com_jomestate/assets/css/backadmin.css');
$controller='admin_listings';
jimport('joomla.html.toolbar');
$bar = new JToolBar( 'toolbar' );
if(Joomla_Version::if3()) {
$bar->appendButton( 'standard', 'new', JText::_('COM_JOMESTATE_ADM_ADD'), $controller.'.add', false );
$bar->appendButton( 'standard', 'publish', JText::_('COM_JOMESTATE_ADM_PUBLISH'), $controller.'.publish', false );
$bar->appendButton( 'standard', 'unpublish', JText::_('COM_JOMESTATE_ADM_UNPUBLISH'), $controller.'.unpublish', false );
$bar->appendButton( 'standard', 'delete', JText::_('COM_JOMESTATE_ADM_DELETE'), $controller.'.delete', false );
} else {
$bar->appendButton( 'Frontend', 'new', JText::_('COM_JOMESTATE_ADM_ADD'), $controller.'.add', false );
$bar->appendButton( 'Frontend', 'publish', JText::_('COM_JOMESTATE_ADM_PUBLISH'), $controller.'.publish', false );
$bar->appendButton( 'Frontend', 'unpublish', JText::_('COM_JOMESTATE_ADM_UNPUBLISH'), $controller.'.unpublish', false );
$bar->appendButton( 'Frontend', 'delete', JText::_('COM_JOMESTATE_ADM_DELETE'), $controller.'.delete', false );
}
return $bar->render();
}

How can i show sphinx search result in PHP

How is that possible to show sphinx search result via PHP
i have installed sphinx and configured but i am unable to get the result via PHP
Check the Sphinx Library : Sphinx Documentation
The Below Code Is Used To Get The Full Content From Sphinx Search Result
Now Currently We Need To Give The Id In $SQL line
<?php
echo "Welcome To Sphinx Search Site </br>";
$q = "html";
$sphx = sphinx_search("html", 0, 20);
$sphx['122'];
$ids = 122;
$sql = "SELECT post_title , post_content FROM wp_posts WHERE ID = '122'";
db();
if( !($r = mysql_query($sql)))
die("[MYSQL]".mysql_error() . mysql_errno() );
$max = $sphx['total'];
$num_rows = $sphx['docs'];
echo "<b>Displaying {$num_rows} results of {$max}</b><br /><br />";
while($row = mysql_fetch_assoc($r) ) {
echo "{$row['post_title']} <br />{$row['post_content']}<br /><hr />";
}
mysql_free_result($r);
/*
* SPHINX Search
*/
/*
* Search sites by Keywords using sphinx; with an option to search sites tags only
* #param string $q te keyword
* #param int $i id of the first result to return
* #param int $max max results to return
* #param bollen $url set to true to return matches from the 'url' column only
*
* #return string $ids comma seperated list of ids
*/
function sphinx_search($q, $i, $limit, $post_type=true){
require_once 'sphinxapi.php';
$ids = '33500';
$cl = new SphinxClient();
$cl->SetServer( "192.168.0.89" , 9667);
$cl->SetMatchMode( SPH_MATCH_EXTENDED );
$cl->SetSortMode ( SPH_SORT_RELEVANCE );
$cl->SetFieldWeights(array('post_title' => 300));
$cl->SetLimits( $i , $limit);
$q = $cl->EscapeString( $q);
//search url only
$q = $post_type ? "#post_type {$q}" : $q;
$result = $cl->Query( $q, 'sites sitesDelta' );
if ( $result === false )
error_log( '[SPHINX]Query failed: ' . $cl->GetLastError() );
elseif ( $cl->GetLastWarning() )
error_log( '[SPHINX]WARNING: ' . $cl->GetLastWarning() );
if ( !empty($result["matches"]) ){
foreach ( $result["matches"] as $doc => $docinfo )
$ids .= "$doc,";
$ids = substr( $ids, 0, -1 );
}else
return false;
return array( 'ids' => $ids, 'total' => $result['total'], 'docs' => count($result["matches"]) );
}
/*
* Connect to MySQL
*/
function db(){
if( !empty($GLOBALS['db']) ) return true;
if( !$GLOBALS['db'] = mysql_connect('localhost', 'root', '' ) ) {
die("[MYSQL]".mysql_error() . mysql_errno() );
}
elseif(!mysql_select_db('sphinxiirmulti')) {
die("[MYSQL]".mysql_error() . mysql_errno() );
}
}
?>

Categories