How can I concatenate queries using Eloquent Builder?
I am building queries based on criteria (where clause) and taking limit and offset from URL. These queries are then passed to ->get() method to fetch result. I want to do it using Eloquent and not Query builder.
This is how you build a query in eloquent(I have given an example of using multiple where clauses):
$result = ModelName::where('key_1', '=' , 'value_1')
->where('key_2', '>', 'value_2')
->take(4)
->offset(2)
->get()
The take() method will limit the number of results to 4 with offset 2.
http://laravel.com/docs/5.0/eloquent
Update
Based on OP's question over here https://laracasts.com/discuss/channels/general-discussion/eloquent-query-builder , I am updating my answer.
You could do something like this:
if($params)
{
$query = $this->model;
foreach($params['search'] as $param)
{
$query = $query->where($param['where'],'=',$param['value']);
}
if (isset($params['start']))
{
$query = $query->offset($params['start'] );
}
if(isset($params['count']))
{
$query = $query->take($params['count']);
}
if (isset($params['sortColumn']))
{
$ascending = $params['ascending'] == 'true' ? 'ASC' : 'DESC';
$query = $query->orderBy($params['sortColumn'], $ascending);
}
}
$query->get();
What you need is assigning result of functions again to the model.
You had:
if($params)
{
foreach($params['search'] as $param)
{
$this->model->where($param['where'],'=',$param['value']);
}
if (isset($params['start']))
{
$this->model->offset($params['start'] );
}
if(isset($params['count']))
{
$this->model->take($params['count']);
}
if (isset($params['sortColumn']))
{
$ascending = $params['ascending'] == 'true' ? 'ASC' : 'DESC';
$this->model->orderBy($params['sortColumn'], $ascending);
}
}
$this->model->get();
and you need to use:
if($params)
{
foreach($params['search'] as $param)
{
$this->model = $this->model->where($param['where'],'=',$param['value']);
}
if (isset($params['start']))
{
$this->model = $this->model->offset($params['start'] );
}
if(isset($params['count']))
{
$this->model = $this->model->take($params['count']);
}
if (isset($params['sortColumn']))
{
$ascending = $params['ascending'] == 'true' ? 'ASC' : 'DESC';
$this->model = $this->model->orderBy($params['sortColumn'], $ascending);
}
}
$data = $this->model->get();
Related
I am using Laravel 9 and am displaying some data using the paginate method on the database. I also have a search field above my table and use it to filter out the result. While filtering, I filter the data and call the paginate method on it too. That's where the issue arises. Let's say I was on page number 6 before filtering and after filtering the result sums up in two page, but the paginate method redirect me to page 6 which in turn will show no results.
Below is my code example:
For the first time page:
$modelData = Model::orderBy('id', 'DESC')->paginate(20);
After filtering:
$search = $_GET['searchField'];
$modelData = Model::where("name", "LIKE", "%{$search}%")->paginate(2);
I was expecting it to take me to the first page of the result, but it takes me the the page where i searched my list from.
EDIT:
My Complete function:
public function index()
{
$sortData = $searchData = NULL;
//CHECKS FOR SORTING, SEARCH AND BOTH
if (isset($_GET['sort']) && !empty($_GET['sort']) && isset($_GET['searchField']) && !empty($_GET['searchField'])) {
$search = $_GET['searchField'];
$modelData = Model::where("name", "LIKE", "%{$search}%")->orderBy($_GET['sort'], $_GET['direction'])->paginate(10);
$sortData = $_GET;
$searchData = $search;
} elseif (isset($_GET['sort']) && !empty($_GET['sort'])) {
$modelData = Model::orderBy($_GET['sort'], $_GET['direction'])->paginate(10);
$sortData = $_GET;
} elseif (isset($_GET['searchField']) && !empty($_GET['searchField'])) {
$search = $_GET['searchField'];
$modelData = Model::where("name", "LIKE", "%{$search}%")->paginate(10);
$searchData = $search;
} else {
$modelData = Model::orderBy('id', 'DESC')->paginate(10);
}
return view('content.view.list', compact(
'modelData',
'sortData',
'searchData'
));
}
I think you should not use $_GET
$request->query('sort')
$request->query('direction')
Since you use !empty(), you don't need to use isset().
You don't need $search, because
$search = $_GET['searchField'];
...
$searchData = $search;
So
$searchData = $_GET['searchField'];
You don't need $searchData,too. Because $sortData = $_GET.
You already have whole $_GET, why do you want to define one of it's element again? $sortData['searchField']
I think the English meaning of searchData is better than sortData. Becuar sortData means the data needed to sort, to order by. While searchData means the data needed to do the search task, do the filtering work. So searchData should be the $_GET.
I suggest:
public function index()
{
$searchData= $request->query(); // This is $_GET
// See what is your $_GET
//echo "<pre>".print_r($searchData, 1)."</pre>"; exit;
$model = Product::query(); //Initialize query builder
if(!empty($searchData['searchField']))){
$model->where('name', 'LIKE', '%'.$searchData['searchField'].'%');
}
if(!empty($searchData['sort']))){
$sort = $searchData['sort'];
}else{
$sort = 'id'; // default use id
}
if(!empty($searchData['direction'])){
$direction = $searchData['direction'];
}else{
$direction = 'DESC'; // default use desc
}
$model->orderBy($sort, $direction);
// This can see the SQL content, and it should before result like paginate() or get(). I think...
if(!empty($searchData['debug'])){
$debugData['sql'] = $query->toSql();
$debugData ['bidings'] = $query->getBindings();
echo "<pre>".print_r($debugData , 1)."</pre>"; exit;
}
if(!empty($searchData['limit'])){
$limit = $searchData['limit'];
}else{
$limit = 10;
}
$modelData = $model->paginate($limit)->appends($queries);
return view('content.view.list', compact(
'searchData',
'modelData',
));
How to implode and insert values into the database in CodeIgniter?
I am creating multiple choice quiz script using CodeIgniter framework. I want to store user results like this:
id userid q_id answer_id time_taken
1 1 1,2,3,4,5 2,3,4,5,3 4,5,7,6,7
in my controller:
public function insert_result()
{
$this->load->model('quiz_models');
$user_id=$this->input->post('user_id');
$qq_id=$this->input->post('questionid');
$answer_id=$this->input->post('AnswerID');
$time_taken=$this->input->post('timetaken');
$question_no=$this->input->post('question_no');
$bd = "$question_no";
switch ($bd) {
case"1":
$data=array('user_id'=>$user_id,
'q_id'=>$qq_id,
'answer_id'=>$answer_id,
'time_taken'=>$time_taken);
$this->quiz_models->insert_result($data);
break;
case"2":
quiz_test();
break;
case"3":
quiz_test();
break;
case"4":
quiz_test();
break;
case"5":
quiz_test();
$this->session->unset_userdata('lastids');
break;
default:
echo "something is wrong";
}
}
public function quiz_test()
{
$this->load->model('quiz_models');
$quiz=$this->quiz_models->quiz_test();
foreach($quiz as $row){
$qid=$row->q_id;
$ans=$row->answer_id;
$time=$row->time_taken;
$a = array("$qq_id","$qid");
$b = array("$answer_id","$ans");
$c = array("$time_taken","$time");
$comma = implode(",",$a);
$comma1 = implode(",",$b);
$comma2 = implode(",",$c);
$data=array('q_id'=>$comma,
'answer_id'=>$comma1,
'time_taken'=>$comma2);
$this->quiz_model->update_result($data);
}
}
}
and Model:
function insert_result($data)
{
$this->dbb->insert('results',$data);
$sectio=$this->db->insert_id();
$this->session->set_userdata('lastids',$sectio);
}
function quiz_test()
{
$ses_id = $this->session->userdata('lastids');
$sql = "SELECT q_id, answer_id, time_taken FROM results WHERE id='$ses_id'";
$query = $this->dbb->query($sql);
$result = $query->result();
return $result;
}
function update_result($data){
$ses_id = $this->session->userdata('lastids');
$this->db->where('id',$ses_id);
$this->db->update('results',$data);
}
when i run it nothing happened,not showing any error where do i mistake?
pls help me what am i doing wrong
First of all - i think you've a major problem in your DB structure
Normalize your Data
You should prevent to store your information in the table like that.
It should be possible to normalize your data properly. If you dont know
how to do that the following link could be interesting:
Normalization in MYSQL
However a possible solution would be to structure your data:
In order to do that - create a save Method in your Model to split between update and insert - this model could look like
class Quiz_Models
{
private $arrPostData;
public function save($arrPostData = false)
{
$this->arrPostData = (!$arrPostData) ? $this->input->post() : $arrPostData;
$id = $this->session->userdata("lastids");
if ($id)
{
$query = $this->db
->select("*")
->from("results")
->where("id",$id)
->get();
if ($query->num_rows() == 1)
{
$this->update($query->row(0));
}
else return false;
}
else
{
$this->insert();
}
if ($this->arrPostData['question_no'] == 10) $this->session->unset_userdata("lastids");
}
private function update($objData)
{
$objCollection = new Quiz_Collection();
$objCollection->userId = $objData->userid;
$objCollection->id = $objData->id;
$arrData = explode($objData->q_id);
foreach($arrData AS $key => $quizId)
{
$objQuiz = new stdClass();
$objQuiz->q_id = $quizId;
$objQuiz->answer_id = explode($objData->answer_id)[$key];
$objQuiz->time_taken = explode($objData->answer_id)[$key];
$objCollection->append($objQuiz);
}
$objQuizFromPost = new stdClass();
$objQuizFromPost->q_id = $this->arrPostData["questionid"];
$objQuizFromPost->answer_id = $this->arrPostData['AnswerID'];
$objQuizFromPost->time_taken = $this->arrPostData['timetaken'];
$objCollection->addQuizFromPost($objQuizFromPost);
$this->db
->where("id",$objCollection->id)
->update("results",$objCollection->getDbData());
}
private function insert()
{
$objCollection = new Quiz_Collection();
$objCollection->userId = $this->arrPostData['user_id'];
$objQuizFromPost = new stdClass();
$objQuizFromPost->q_id = $this->arrPostData["questionid"];
$objQuizFromPost->answer_id = $this->arrPostData['AnswerID'];
$objQuizFromPost->time_taken = $this->arrPostData['timetaken'];
$objCollection->addQuizFromPost($objQuizFromPost);
$this->db->insert("results",$objCollection->getDbData());
$this->session->set_userdata("lastids", $this->db->insert_id());
}
}
as an addition you need a Collection Object (put this below your model)
class Quiz_Collection extends Array_Object
{
public $userId = 0;
public $id = 0;
public function addQuizFromPost($objQuiz)
{
if (intval($objQuiz->q_id) > 0)
{
foreach($this AS $key => $obj)
{
if ($obj->q_id == $objQuiz->q_id)
{
$this->offsetSet($key, $objQuiz);
return true;
}
}
$this->append($objQuiz);
return true;
}
return false;
}
public function sortQuizData($objA, $objB)
{
if ($objA->q_id == $objB->q_id) return 0;
return ($objA->q_id < $objB->q_id) ? -1 : 1;
}
public function getDbData()
{
$this->uasort(array($this,"sortQuizData"));
$arrData = $this->getArrayCopy();
$arrDbData = [
"userid" => $this->userId,
"q_id" => implode(array_map(function($obj){ return $obj->q_id;},$arrData),","),
"answer_id" => implode(array_map(function($obj){ return $obj->answer_id;},$arrData),","),
"time_taken" => implode(array_map(function($obj){ return $obj->time_taken;},$arrData),","),
];
return $arrDbData;
}
}
pS: this is just an instruction how you can do that in a proper way. Pls study this code. If you still don't understand whats going on, feel free to ask.
Is it possible to split queries somehow like this?
public function getStatuses($dates)
{
$query = DB::table('tickets');
if ($dates['from'])
$query = $query->where('from', $dates['from']);
if ($dates['to'])
$query = $query->where('to', $dates['to']);
$query = $query->select('Active');
return $query->get()->toArray();
}
Yes, it's possibile. But don't reassign to the same variable or you risk messing it up:
public function getStatuses($dates)
{
$query = DB::table('tickets');
if ($dates['from'])
$query->where('from', $dates['from']);
if ($dates['to'])
$query->where('to', $dates['to']);
$query->select('Active');
return $query->get()->toArray();
}
In Laravel 4, its necessary to assign the get method to a variable
public function scopeGetPosts($query, $this_user = NULL){
$results = DB::table('post')
->select('*')
->where('post_status','=','publish');
if( $this_user != NULL ){
$results->where('post_author','=',$this_user->user_id);
}
$data = $results->orderBy('created_at', 'desc')
->get();
if( empty( $results ) )
$data = 'no results';
return $data;
}
In Laravel Eloquent :
$query = ModelName::where('status',1);
if($userId){
$query->where('user_id',$userId);
}
if($limit){
$query->limit($limit);
}
$result = $query->get();
I have some simple function to collect allowed array, but something is not ok, can somebody help me? Here is my code
public function getAllbyLink($table, $what, $url)
{
$link=mysql_real_escape_string($url);
$query = $this->db->query("SELECT * FROM ".$table." WHERE ".$what." = '{$link}' LIMIT 0 , 1");
if ($query->num_rows() > 0)
{
return $query->result();
}
else redirect('');
}
Please read something about MVC pattern, question is clearly pointed on how to write a Model.
consider using this function
public function getTable($table, $where = array(), $select = '*', $order_by = '', $limit = '', $offset = '') {
if ($order_by !== '' && $order_by != 'RANDOM') $this->db->order_by($order_by);
if ($order_by == 'RANDOM') $this->db->order_by('id', 'RANDOM');
if ($limit !== '') $this->db->limit($limit, $offset);
$this->db->select($select);
$q = $this->db->get_where($table, $where);
return ($q->num_rows() > 0) ? $q->result() : FALSE;
}
for your purpose call the function like this:
getTable($talbe, array('what' => $link));
//returns FALSE if no data are selected,
//or returns object with data,
if you wish return array instead replace $q->result() with $q->array_result()
Please note that active record auto escapes.
After comments:
comment-1, you can simplify that function easily just delete what you do not need, for example
public function getTable2($table, $where = array(), $limit = '', $offset = '') {
if ($limit !== '') $this->db->limit($limit, $offset);
$q = $this->db->get_where($table, $where);
return ($q->num_rows() > 0) ? $q->result() : FALSE;
}
comment-2,when there is no data use this if-else statement
if (!$my_data = getTable2('table', array('where' => $link))) {
//there is some DATA to work with
echo "<pre>";
var_dump($my_data);
echo "</pre>";
} else {
//no DATA do redirect or tell user that there is no DATA
redirect(); //redirect to default_controller
}
comment-3, no comment;
comment-4, It also allows for safer queries, since the values are escaped automatically by the system. from this source. And another SO question about active record providing exact answer you are seeking.
My understanding of your code is:
Read all rows from table
Check if linkurl is in the list
If so, return a random row for that value
Else, redirect.
In this case, try this:
public function getAllbyLink($table,$url,$what)
{
$query = $this->db->query("
SELECT *
FROM `".$table."`
WHERE `".$what."` = '".mysql_real_escape_string($linkurl)."'
ORDER BY RAND()
LIMIT 1
");
if( !$query) return redirect('');
$result = $query->result();
if( !$result) return redirect('');
return $result;
}
I am developing a CMS which works on template page system in a different approach.
I have this object:
$structure = new stdClass;
$structure->homepage->news->method = 'get_articles_by_page_name';
$structure->homepage->news->lang_key = translate('home_news');
$structure->homepage->news->lang = $lang;
$structure->homepage->news->add_media = true;
$structure->homepage->news->media_type = 'ibs';
$structure->homepage->news->limit = '5';
$structure->homepage->news->order_by = 'a.logical_date';
$structure->homepage->news->asc_des = 'desc';
$structure->homepage->news->result_type = 'result';
This helps to get contents as following:
foreach ($structure as $page_template => $page_contents)
{
// Call Customized Content for Homepage
if($this->data['page_data']->page_view == $page_template) // homepage comes ok.
{
foreach ($page_contents as $view_var_name => $page_cdata)
{
$method = $page_cdata->method; // method names comes
$page_cdata = substr(implode(",",(array) $page_cdata),(strlen($method)+1)) . '\'';
//Returns as expected:
//**'Haberler','tr','1','ibs','5','a.logical_date','desc','result'**
$this->data[$view_var_name] = $this->publish->$method($page_cdata);
vdebug($page_cdata);
}
}
}
It suppose to call them model function of:
function get_articles_by_page_name( $lang_key='',$lang='en',$add_media=true,
media_type='ibs',$limit='0',$order_by='a.logical_date',$asc_desc='desc',$result_type='result')
However, there is a problem with. When I return to last worked query it says:
SELECT * FROM (`page`) JOIN `page_lang` ON `page`.`id_page` = `page_lang`.`id_page` WHERE `page_lang`.`title` = '\'News\',\'tr\',\'1\',\'ibs\',\'5\',\'a.logical_date\',\'desc\',\'result\''
It souldn't be like this. every thing between commas are parameters of the method function. What cause this, any idea?
Content of get_articles_by_page_name:
function get_articles_by_page_name ($lang_key='',$lang='tr',$add_media=true,$media_type='ibs',$limit='0',$order_by='a.logical_date',$asc_desc='desc',$result_type='result')
{
// Define variables
$id_page = '';
$result = '';
// Get Page Data
$page_name = $lang_key;
$get_page = $this->vayes->getJoined('page','page_lang','id_page','','',array('page_lang.title'=>$page_name),'row');
if($get_page)
{
$id_page = $get_page->id_page;
$result = $this->publish->get_articles($lang,$id_page,null,false,'',$order_by,$asc_desc,$limit,'result');
}
else
{
$result = array('No id_page specified');
}
return $result;
}
Content of get_articles:
function get_articles($lang='tr',$id_page,$id_article=null,$incl_media=true,$media_type='',$order_by='a.logical_date',$asc_desc='desc',$limit='0',$result_type='result')
{
$this->db->select('*');
$this->db->from('article a');
$this->db->join('article_lang b','b.id_article=a.id_article','left outer');
if($incl_media) {
$this->db->join('article_media c','c.id_article=b.id_article','left outer');
$this->db->join('media d','d.id_media=c.id_media','left outer');
}
if($id_article == null) { $this->db->where('a.id_page',$id_page); }
else /*------------->*/ { $this->db->where('a.id_article',$id_article); }
$this->db->where('b.lang',$lang);
$this->db->where('b.online',1);
if(($incl_media == true) AND $media_type != '' ) $this->db->where('c.usage',$media_type);
// Order Results
$this->db->order_by($order_by,$asc_desc);
// Limit Results
if ($limit) $this->db->limit($limit);
$query = $this->db->get();
if($query->num_rows() > 0)
{
$result = $query->$result_type();
$query->free_result();
return $result;
}
return false;
}
try stripslashes()
Attempting to use stripslashes on an array in 5.2.17 returns the string "Array", but in 5.3.6 it returns NULL. So using stripslashes() on an array you will need to do it recursively;
function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}
// Example
$array = array("f\\'oo", "b\\'ar", array("fo\\'o", "b\\'ar"));
$array = stripslashes_deep($array);
// Output
print_r($array);