Laravel get static array of random numbers and use it in pagination - php

I am developing an application in Laravel 5.5 ... it is kind of a testing system...
What I want to achieve is that when user clicks on RUN TEST, it will generate random set of questions (let's say 5) then I want them to be served to the user one by one ... I did a pagination in AJAX so the questions can be served by pages .. and after that user will click on SUBMIT which will submit the form ..
I am able to get the random list of questions
In the TestController within the method "exec_test" is
// get random id
$q_id = Question::select('id')
->where('test_id','=',$test_id)
//->where('id','=',114)
->orderByRaw("RAND()")
->take(3)
->get();
This will get 3 random ID's for that specific test ...
Following code in the same method is
// get data
$data = array (
'tests' => Test::select('id','code','name',DB::raw('duration_m * 60 as duration_m'),'questions','passing_score')
->where('id','=',$test_id)
->orderBy('code', 'asc')
->paginate($this->page_limit),
'test_questions' => Question::select('questions.id','questions.question_header','questions.question_detail_local_url')
->join('tests','tests.id','=','questions.test_id')
->where('test_id','=',$test_id)
->whereIn('questions.id',$q_id)
//->orderByRaw("RAND()")
//->take(4)
->paginate($this->test_question_page_limit),
'test_answers' => Answer::select('id','answer_text_cleaned')
->whereIn('question_id',$q_id)
->get()
);
// check for ajax requests
if ($request->ajax()) {
return view('/custom/test/run_test_quests', $data)->render();
}
return view('/custom/test/run_test_info',$data);
But I don't know how can I make that first query static and to make it served one by one (per page) to the user .. so he can go trough all questions
Do you have any suggestions please?

while paginating the first page would be 1, it would be specified in the url too.
try this:
if($request->input('page') ==1)
{
//code for first page
}else{
//code for random
}
this is just a suggestion. Sorry if I understood the question wrong

Related

Laravel collection not saving added data

I'm building a Laravel 9x application where i will need to populate some pages with the google places API.
Reading at the ToS of Google Places, i can only store in my db, for at most 30 days, the place_id.
Now, I'm facing an issue; I have a restaurants.index blade page where I'm showing in a table all the records from the restaurants table.
The issue is that i need to show in each table row the name of the restaurant that i don't have in my db table but i need to fetch it from Google Places Api.
So far, in my RestaurantsController I have done the following :
public function index()
{
$getAllRecords = Restaurant::all();
$google_places_api = new PlacesApi(env('GOOGLE_MAPS_API_KEY'));
$restaurants = new Collection();
foreach($getAllRecords as $restaurant){
$response= $google_places_api->placeDetails($restaurant->google_place_id);
$restaurant['name'] = $response['result']['name'];
$restaurants->prepend($restaurant);
}
dd($restaurants);//When dd here, the collection shows correctly the added value.
$restaurants->paginate(8);
$categories = Category::where('type', 'Restaurant')->cursor();
return view('tenant.restaurants.index', compact('categories', 'restaurants'));
}
And it seems to work pretty well if I dd($restaurants) inside the RestaurantsController as you can see from the picture below :
But when i try to #dd($restaurants) from the restaurants.index page, the added name is completely disappeared as you can see from the picture below :
It's now about a whole day that I'm tryng to understand why this behavior happen, is there anybody who has an idea of what is happening?
Thank you

Reordering Collections in Laravel

I am working on a Laravel project where people can post tiles on a page then click a button to move them up or down on the page. Currently I have a table setup for tiles like so:
$table->string('tile_name');
$table->text('tile_rules');
$table->integer('tile_order');
Then on the frontend I have a button should either move the tile up or down depending which arrow you press. For my up function I thought I could just take the current order from the Tile and Add which does work in its simplest form, but my question is what is the best approach for looping back through and updating all the other tiles on the page? I think it is also fair to say there will never likely be more than ten tiles on a page that would need reordering.
I was thinking this must be do able with a foreach loop:
$currentOrder = $currentTile->tile_order;
foreach($Tiles as $tile) {
Tiles::whereKey($tile->id)->update(['tile_order' => ++$order]);
}
but what I missing is how do I tell it to start at a particular tile and only update the tiles above or below it depending on whether or not I am moving it up or moving it down?
If someone could push me in the right direction that would be greatly appreciated!
I debated handling on the frontend and allowing the user to save the order when they had completed it, but instead I created an Up and Down function that would find the item above or below it and just switch the order integer with it. This seems to work better than looping through everything and updating the count.
if ($tileAbove == 0) {
session()->flash('message', 'This Tile can not be moved any higher');
} else {
//Update the current Tile to the new order and tileAbove to the old order
$tileAboveObj = $positionTiles->filter(function($item) use ($tileAbove) {
return $item->tile_order == $tileAbove;
})->first();
Tiles::whereKey($currentTile->id)->update(['tile_order' => $tileAbove]);
Tiles::whereKey($tileAboveObj->id)->update(['tile_order' => $currentTileOrder]);
}
with $tileAbove just being the current tile order subtracted by 1.

Twilio Paging Information

Im using the Twilio PHP Sdk.
$AccountSid = env('TWILIO_SID');
$AuthToken = env('TWILIO_TOKEN');
$this->twi = new TwilioClient($AccountSid, $AuthToken );
And Im retrieving call logs like so.
$calls = $this->twi->calls->read(["to" => "+".$number->number], 15);
This is fine, and is returning 15 records of the latest calls.
But how do I access paging information such as how many total records are available, and how many pages are available to view. So that I can display some sort of pagination on my page??
I tried just accessing the Calls.json object, via CURL without using the SDK, like this...
$url = "https://api.twilio.com/2010-04-01/Accounts/".$AccountSid."/Calls.json?PageSize=15";
And that gave me a nice JSON object, with some paging info such as next_page_uri and previous_page_uri.
[previous_page_uri] =>/2010-04-01/Accounts/AC##########/Calls.json?PageSize=15&Page=0
[page_size] => 15
[start] => 0
[next_page_uri] => /2010-04-01/Accounts/AC##########/Calls.jsonPageSize=15&Page=1&PageToken=PACA27b63143f18c458f2abd35ef90753e5a
[page] => 0
But still, no totals such as total records, or total pages in the query??? So I cant display a nice bar of pagination at the bottom of my table, to show how many actual pages there are?
This seems dumb.
Is there no way to get this information?? Without actually storing the calls individually in my own database, so I can provide this manually?
Also.....one other question (assuming I cant retrieve that information)
I still want to be able to navigate from page to page, via the SDK instead of CURL requests. So....how do I pass the page number to the Twilio SDK? Ive tried...
$calls = $this->twi->calls->read(["To" => "+".$number->number,"Page"=>22], 15);
But it still just returns the first page. So how do I paginate these records via the SDK??
I am not sure about total pages, but for pagination i have used TWILIO PHP SDK's function,
Here how it will work,
//this will fetch first 10 calls
$calls = $twilio->calls->page([], 10, \Twilio\Values::NONE, 0);
//then you just need to call 2 methods for next and previous page
$nextPageData = $calls->nextPage(); //this will return data of next page
$previousPageData = $calls->previousPage(); // this will return data of previous page
// to check if current page has valid data
if(!$nextPageData->valid()){
//Invalid page
}
This is what i used for pagination on my project.

Laravel ajax pagination set page

In my laravel project i use hashes in the url to keep track on selections of the user, so they are able to go back to a filter result. I dont want the page to refresh so I DONT UPDATE THE URL with Page=someid (except the hash) the response of the server looks like.
if ($request->ajax()) {
//The page I want to select posted with ajax
$paginaId = $request->input('page');
//some query like
$query = Table::Query();
//get 9 items
$rooms= $query->paginate(9);
//Return the response
return Response::json(View::make('front.rooms.render', array('rooms' => $rooms))->render());
}
The $paginaId represents the selected pagination page. Everything works fine except one part. I cant set the current page of the pagination. I viewed the documentation but couldn't find any solutions.
Try the following:
$rooms = $query->paginate(9, ['*'], 'page', $paginaId);
In this case you can set $paginaId manualy

Codeigniter MVC. Going from summary information on one View to detailed Information in another View

Ok, so I have views that provide summary information regarding user entries. Users can create entries for different "programs" (categories more or less) and different "vendors" etc. So the Program View will show some summary information for each program as well as how many entries each program has. The Vendor View will show summary information about each vendor as well as how many entries exist for each vendor.
How do I code a button that users can click to take them to a view of entries for that program or vendor. I'm getting confused because I don't think you are supposed to access a controller from a view but I want the user to be able to see summary information in different ways and then click to get to the detailed data.
So the Program View might look like:
Page Title: All Programs
Program: Program 1
Start Date: 5/5/13
End Date: 5/5/14
Button: |Click to view entries|
Program: Program 2
Start Date: 6/1/13
End Date: 2/15/14
Button: |Click to view entries|
What I would really like to do is call a model I created that accepts an array which acts as a filter. It works nicely when called from a controller but I don't think I can do that looks like this:
public function get_entries($filter, $option = false)
{
$this->db->where($filter);
$this->db->from('item i');
$this->db->join('program p', 'p.Id=i.program_Id');
$this->db->join('vendor v', 'v.Id=i.vendor_Id');
$this->db->join('item_type it', 'it.Id=i.item_type_Id');
$this->db->join('item_type_category itc', 'itc.item_type_Id=it.Id');
$this->db->join('category c', 'c.Id=itc.category_Id');
$this->db->select('i.*, p.programName, v.VENDNM, it.name, c.catName');
$this->db->select('(SELECT FORMAT(i.cost, "c")) AS cost', FALSE);
$query = $this->db->get();
$result = $query->result_array();
if ($option === false){
return $result;
}
elseif ($option === "count"){
return count($result);
}
}
This is easy -- just use a form that has fields that determine the ranges you want to search on. The address that you use on the form will first go to your controller -- then the method. Using Codeigniters form helper if your controller is 'reports' and a method 'search':
echo form_open('reports/search');
then in your 'reports' controller in a method called 'search'
Verify the Form Using the Form Validation class.
ALWAYS verify user input even if you are just using drop down menus.
If the form does not verify
show the form view again with an error message
Else
do the search with the values provided by the form.
Typically doing this search and passing back the results
(or False for no results) will happen in the Model
If there are no database results
show the form view again with a no results message
Else if there are results
pass results to a view page which will display them.
Form Helper
http://ellislab.com/codeigniter/user-guide/helpers/form_helper.html
Form Validation
http://ellislab.com/codeigniter/user-guide/libraries/form_validation.html
and take a look at this tutorial -- will show you many of the basic code patterns you need -
http://ellislab.com/codeigniter/user-guide/tutorial/index.html

Categories