I am new in codeigniter4 I want to filter the list by alphabet and search input. On click of each alphabet, it should sort the list according to the alphabet. In my database product list is stored in JSON array format.
The below image to explain better
For example: If you click on "A" then it will display a list starting with "A" Like ( Apple, Airplane, Adidas ), etc. And the case should be the same when you input in the search input box.
Below is the render function in the controller which is searching particular objects of the JSON array.
public function loadRecord(){
$request = service('request');
$searchData = $request->getGet();
$search = "";
if(isset($searchData) && isset($searchData['search']))
{
$search = $searchData['search'];
}
$model = new PageModel();
if($search == ''){
$paginateData = $model->paginate(5);
} else {
$db=\Config\Database::connect();
$product_array = [];
$query = $db->query('
SELECT description->"$.products_title" as product_titles
FROM iolt_pages
WHERE description->"$.products_title"
LIKE "%'.$search.'%"
AND pg_id=33'
);
$result = $query->getResult();
$productData=json_decode($result[0]->product_titles);
for($i=0;$i<count($productData);$i++)
{
if(strpos($productData[$i], $search) !== false)
{
$product_array[]=$productData[$i];
} else {
//echo "Word Not Found!<br>";
}
}
print_r($product_array);
}
}
You need something like this:
public function loadRecord() {
$request = service('request');
$searchData = $request->getGet();
if(isset($searchData) && isset($searchData['search']))
{
$search = $searchData['search'];
}
$model = new PageModel();
if(!empty($search)) {
$model->like('description', $search, 'after');
}
$data = $model->asArray()->paginate(5);
if(!empty($data)) {
die('word not found');
}
dd($data);
}
There's no need for json for the filter, you can filter that with the like statement and you can keep adding to the model object with if statements and just run the query in the end. This way you don't need to have one query for all records and another for the filter, just add the filter if needed.
Also if you need an array instead of object you can do so in the model by changing the return type, this you can override by using the asArray() method that will return all data as an array. This way you don't need to iterate all the data to transform it from object to array.
Related
I have situation where I need to write a sql select query which is technically need to be repeated to all the items in a list.
For example, say I have list like this,
list =[ { item_1: value_11,
item_2: value_12,
item_3: value_13,
item_4: value_14'
},
{ item_1: value_21,
item_2: value_22,
item_3: value_23,
item_4: value_24,
},
{ item_1: value_31,
item_2: value_32,
item_3: value_33,
item_4: value_34,
},
......
];
Now I need to write a SELECT query to get all the related records for each of the item, something like,
//for each item
SELECT * FROM tbl WHERE tbl.fld1 = list[0].item_1 AND tbl.fld2 = list[0].item_2 AND tbl.fld3 = list[0].item_3 AND tbl.fld4 = list[0].item_4;
Is it possible to write a single query for the same within SQL statement (kind of loop) or else does it need to be repeated from the coding side so it will call the db for each items separately.
Please help,
Thank You in advance
As #draz already commented you need to loop over the list to dynamically create the sql statement. You can loop over it in your code and generate a single sql statement that can be send to the database once.
A simple but probably not the nicest idea would be something like:
sql_select = "SELECT * FROM tbl WHERE";
first_item = true;
for (element in list) {
sql_select = (first_item) ? sql_select : sql_select + " OR";
fist_item = false;
where_clause = ` (tbl.fld1 = ${element.item_1} AND tbl.fld2 = ${element.item_2} AND tbl.fld3 = ${element.item_3} AND tbl.fld4 = ${element.item_4})`;
sql_select.concat(where_clause);
}
So I am trying to send the "id" of a selected row in datatable in javascript to a php page so I could delete it from database.
var ids = $.map(table.rows('.selected').data(), function (item) {
return item[0] });
the variable "ids" is sent by post method
$.post( "deleterow.php", { v1: ids });
but it didn't worked so i try to see the response from post method and it says
"notice array to string conversion in C on line ... "
the line is of php page where i am writing the delete query
$id = $_POST["v1"];
$query = "DELETE FROM `package` WHERE `id` = '$id'";
The whole php page works fine when trying with other values.
Because you send an array here:
$.post( "deleterow.php", { v1: ids });
so v1 contains an array of elements. But in your php code you treat it as a single element:
$id = $_POST["v1"];
Hence the notice array to string conversion.
If you send an array of elements, you have to get it as an array and treat is as an array. To create a correct SQL string you should append each ID, like this:
$ids = json_decode($_POST["v1"]);
$query = "DELETE FROM `package` WHERE";
$first = true;
foreach ($ids as $id) {
if ($first) {
$first = false;
} else {
$query += " OR";
}
$query += " `id` = '$id'"
}
This way you loop the array and append a id = ID for each array element.
Now, this is important, this code is prone to SQL injection, a really bad security problem. Read this to get more info about this: How can I prevent SQL injection in PHP?
A JSON encoded array is passed from PHP to an HTML document. It is not at all clear how to deconstruct that array into javascript-usable pieces. For example, consider the following HTML:
<div id="options">{"foo":[{"id":1},{"id":3}], "bar":[{"id":2},{"id":4}]}</div>
The only a priori known element of this array is that the key id exists. The indices, I know, can be found with
var data = JSON.parse($("#options").text());
$.each(data, function(index) {
// index will be foo & bar
});
The use case is to use the index and id to add an attribute to elements in a document. I have not yet stumbled upon the technique to return the ids associated with each index. How best can that be done?
Edit - a clarification of the use case - the long story
I want to re-enable some options on a form based on properties of an entity (in a Symfony application). Disabled options cannot be modified, but are also not not persisted - their values are set to null. I've built a service to determine the option elements that are disabled and send those elements to the form document as a JSON object. I'm assuming for now that the specific options are not known until the form is created. In the example above, foo & bar represent possible options, and the ids correspond to the option. For example, a Household entity might have Reason options selected but disabled of "Low wages" (id = 3). This would show up in as ...id="options">{"reasons":[{"id":3}]}<.... I would the use this information to remove the disabled="disabled" attribute from the set of checkboxes for the Reason, id=3 (i.e., id="household_reasons_3") field. I hope this makes sense.
Edit #2, by request - the PHP code creating the object.
The result of getMetatData() appears in the document at #options. From the above edit, the Household entity is $object.
public function getMetaData($object) {
$data = array();
$className = get_class($object);
$metaData = $this->em->getClassMetadata($className);
foreach ($metaData->associationMappings as $field => $mapping) {
if (8 === $mapping['type']) {
$data[$field] = $this->extractOptions($object, $field);
}
}
return json_encode($data);
}
private function extractOptions($object, $field) {
$data = [];
$method = 'get' . ucfirst($field);
$itemName = substr($field, 0, -1);
$getter = 'get' . ucfirst($itemName);
$entity = $object->$method();
foreach ($entity as $item) {
if (method_exists($item, 'getEnabled') && false === $item->getEnabled()) {
$data[] = ['id' => $item->getId()];
}
}
return $data;
}
Long before the infinite monkey limit was reached I stumbled on a method to create the results I was looking for. My thanks go out to all who pushed for clarifications. So, for the object
{"foo":[{"id":1},{"id":3}], "bar":[{"id":2},{"id":4}]}
the script
var data = JSON.parse($("#options").text());
var i = 0
var output = [];
$.each(data, function(index, item) {
$.each(item, function(k, v) {
output[i] = "household_" + index + "_" + v.id;
i++;
});
});
output;
produces this:
["household_foo_1", "household_foo_3", "household_bar_2", "household_bar_4"]
I get the strings I need; I can take it from here.
I tried to build an ajax search bar. It works fine with a single keyword but I can't manage to make it work with 2 keywords...
I was thinking about parsing the data in the input field but my knowledge is limited and I didn't manage to find the solution.
Any ideas?
In my main.js I get the data from the input like this:
var kwVal = $(this).val();
if (kwVal.length < 3){
$(".clothes-container").html("");
}
else {
$.ajax({
"url": "ajax/getclothes.php",
"type": "GET",
"data": {
"kw": kwVal
}
})
And this is my sql request
$sql = "SELECT title, description, picture
FROM outfit
WHERE type LIKE :keyword OR
color LIKE :keyword OR
brand LIKE :keyword OR
material LIKE :keyword";
Thanks a lot.
Something like this? Of course, all the SQL literals and strings must be properly escaped (especially the $keyword).
// keywords extracted from user's input
$keywords = array('blue', 'jeans');
// columns, that You want to match against
$columns = array('type', 'color', 'brand', 'material');
// we build the condition for each keyword
$word_conditions = array();
foreach ($keywords as $keyword) {
$conditions = array();
foreach ($columns as $column)
$conditions[] = $column.' LIKE \'%'.$keyword.'%\'';
$word_conditions[] = '('.implode(' OR ', $conditions).')';
}
// we build the query, that requires every item to have all the keywords
$query = 'SELECT * FROM ... WHERE '.implode(' AND ', $word_conditions);
Suppose your keywords are saperated by 'Space' like "ABC DEF GEH".
than on server you can do is,
$keywords = explode(" ", $_POST['data']); //Make it array;
$string = implode(",", $keywords);
$sql = "SELECT title, description, picture
FROM outfit
WHERE type in (".$string.") OR
color in (".$string.") OR
brand in (".$string.") OR
material in (".$string.")";
I have 3 dropdowns with list of places that I wanted to sort in ascending order. The first dropdown of places is sorted using codeigniter active record order_by function and the places were successfully sorted in ascending order.However,using onchange javascript function,when I choose a place in the first dropdown then populate the second dropdown of places excluding the place I have chosen in the first dropdown, the places returned were not sorted in ascending order even though there is order_by function I have in my query. I suspect that this is because of the json formatted data returned in onchange. Here are my codes. Thanks for the help.
This code sorts the data properly in ascending order
function get_dropdown_barangay(){
$query = $this->db->select('ID,brgy_name')
->from('tbl_barangay')
->order_by('brgy_name','asc')
->get()
->result_array();
$dropdown = array('0'=>'Select Barangay');
foreach($query as $value){
$dropdown[$value['ID']] = $value['brgy_name'];
}
return $dropdown;
}
Output Image:
Onchange code, the returned places are not sorted in ascending order
$('#brgy_id_1').change(function(){
var brgy_id = $("#brgy_id_1").val();
alert(brgy_id);
var data_val = {'brgy_id':brgy_id};
$.ajax({
type: "POST",
url:"<?php echo base_url();?>admin/get_barangay_list",
data:data_val,
dataType:'json',
success: function(data)
{
$('#brgy_id_2').empty();
$.each(data,function(id,val)
{
var opt = $('<option />'); // here we're creating a new select option for each group
opt.val(id);
opt.text(val);
$('#brgy_id_2').append(opt);
});
}
});
}); //end change
admin.php
function get_barangay_list(){
if(isset($_POST['brgy_id2'])){
$brgy_array_id = array('0'=>$_POST['brgy_id'],'1'=>$_POST['brgy_id2']);
} else{
$brgy_array_id = array('0'=>$_POST['brgy_id']);
}
$result=$this->core_model->get_barangay_list($brgy_array_id);
$this->output->set_header('Content-Type: application/json',true);
echo json_encode($result);
}
model.php
function get_barangay_list($brgy_array_id){
$query = $this->db->select('ID,brgy_name')
->from('tbl_barangay')
->where_not_in('ID',$brgy_array_id)
->order_by('brgy_name','asc')
->get()
->result_array();
$dropdown = array('0'=>'Select Barangay');
foreach($query as $value){
$dropdown[$value['ID']] = $value['brgy_name'];
}
return $dropdown;
}
Output Image showing data are not sorted in ascending order
One way to implement kinghfb's comment :
On the server side : build an array
$dropdown = array();
$dropdown[] = array('id' => 0, 'label' => 'Select city');
for ($query as $value) {
$dropdown[] = array('id' => $value['ID'], 'label' => $value['brgy_name']);
}
On the client side (javascript) : change your loop code :
$.each(data,function(id,val) {
var opt = $('<option />'); // here we're creating a new select option for each group
opt.val(val.id);
opt.text(val.label);
$('#brgy_id_2').append(opt);
});
You are losing your order here, because you are setting new keys (problem is described here Change array key without changing order).
So you have to keep the keys and due this you have to change the js part as well, because you can´t access the data using key-value anymore.
function get_dropdown_barangay(){
$query = $this->db->select('ID,brgy_name')
->from('tbl_barangay')
->order_by('brgy_name','asc')
->get()
->result_array();
$dropdown = array('0'=>'Select Barangay');
foreach($query as $value){
$dropdown[] = array("id" => $value["ID"], "name" => $value['brgy_name']); // setting new value and keep an numeric key which represents the order
}
return $dropdown;
}
and the js has to be like:
$('#brgy_id_1').change(function(){
var brgy_id = $("#brgy_id_1").val();
alert(brgy_id);
var data_val = {'brgy_id':brgy_id};
$.ajax({
type: "POST",
url:"<?php echo base_url();?>admin/get_barangay_list",
data:data_val,
dataType:'json',
success: function(data)
{
$('#brgy_id_2').empty();
$.each(data,function(object)
{
var opt = $('<option />'); // here we're creating a new select option for each group
opt.val(object.id);
opt.text(object.value);
$('#brgy_id_2').append(opt);
});
}
});
});
I had highlighted the changes, but I don´t know hot to use bold in code at SO....
You could sort your JSON using underscore
Just pass in your JSON and a sort function. Like so:
var cityJSON = [{city: 'San Vinente'}, {city: 'Pequnio'}, {city: 'Pili Drive'}, {city: 'Jc Aquino'}, {city: 'Banza'}];
console.log(cityJSON); // unsorted
cityJSON = _.sortBy(cityJSON, function(item){return item.city});
console.log(cityJSON); // sorted