I'm building a function in Laravel along with the datatables and ajax. I have a fully working page with multiple functions that return data into the databale however one of the functions doesn't like to search properly and doesn't return any data into the table.
I have a datapicker with the following code:
<div class=" input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-clock"></i></span>
</div>
<input class="form-control" type="text" data-plugin-datepicker id="lastLogged" name="lastLogged" placeholder="Owner has not logged in since:">
</div>
My search button is called: search_data
My ajax call is as followed:
<script>
$(document).on("click", "#search_data", function (e) {
e.preventDefault();
$(this).html("<i class='fa fa-circle-o-notch fa-spin'></i>");
})
$.ajax({
url: "/search/user",
type: "POST",
dataType: "json",
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
data: {
loginUser : $('#lastLogged').val()
}
})
.done(function(data) {
console.log(data);
table.ajax.reload();
$('#search_data').html('<i class="fas fa-search"></i>');
})
.fail(function(data) {
console.log(data);
$('#search_data').html('<i class="fas fa-search"></i>');
});
});
My PHP controller:
public function Building(Request $request)
{
if ($request->ajax())
{
$buildings = building::with('ownerinfo');
$data = array();
$totalData = building::count();
$totalFiltered = $totalData;
$start = $request->input('start');
$order = 'id';
$dir = $request->input('order.0.dir');
// Other if statements here with functions
if(isset($request->login))
{
$date = date("Y-m-d H:i:s",strtotime($request->login));
$users = Users::where('last_login_in', '<=', $date)->get();
foreach($users as $user) {
$buildings = $buildings->where('owner', $user->id);
}
}
$buildings = $buildings->get();
if(!empty($buildings))
{
foreach ($building as $building)
{
$nestedData['id'] = $building->id;
$nestedData['name'] = $building->buildingName;
$nestedData['view'] = '<a class="button is-small full-width is-hovered" href="/view/building/' . $building->id . '">View</a>';
$data[] = $nestedData;
}
$json_data = array(
"data" => $data,
"draw" => intval($request->input('draw')),
"recordsTotal" => intval($totalData),
"recordsFiltered" => intval($totalFiltered)
);
return json_encode($json_data);
}
}
}
This keeps on returning no data at all. I am using 1 January 2019 from the datepicker to search, it has the value: 2019-01-01 00:00:00 and the data of one of the users in the database has 2018-08-20 07:11:34. I checked the queries with var_dumps and it returns the correct users, however it doesn't show any results in the buildings datatable.
The idea behind this is to let an administrator select a specific date, the database runs the search and returns buildings of users that have not logged in since the selected date.
What am I doing wrong?
The $users return the correct users but the $buildings are empty?
Try to use a hasMany relation between the User and Building it will be a better solution than this:
foreach($users as $user) {
$buildings = $buildings->where('owner', $user->id);
}
Related
I'm working with Lumen, Vuejs and Axios. Users who are signed in can post something, and other users can like and comment on it. What I want to do is to make it obvious that someone liked the post. But I'm not able to switch the button after someone liked it.
This is my Vuejs Code:
<button class="btn btn-light" #click="likes(item.id)"><i class="far fa-heart"></i></button>
<button class="btn btn-light" #click="likes(item.id)"><i class="fas fa-heart"></i></button>
likes(id){
const axiosConfig = {
headers: {
Authorization: localStorage.getItem('token')
}
};
const postData = {
posts_id: id,
likes: true
};
axios.post('http://lumen.local/like', postData, axiosConfig)
.then(response => {
this.getPosts();
})
.catch(error => {
console.log(error)
});
},
And this is my lumen Code:
$post_query = Posts::with('comments')
->with('comments.owner')
->with('likes.isLiked')
->withCount('likes')
->where('user_id', $user->id)
->orderBy('id', 'desc')
->limit($request->limit)
->get();
I tried to make another function where I can get the user_id of the logged in user, so I can change the button with vue-if
public function checkLike(Request $request)
{
$user_name= $request->username;
$user = User::where('username', $user_name)->first();
$post_id = $request->posts_id;
$post = Posts::find($post_id);
$like = Likes::where('posts_id', $post_id)
->where('user_id', $user->id)
->get();
if(count($like) == 0){
return response()->json('no likes');
} else{
return response()->json($like);
}
}
It worked in postman, but I was not able to implement it in Vuejs, because I could not get the user_id without a v-for. So I thought I should get the user_id in the posts_query but I couldn't do it.
Do you have any ideas?
Based on the details you gave me in the comments, I can suggest you to try this.
(I have not tested it yet so ther might be some syntax errors)
In your Vue script part :
data() {
return {
currentUserId: null,
items: null,
}
},
mounted() {
this.getCurrentUserId()
this.getPosts()
},
methods: {
getCurrentUserId() {
// returns the ID of the current user
},
likes() {
// your method
},
getPosts() {
axios.get(MY_URL)
.then (res => {
const posts = res.data
/*
* creates a new array that contains each post + a boolean that indicates if
* the current user has liked or not.
*/
this.items = posts.map(post => ({
...post,
liked: this.isPostLiked(post.likes)
}))
})
.catch (err => {
console.error(err)
})
},
/*
* Not sure if your likes array is composed like this.
* This method looks for the currentUserId inside the
* likes array passed as an argument. Returns true when
* it finds one, otherwise returns false.
*/
isPostLiked(likesArray) {
likesArray.forEach(like => {
if (like.user_id === this.currentUserId) {
return true
}
}
return false
}
},
Now we should obtain an array of objects that contains each post with its liked state.
Then you only have to loop through it with a v-for in your template:
<div v-if="items !== null" class="like-buttons">
<button
v-for="(item, index) in items"
:key="'item_' + index"
class="btn btn-light"
#click="likes(item.id)"
>
<i v-if="item.liked === true" class="far fa-heart" />
<i v-else class="fas fa-heart" />
</button>
</div>
I have items and for every item there are related items, so when I open the homepage it shows all item, when I want to click on any item, ajax will pass this item id to controller to get the related items for this item, the problem is I want to show the related item in a modal dialogue, the modal dialogue now show all related items to all items not to the current item.
I think the problem is because the include of modal in the homepage which has the foreach!, hope you can help me in solving this issue
route
Route::get('/',['as'=>'showItems','uses'=>'HomeController#getItem']);
Route::get('Get_relateditem',['as'=>'Get_relateditem','uses'=>'HomeController#getItem']);
ajax
$(function(){
$('.Item_root').on("click", function () {
var item_id = $(this).data('id');
$.ajax({
type:'get',
url: '/',
data: {
'_token': $('input[name=_token]').val(),
'item_id':item_id,
},
success:function(data){}
});
});
});
controller
public function getItem(Request $request)
{
$currentitemid =$request->item_id;
$ritems = Relateditem::orderBy('id', 'asc')->where('ritemf_id','LIKE','%'.$currentitemid.'%')->with('items')->get()->groupBy('ritemf_id');
$items = Item::orderBy('category_id', 'asc')->with('category')->get()->groupBy('category_id');
$categories = Category::orderBy('category_id', 'asc')->get();
return view('home')->with('items',$items)->with('categories',$categories)->with('ritems',$ritems);
}
}
modal
#foreach($ritems as $item_id => $realtedItems)
#foreach($realtedItems as $ritem)
<div class="SuggestedItem_container">
<label color="red" class="Checker_root Checker_red Checker_left">
<input type="checkbox" class="Checker_input" value="on">
<div class="SuggestedItem_nameContainer">
<div>
<span class="SuggestedItem_name">{{$ritem->riteml_id}}</span>
<span class="SuggestedItem_price styles_small styles_base styles_spacing-base">+$3.95</span></div></div>
<div class="SuggestedItem_description styles_small styles_base styles_spacing-base">
<span class="SuggestedItem_category styles_bold">Appetizers</span>
<span> · Edamame soybean pods harvested right before the beans begin to harden are lightly boiled and seasoned with sea salt.</span>
</div>
</label>
</div>
#endforeach
#endforeach
Modify routes:
Route::get('/','HomeController#getItem');
Route::get('/get_related_items/{id}','HomeController#getRelatedItems');
modify getItem to get only the items and categories:
public function getItem(Request $request)
{
$items = Item::orderBy('category_id', 'asc')
->with('category')->get()
->groupBy('category_id');
$categories = Category::orderBy('category_id', 'asc')->get();
return view('home',['items' => $items,'categories' => $categories]);
}
get related items for a single item id:
public function getRelatedItems(Request $request, $id)
{
$ritems = Relateditem::orderBy('id', 'asc')
->where('ritemf_id',$id)
->with('items')
->get()
->groupBy('ritemf_id');
return response()->json($ritems);
}
now for the js part:
$(function(){
$('.Item_root').on("click", function () {
var item_id = $(this).data('id');
$.ajax({
type:'get',
url: '/get_related_items/' + item_id,
data: {
'_token': $('input[name=_token]').val()
},
success:function(data){
if(data && data.length){
var con_el = $('.SuggestedItem_container');
for(var i = 0; i < data.length;i++){
var related_item_el = "<div class='related_item'><p>" + data[i].id + "</p></div>"
con_el.append(related_item_el);
}
}else{
console.log('no related items found');
}
}
});
});
});
this will insert all the related items inside the SuggestedItem_container
i didn't write the view template cuz that part is easy, and note that i only included the related item id as example cuz i don't know what fields the item has.
i hope this helps you
I have this simple code that display only 2 column (step and feedback)
so whenever the "feedback" has submited or post like in my controller below and the "step" column would count like $step+=1 or update with query update my_table set step = step + 1 where id = $user_id ,,which is if "feedback" has submited the "step" column always increment ++ .
controllers/Person.php
public function ajax_update()
{
$data = array(
//'step' => $this->input->post('step'),
'feedback' => $this->input->post('feedback'),
);
$this->person->update(array('user_id' => $this->input->post('user_id')), $data);
echo json_encode(["status" => TRUE]);
}
Model/Person_model.php
public function update($where, $data)
{
$this->db->update($this->table, $data, $where);
return $this->db->affected_rows();
}
Views/person_view.php
<div class="form-group">
<label class="control-label col-md-3">kcp naem</label>
<div class="col-md-9">
<input name="feedback" placeholder="status" class="form-control" type="text">
<span class="help-block"></span>
</div>
</div>
<button type="button" id="btnSave" onclick="save()" class="btn btn-primary">Save</button>
plus jquery ajax for button save()
function save()
{
$('#btnSave').text('saving...'); //change button text
$('#btnSave').attr('disabled',true); //set button disable
var url;
url = "<?php echo site_url('person/ajax_update')?>";
// ajax adding data to database
$.ajax({
url : url,
type: "POST",
data: $('#form').serialize(),
dataType: "JSON",
success: function(data)
});
}
maybe we should just focus on the controller and model .
Some assistance would be great on how to setup the update.
Thankyou
You can do this in qb using the following method:
$this->db->set('step', 'step+1', FALSE);
$this->db->where('user_id', $user_id);
$this->db->update('tablename');
https://www.codeigniter.com/userguide3/database/query_builder.html#updating-data
// controller
public function ajax_update() {
$feedback = $this->input->post('feedback');
$uid = $this->input->post('user_id');
if (!is_null($feedback) && !is_null($uid)) {
// only increment: "whenever the "feedback" has submited or post"
$this->person->update_feedback($uid, $feedback);
echo json_encode(["status" => TRUE]);
} else {
echo json_encode(['status' => FALSE]); //?
}
}
// model
public function update_feedback($user_id, $feedback) {
$this->db->set('step', 'step+1', FALSE);
$this->db->set('feedback', $feedback);
$this->db->where('user_id', $user_id);
$this->db->update($this->table);
return $this->db->affected_rows();
}
Took a few snippets from the different areas I worked on the code. I tried copying and altering the code to delete one product. Currently there is no response when clicking the delete all button I created.
Service
public function deleteAllProductsByVendorId($vendorId)
{
$this->productRepository->deleteAllProductsByVendorId($vendorId);
}
Repository
public function deleteAllProductsByVendorId($vendorId)
{
// #Todo: revisit this at a later date and determine if the vendor id is actually required
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->delete("Thinkfasttoys\Mapwatch\Entity\Product","p")
->andWhere($qb->expr()->eq('p.vendor_id', ':vendor_id'))
->setParameter(':vendor_id', $vendorId)
->getQuery()
->getResult();
}
Controller
/**
* #Route("/admin/vendor/{vendorId}/product/deleteAll", name="admin_vendor_product_delete_all_ajax", defaults={"vendorId"=""})
* #Route("/admin/vendor/{vendorId}/product/deleteAll", name="admin_vendor_product_delete_all"))
* #Secure(roles="ROLE_ADMIN")
*/
public function deleteAllProductForVendorAction($vendorId)
{
$request = $this->container->get('request');
if ($id == '') {
$this->get('session')->getFlashBag()->add('notice-error', 'Vendor Id must be supplied!');
return $this->redirect($this->generateUrl('admin_vendors_list'));
}
$vendorService = $this->get('Thinkfasttoys.MapWatch.Vendors');
$vendor = $vendorService->getProfileById($id);
if (!$vendor) {
$this->get('session')->getFlashBag()->add('notice-error', 'Vendor does not exist!');
return $this->redirect($this->generateUrl('admin_vendors_list'));
}
$user = $vendor->getUser();
if (!$user) {
$this->get('session')->getFlashBag()->add('notice-error', 'User for this Vendor does not exist!');
return $this->redirect($this->generateUrl('admin_vendors_list'));
}
if ($request->isXmlHttpRequest()) {
$productService = $this->get('Thinkfasttoys.MapWatch.Products');
$productService->deleteAllProductsByVendorId($vendorId);
return new Response(json_encode(array('status' => 'ok')),200,array('Content-Type'=>'application/json'));//make sure it has the correct content type
} else {
return $this->redirect($this->generateUrl('admin_vendor_products_edit', array('id' => $vendorId)));
}
}
View
<div class="btn-toolbar">
<a data-toggle="modal" href="#importProductsModal" id="importProducts" class="btn btn-danger">Import Products</a>
<a data-toggle="modal" href="#productModal" id="addProduct" class="btn btn-primary pull-right">Add New Product</a>
<a class="btn btn-danger pull-right" id="deleteall">Delete All</a>
</div>
Created Var deletePathAll
var vendorId = {{ vendorId }};
var getPath = '{{ path('admin_vendor_product_get_ajax', { id: vendorId } ) }}';
var editPath = '{{ path('admin_vendor_product_edit', { id: vendorId } ) }}';
var deletePath = '{{ path('admin_vendor_product_delete_ajax', { id: vendorId } ) }}';
var deletePathAll = '{{ path('admin_vendor_product_delete_all_ajax', { vendorId: vendorId } ) }}';
JS
$('#deleteall').on('click', 'table#products', function(e){
e.preventDefault();
var aData = $('#products').dataTable().fnGetData(aPos);
row.find('a').attr('disabled', true);
var rowId = aData['id'];
$.ajax({
type: "POST",
url: deletePathAll,
success: function(data) {
oTable.fnReloadAjax();
},
error: function(data) {
row.find('a').attr('disabled', false);
}
});
});
Pretty sure your Product entity doesn't have the property vendor_id but vendor.
In this case this should correct the issue
->andWhere($qb->expr()->eq('p.vendor_id', ':vendor_id'))
should be replaced with
->andWhere($qb->expr()->eq('p.vendor', ':vendor_id'))
I am using code igniter, google charts with php and MySQL to display charts. It works using fixed query. I am trying to add a dropdown to display the chart based on the option (sql column "status") selected
Here is what I have so far. How can I modify this to accept dropdown values?
model.php
public function get_chart_data()
{
$query = $this->db->get($this->db_mgmt);
$this->db->select('rating, COUNT(rating) AS Count');
$this->db->from('db_mgmt');
$this->db->where('status =', $status);
$this->db->group_by('rating');
$query = $this->db->get();
$results['chart'] = $query->result();
}
controller.php
$this->load->model('model', 'chart');
public function index() {
$results = $this->chart->get_chart_data();
$data['chart'] = $results['chart'];
$this->load->view('index.php', $data);
}
view.php
<?php
foreach ($chart as $object) {
$open_all[] = "['".$object->rating."', ".$object->Count."]";
}
?>
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart_open);
function drawChart_open() {
// Create the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Rating');
data.addColumn('number', 'Count');
data.addRows([
<?php echo implode(",", $open_all);?>
]);
var options = {
pieSliceText: 'value-and-percentage',
};
var chart = new google.visualization.PieChart(document.getElementById('open_div'));
chart.draw(data, options);
}
<div id="open_div" class="chart"></div>
Thanks in advance!
UPDATE:
I have tried the below using ajax but it doesn't seem to work. I am definitely sure I am doing something wrong here but not sure where. Using Inspect in chrome also doesn't give any errors.
model.php
public function fetch_result($status)
{
$query = $this->db->get($this->db_mgmt);
$this->db->select('rating, COUNT(status) AS Status_Count');
$this->db->from('db__mgmt');
$this->db->where('status =', $status);
$this->db->group_by('rating');
$query = $this->db->get();
return $query;
}
controller.php
$this->load->model('model', 'chart');
public function mychart() {
if(!empty($_POST["val"])) {
$val=$_POST["val"];
$result_new=$this->chart->fetch_result($val);
$array = array();
$cols = array();
$rows = array();
$cols[] = array("id"=>"","label"=>" Rating","pattern"=>"","type"=>"string");
$cols[] = array("id"=>"","label"=>"Count","pattern"=>"","type"=>"number");
foreach ($result_new as $object) {
$rows[] = array("c"=>array(array("v"=>$object->risk_rating,"f"=>null),array("v"=>(int)$object->Status_Count,"f"=>null)));
}
$array = array("cols"=>$cols,"rows"=>$rows);
echo json_encode($array);
}
}
view.php
function drawChart_open_all(num) {
var PieChartData = $.ajax({
type: "POST",
url: "<?php echo base_url(); ?>" + "dashboard/chart/mychart",
data:'val='+num,
dataType:"json"
}).responseText;
alert(PieChartData);
// Create the data table.
var data = new google.visualization.DataTable(PieChartData);
var options = {
pieSliceText: 'value-and-percentage',
};
var chart = new google.visualization.PieChart(document.getElementById('open_new'));
chart.draw(data, options);
}
<div><span> <b>Pie Chart<br /><br /></span></div>
<form>
<select name="status" onchange="drawChart_open_all(this.value)">
<option value="WIP">WIP</option>
<option value="Close">Close</option>
</select>
</form>
<div id="open_new" class="chart"></div>
Thanks in advance!!
I think the easiest thing would be to send a GET request with the <option> value
First, go back to your first version.
Next, send the value in your onchange event
function drawChart_open_all(num) {
location = "<?php echo base_url(); ?>" + "dashboard/chart/mychart?option=" + num;
}
Then in Model --
get_chart_data()
you should be able to access the value with --
$_GET['option']
use that to modify your query
here's an old answer with similar concept -- difference is it uses POST vs. GET
and a <form> with a <input type="submit"> button to send the request
How to pass JavaScript variables to PHP?
I managed to figure out what the problem was and used ajax in the end. #WhiteHat solution led to also in the right direction. Thanks for that!
model.php
public function fetch_result($status)
{
$query = $this->db->get($this->db_mgmt);
$this->db->select('rating, COUNT(status) AS status_count');
$this->db->from('db_mgmt');
$this->db->where('status =', $status);
$this->db->group_by('rating');
$query = $this->db->get();
$results_new = $query->result(); // <-- Forgot to add this!
return $results_new;
}
controller.php
$this->load->model('model', 'chart');
public function mychart() {
if(!empty($_POST['option'])) {
$val = $_POST['option'];
$result_new=$this->chart->fetch_result($val);
$array = array();
$cols = array();
$rows = array();
$cols[] = array("id"=>"","label"=>" Rating","pattern"=>"","type"=>"string");
$cols[] = array("id"=>"","label"=>"Count","pattern"=>"","type"=>"number");
foreach ($result_new as $object) {
$rows[] = array("c"=>array(array("v"=>(string)$object->rating),array("v"=>(int)$object->status_count)));
}
$array = array("cols"=>$cols,"rows"=>$rows);
echo json_encode($array);
}
}
view.php
function drawChart_open_all(status) {
var PieChartData = $.ajax({
type: 'POST',
url: "<?php echo base_url(); ?>" + "dashboard/chart/mychart",
data: { 'option':status }, // <-- kept as option instead of val
dataType:"json",
global: false, // <-- Added
async:false, // <-- Added
success: function(data){ // <-- Added
return data; // <-- Added
},
error: function(xhr, textStatus, error){
console.log(xhr.statusText);
console.log(textStatus);
console.log(error);
}
}).responseText;
// Create the data table.
var data = new google.visualization.DataTable(PieChartData);
var options = { pieSliceText: 'value-and-percentage', };
var chart = new google.visualization.PieChart(document.getElementById('open_new'));
chart.draw(data, options);
}
<div><span> <b>Pie Chart<br /><br /></span></div>
<form>
<select name="status" onchange="drawChart_open_all(this.value)">
<option value="WIP">WIP</option>
<option value="Close">Close</option>
</select>
</form>
<div id="open_new" class="chart"></div>