Hi, my problem is simple i want to add multiple where condition on yii2 Query bulder, but i don't know what doing.
my code like that
public function searchForTrip($params, $extraParams, $filter) {
$query = Boatinformation::find()
->where(['what_island' => $params['BoatinformationSearch']['what_island']])
->all();
if(isset($filter)) {
foreach ($filter as $key => $value) {
->andFilterWhere([$value => 1])
}
}
return $query;
}
this is not working
please someone help me
You can do in several way and you can found an useful guide in this doc http://www.yiiframework.com/doc-2.0/guide-db-query-builder.html
you can use string format specifying the condition as a string :
$query->where('your_field1 =1 and your_field2 = 2');
You can use hash format and
$query->where([
'your_field1' => 10,
'your_field2' => null,
'your_field3' => [4, 8, 15],
]);
You can use operator format
$query->where(['and' , 'your_field1', 10, ]);
and you can also use
andWhere('your_field'=> $your_value ),
You should write something like
public function searchForTrip($params, $extraParams, $filter) {
$query = Boatinformation::find()
->where(['what_island' => $params['BoatinformationSearch']['what_island']])
if(isset($filter)) {
foreach ($filter as $key => $value) {
$query->andFilterWhere([$value => 1])
}
}
return $query;
}
$query->andFilterWhere() add where condition if $value exist,
$query->andWhere() add where condition always
and if you want to return objects instead of query you should return $query->all();
Related
I'm trying to build a filter on my data using laravel ..
I have many to many relationships between the BasicItem model And AttValue Model and table Item_value between them.
this code works as what I want but I need it to be more dynamic depending on the user choice
ex. this $value is what the user choices
$values = array(
"0" => ['Dell','hp'],
"1" => ['Mac' ,'linux','windows'],
"2" => ['12.3' ,'12.5'],
"3" => ['8 GB RAM'],
);
$x = BasicItem::whereHas('AttValue', function($query) use ($values) {
$query->whereIn('attributeValue', $values["0"] );
})
->WhereHas('AttValue', function($query) use ($values) {
$query->whereIn('attributeValue',$values["1"]);
})
->WhereHas('AttValue', function($query) use ($values) {
$query->whereIn('attributeValue',$values["2"]);
})
->WhereHas('AttValue', function($query) use ($values) {
$query->whereIn('attributeValue',$values["3"]);
})
->get();
Now I want to Repeat the
->WhereHas('AttValue', function($query) use ($values) {
$query->whereIn('attributeValue',$values["$i"]);
statement as many as the length of the array
If you want the query to work contextually the same, the best way is to do this:
$x = BasicItem::query();
foreach($values as $value) {
$x->whereHas('AttValue', function($query) use ($value) {
$query->whereIn('attributeValue',$value);
});
}
$x->get();
Only results will show that have attributeValue in first array AND second array AND third array AND forth array and so on.
EDIT: Changed solution to loop over whereHas in stead of whereIn
$values = array(
"0" => ['Dell', 'hp'],
"1" => ['Mac', 'linux', 'windows'],
"2" => ['12.3', '12.5'],
"3" => ['8 GB RAM'],
);
$val_arr = [];
foreach ($values as $value) {
foreach ($value as $item){
$val_arr[] = $item;
}
}
$x = BasicItem::whereHas('AttValue', function($query) use ($val_arr) {
$query->whereIn('attributeValue', $val_arr );
})->get();
you can do this just whereHas. You can look your array put 1 array and you can whereIn this array.
Simple and sweet query:
use Illuminate\Support\Arr;
$x = BasicItem::whereHas('AttValue', function($query) use ($values) {
$query->whereIn('attributeValue', Arr::flatten($values));
})
->get();
infinite/dynamic whereHas,
$x = BasicItem::query();
foreach($values as $value) {
$x->whereHas('AttValue',
fn($query) => $query->whereIn('attributeValue',$value)
);
}
$x->get();
I want to retrieve some data from 'tbl_karyawan' and input into 'tbl_absen' which is if the NIP exist from 'tbl_karyawan' then parshing some data into 'tbl_absen'. I was create the code, and the data is going well. but i have something trouble with
i want the data input in Nip_kyn be like 'KIP001' not [{"Nip_kyn":"KIP001"}].
this is my Model
public function presensi($data)
{
$isExist = DB::table('tbl_karyawan')
->where('Nip_kyn', $data)->exists();
if ($isExist) {
$namakyn = DB::table('tbl_karyawan')->where($data)->get('Nama_kyn');
$nippppp = DB::table('tbl_karyawan')->where($data)->select('Nip_kyn')->get($data);
$values = array('Nip_kyn' => $nippppp, 'Nama_kyn' => $namakyn, 'Jam_msk' => now(), 'Log_date' => today());
DB::table('tbl_absen')->insert($values);
} else {
echo 'data not available';
}
}
this is my controller
public function get()
{
$day = [
'time_in' => $this->AbsenModel->timeIN(),
'time_out' => $this->AbsenModel->timeOut(),
'break' => $this->AbsenModel->break(),
// absen here
's' => $this->AbsenModel->absensi(),
];
$data = [
'Nip_kyn' => Request()->Nip_kyn,
];
$this->AbsenModel->presensi($data);
return view('v_absen', $data, $day);
}
Yup, I finally got it, the problem is on my model.
$nama_karyawan = DB::table('tbl_karyawan')->where($data)->value('Nama_kyn');
$nipkyn = DB::table('tbl_karyawan')->where($data)->value('Nip_kyn');
I just change 'get' to 'value'.
What I am trying to achieve:
I have a table with a type field which holds integer values. These integer values represent different strings.
I want to be able to search the table using the string values that the integers represent.
E.g type = abc rather than type = 0.
What have I tried:
I have created a query class for the model and tried to make use of the $boolean_map property:
class ReportQuery extends FilterableQuery
{
protected $filterable = [
'type' => 'LIKE',
'removed_the_rest'
];
protected $boolean_map = ["type" => [ 'addacs' => 0, "arudd" => 1,]];
}
Then I have overridden the find method of the model to use the query class:
public static function find()
{
$query = new ReportQuery(get_called_class());
return $query;
}
And in the search model I have:
public function search($params)
{
$query = Report::find();
$dataProvider = new ActiveDataProvider([
'query' => $query
]);
$this->load($params, '');
if (!$this->validate()) {
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'type' => $this->type,
]);
$query->andFilterWhere(['like', 'type', $this->type]);
return $dataProvider;
}
When searching by the string values I get an empty result. Searching by the integer values produces the data.
Any help is appreciated. Thanks.
Maybe it's better for you to make filter on that column instead of searching by string. You can do it for string as follows.
$filter = [
'example1' => 1,
'example2' => 2,
'example3' => 3,
];
$query->andFilterWhere(['like', 'type', $this->filter[$this->type]);
or in this place
// grid filtering conditions
$query->andFilterWhere([
'type' => $this->filter[$this->type],
])
also you can make filter dropdown on column, and for dropdown of that filter you can pass this array and just do
$query->andFilterWhere([
'type' => $this->type,
])
Why do you create mapping mechanism in query object? Okay, you show integer type as a string in frontend of your application, but the query shouldn't have details of representation. You should map string type to integer type in your search model. For example:
class ReportSearchModel extends ReportModel
{
public function mapType($value)
{
$items = [
'addacs' => 0,
'arudd' => 1
];
return array_key_exists($value, $items) ? $items[$value] : null;
}
public function search($params)
{
//another code
$query->andFilterWhere([
'type' => $this->mapType($this->type),
])
//another code
}
}
The alternative way is using an enum instead of mapping.
I am generating a query that returns results from a camp. I am sending it to another platform that digests this data as an array.
I am trying to return my kickoffs in order by score (highest to lowest).
Here is what the query looks like:
$camp = Camp::where('id', $camp_id)
->where('approved', 1)
->with(['athletes' => function ($q) use ($camp_id) {
$q->with(['kickoffs' => function ($q) use ($camp_id) {
$q->where('camp_id', $camp_id);
}]);
$q->with(['kickoff_results' => function ($q) use ($camp_id) {
$q->where('camp_id', $camp_id);
$q->orderBy('score', 'desc');
}]);
...
})->first();
...
if ($camp) {
return response()->json([
'data' => $camp,
...
], 200);
}
In my other system this is how I am outputting it:
foreach ($context['camp']['data']['athletes'] as $athlete) {
...
if (!empty($athlete['kickoff_results'])) {
...
}
}
When the result is finally rendered, it seems there is no order whatsoever.
Thank you for any suggestions!
my controller:
function getFeed()
{
$feed_url = $this->input->get("url");
$content = file_get_contents($feed_url);
$x = new SimpleXmlElement($content);
foreach($x->channel->item as $entry) {
$feeds[] = array(
'title' => (string)$entry->title,
'url'=> (string)$entry->link,
'username' => $this->session->userdata('username')
);
$this->load->model('membership_model');
$this->membership_model->feeds($feeds);
}
Model:
function feeds($feeds_data)
{
$this->db->insert_batch('feeds', $feeds_data);
}
Is there a function to insert if only the row doesn't exists in the table? I have a table with 4 column : id,title,url,username. I have an anchor when i click him it calls geFeed function and insert the info into table. But i want to insert only if not exists.
I had the same challenge, so i eventually come up with a function which might be helpful to you.
function safe_update_batch($table_name,$records,$filter_field)
{
$filters=array();
foreach($records as $record)$filters[]=$record[$filter_field];
$this->db->query("SET SESSION group_concat_max_len=10000000");
$query=$this->db->select("GROUP_CONCAT($filter_field) AS existing_keys",FALSE)->where_in($filter_field, $filters)->get($table_name);
$row=$query->row();
$found_fields=explode(',',$row->existing_keys);
$insert_batch=array();
$update_batch=array();
foreach($records as $record)
{
if(in_array($record[$filter_field],$found_fields))$update_batch[]=$record;
else $insert_batch[]=$record;
}
if(!empty($insert_batch))$this->db->insert_batch($table_name,$insert_batch);
if(!empty($update_batch))$this->db->update_batch($table_name,$update_batch,$filter_field);
}
//sample usage
$this->safe_update_batch('feeds', $feeds_data,'title');
You can try this in your model!!
function insertClient($array)
{
$this->db->from('MyTable');
$this->db->where('Id', $array['Id']);
$query = $this->db->get();
if($query->num_rows() != 0){
$data = array(
'name'=>$array['name'],
'phone'=>$array['phone'],
'email'=>$array['email']
);
$this->db->where('Id', $array['Id']);
$this->db->update('CLIENTS', $data);
}else{
$data = array(
'name'=>$array['name'],
'phone'=>$array['phone'],
'email'=>$array['email']
);
$this->db->insert('CLIENTS',$data);
}
}
In controller:
$this->site_model->insertClient($_POST);
Sadly if you are using the active record class an INSERT IF NOT EXISTS function doesn't exist. You could try
Extending the active record class (easier said than done)
You could set indexes on certain columns as UNIQUE so that MySQL will check to see if it already exists
You could do some kind of SELECT before your INSERT to determine if the record is already there
For the queries where you need to do INSERT IF NOT EXISTS do $this->db->query('INSERT IF NOT EXISTS...')
function getFeed()
{
// Load the model up here - otherwise you are loading it multiple times
$this->load->model('membership_model');
$feed_url = $this->input->get("url");
$content = file_get_contents($feed_url);
$x = new SimpleXmlElement($content);
foreach($x->channel->item as $entry) {
// check if the feed is unique, if true then add to array
if( $this->membership_model->singleFeedIsUnique($entry) == TRUE ){
$feeds[] = array(
'title' => (string)$entry->title,
'url'=> (string)$entry->link,
'username' => $this->session->userdata('username')); }
} //foreach
// check to make sure we got any feeds with isset()
// if yes, then add them
if (isset($feeds)){ $this->membership_model->feeds($feeds); }
}
You can try this in your model and leave you controller without changes
function feeds($feeds_data)
{
$data = array(
title => $feeds_data[0],
url => $feeds_data[1],
username => $feeds_data[2]
);
$this->db->select('*');
$this->db->from('mytable');
$this->db->where('title',$feeds_data[0]);//you can use another field
if ($this->db->count_all_results() == 0) {
$query = $this->db->insert('mytable', $data);//insert data
} else {
$query = $this->db->update('mytable', $data, array('title'=>$feeds_data[0]));//update with the condition where title exist
}
}
you can check the id if you have it, adding in the data array and use it to check if exist