Route after filters are not being canceled when before filter fails - laravel-4

According to the docs, when the before filter of a route fails, the after filter is canceled, but it doesn't seem to be the case. I'm have a navigation pulled from the database. My route before filter whether on a Route::group or a plain route checks whether a person has visited that a certain page. If it hasn't, it will return a Redirect::route('new route').
The route after filter will add a row to a visited_pages table.
What is happening when I click on a link where I haven't visited its prerequisite page, is it will redirect. But - it will still add a row to the database. So the after isn't being canceled. It still fires.
The way I tested this was I was logged in and was on a page. Cleared the page visits from the database. I then clicked on my "classroom" nav item. This requires "orientation"
What gets entered into the database is a page visit in the following in this order:
Classroom
Classroom Instructions
Orientation
What I'm expecting to see is:
Orientation
Routes
Route::group(array("prefix"=>"classroom","before"=>"checkPrerequisite"),function()
{
Route::get('/',array(
'as'=>'classroom',
'uses'=>'ClassroomController#index',
'after'=>'addvisit',
));
//there are more routes here, but they don't need after filters.
Route::get('/instructions',array(
'as'=>'classroom.instructions',
'after'=>'addvisit',
function()
{
return View::make('classroom.instructions');
}
));
});
Before filter
Route::filter('checkPrerequisite', function($route, $request)
{
$sPrerequisite = Navigation::where('url','=',Navigation::where('url','=',Route::currentRouteName())->first()->prerequisite)->first();
// get the module id from session
$mod_id = Session::get('current_module');
// get the page from the user_page_visits
$page = Auth::user()
->pages()
->where('module_id','=',$mod_id)
->where('nav_id','=',$sPrerequisite->id)
->first();
if(!$page) return Redirect::route($sPrerequisite->url);
});
After filter
Route::filter('addvisit', function($route, $request, $response)
{
// get the current route
$current = Route::currentRouteName();
// get the id of the navigation item with this route
$nav_id = Navigation::where('url','=',$current)->first()->id;
// get the module id from cache
$mod_id = Session::get('current_module');
// see if the page has been visited
$page = Auth::user()
->pages()
->where('module_id','=',$mod_id)
->where('nav_id','=',$nav_id)
->first();
if($page)
{
// if it has been visited, increment the visits column by 1
$page->increment('visits');
}
else
{
// otherwise, create a new page visit
$visit = new UserPageVisits;
$visit->user_id = Auth::user()->id;
$visit->module_id = $mod_id;
$visit->nav_id = $nav_id;
$visit->save();
}
});

Related

how to return to a specific page after form submit based on value laravel

i have a logic whereby on form submission i want to return to specific page based on a certain value the user choosed when submiting the form.the form works well but when i try to return it doesnt work.where might i be missing the point here.
public function addtoorder(Request $request){
$userid=Auth::user()->id;
$addresses=Deliveryaddress::where('user_id',$userid)->first();
if($request->isMethod('post')){
$data=$request->all();
$order = new Order();
$order->name = Auth::user()->name;
$order->phone =$addresses->phone;
$order->county =$addresses->shipcharges->county;
$order->town =$addresses->towns->town;
$order->order_status="New Order";
$order->payment_method = $request->payment_method;
$order->user_id =$userid;
$order->grand_total = Session::get('grand_total');
$order->shipping_charges=$addresses->shipping_cost;
$order->save();
}
if($data=="SKRILL"){
return view('frontend.product.skrill');
}elseif($data=="PAYPAL"){
return view('frontend.product.paypal');
}
}
}
i have been able to save the data on the database but am unable to return to the specific pages.rather it return to blank page without any error,but it saves the data to the orders table perfectly.
I guess blank screen means that nothing was returned, because you are trying to check whether $data(which is array) is equal to some string.
My thoughts would be for you to try check string in your if statement.
Like this
if($data['payment_method'] === "SKRILL"){
return view('frontend.product.skrill');
}elseif(data['payment_method'] === "PAYPAL"){
return view('frontend.product.paypal');
}

Laravel : Fetch big Data from Api (URL)

Hwllo please i'm trying to fetch 15000 objects from api i used guzzle and file_get_contents but it's take long time and sometime the page doesn't load completely .
the controller :
$client = new \GuzzleHttp\Client();
$request = $client->get('http://XXX');
$response = $request->getBody();
$books = json_decode($response, true);
return view('n.search', compact('books'));
the books variable return 10000 items and take very time to load !
Could you help me to fix that ?
Here's an example just to give you an idea how I made this kind of problem.
in your controller, you should always paginate the returned collection of it. Like below
$users = User::all()->paginate(100);
laravel will return these 20 users together with some data like, next url, prev url, current_page and etc. These additional is important so that you will know what is the next url and prev url (these urls will be use in your api requests);
Now, after you get the paginated users, you need also to count the total users and return it together with users so that your front will know if how many pages it will display. Like this below
$total_users = User::all()->count();
now your final controller will look like this.
public function getUsers() {
$users = User::all()->paginate(20);
$total_users = User::all()->count();
return compact('users', 'total_users');
}
and it will return these results.
users // the 20 users
total_users // the total number of users in your table
currentPage
lastPage
perPage
hasMorePages
url
nextPageUrl
firstItem
lastItem
total
count
and so, every time you click pages in your datatable, you just need to use the next nextPageUrl and prevPageUrl as url in your api request.

Yii2 validation on controller action

I am developing a Yii 2.0 application in which users can create orders then send the orders to review and after that it follows a number of stages in the workflow.
Everything is ok until yesterday that the customer ask for the possibility that before sending the orders to review the order are considered as draft. Which means I have to turn off validations on create and validate them when users clicks Send To Review button. I know Yii 2.0 supports scenarios but maybe scenarios doesn't apply to this because the Send To Review button is shown in a readonly view. This forces me to do validation inside the controller action because there is no send_to_review view. How can this be done (I mean model validation inside controller action)?
Here is the controller action code
public function actionSendToReview($id)
{
if (Yii::$app->user->can('Salesperson'))
{
$model = $this->findModel($id);
if ($model->orden_stage_id == 1 && $model->sales_person_id == Yii::$app->user->identity->id)
{
$model->orden_stage_id = 2;
$model->date_modified = date('Y-m-d h:m:s');
$model->modified_by = Yii::$app->user->identity->username;
//TODO: Validation logic if is not valid show validation errors
//for example "For sending to review this values are required:
//list of attributes in bullets"
//A preferred way would be to auto redirect to update action but
//showing the validation error and setting scenario to
//"send_to_review".
$model->save();
$this::insertStageHistory($model->order_id, 2);
return $this->redirect(['index']);
}
else
{
throw new ForbiddenHttpException();
}
}
else
{
throw new ForbiddenHttpException();
}
}
What I need to solve is the TODO.
Option 1: Showing validation errors in the same view and the user has to clic Update button change the requested values save and then try to Send To Review again.
Option 2: Redirecting automatically to update view already setting scenario and validation errors found in the controller.
Thanks,
Best Regards
You can use $model ->validate()for validation in controller.
public function actionSendToReview($id)
{
if (Yii::$app->user->can('Salesperson'))
{
$model = $this->findModel($id);
if ($model->orden_stage_id == 1 && $model->sales_person_id == Yii::$app->user->identity->id)
{
$model->orden_stage_id = 2;
$model->date_modified = date('Y-m-d h:m:s');
$model->modified_by = Yii::$app->user->identity->username;
//TODO: Validation logic if is not valid show validation errors
//for example "For sending to review this values are required:
//list of attributes in bullets"
//A preferred way would be to auto redirect to update action but
//showing the validation error and setting scenario to
//"send_to_review".
//optional
$model->scenario=//put here the scenario for validation;
//if everything is validated as per scenario
if($model ->validate())
{
$model->save();
$this::insertStageHistory($model->order_id, 2);
return $this->redirect(['index']);
}
else
{
return $this->render('update', [
'model' => $model,
]);
}
}
else
{
throw new ForbiddenHttpException();
}
}
else
{
throw new ForbiddenHttpException();
}
}
If you don't need validation in actionCreate().Create a scenario for not validating any field and apply there.

Unset session in SilverStripe

I am building a pretty simple online shop in SilverStripe. I am writing a function to remove an item from the cart (order in my case).
My setup:
My endpoint is returning JSON to the view for use in ajax.
public function remove() {
// Get existing order from SESSION
$sessionOrder = Session::get('order');
// Get the product id from POST
$productId = $_POST['product'];
// Remove the product from order object
unset($sessionOrder[$productId]);
// Set the order session value to the updated order
Session::set('order', $sessionOrder);
// Save the session (don't think this is needed, but thought I would try)
Session::save();
// Return object to view
return json_encode(Session::get('order'));
}
My issue:
When I post data to this route, the product gets removed but only temporarily, then next time remove is called, the previous item is back.
Example:
Order object:
{
product-1: {
name: 'Product One'
},
product-2: {
name: 'Product Two'
}
}
When I post to remove product-1 I get the following:
{
product-2: {
name: 'Product Two'
}
}
Which appears to have worked but then I try and remove product-2 with and get this:
{
product-1: {
name: 'Product One'
}
}
The SON OF A B is back! When I retrieve the entire cart, it still contains both.
How do I get the order to stick?
Your expectation is correct, and it should work with the code you wrote. However, the way the session data is managed doesn't work well with data being deleted, because it is not seen as a change of state. Only existing data being edited is seen as such. See Session::recursivelyApply() if you want to know more.
Only way I know is to (unfortunately) emphasized textmanipulate $_SESSION directly before you set the new value for 'order'
public function remove() {
// Get existing order from SESSION
$sessionOrder = Session::get('order');
// Get the product id from POST
$productId = $_POST['product'];
// Remove the product from order object
unset($sessionOrder[$productId]);
if (isset($_SESSION['order'])){
unset($_SESSION['order']);
}
// Set the order session value to the updated order
Session::set('order', $sessionOrder);
// Return object to view
return json_encode(Session::get('order'));
}

CodeIgniter - showing original URL of index function?

I'm not sure if I'm approaching this fundamentally wrong or if I'm just missing something.
I have a controller and within it an index function that is, obviously, the default loaded when that controller is called:
function index($showMessage = false) {
$currentEmployee = $this->getCurrentEmployee();
$data['currentEmp'] = $currentEmployee;
$data['callList'] = $currentEmployee->getDirectReports();
$data['showMessage'] = $showMessage;
$this->load->view('main', $data);
}
I have another function within that controller that does a bulk update. After the updates are complete, I want the original page to show again with the message showing, so I tried this:
/**
* Will save all employee information and return to the call sheet page
*/
function bulkSave() {
//update each employee
for ($x = 0; $x < sizeof($_POST['id']); $x++) {
$success = Employee::updateEmployeeManualData($_POST['id'][$x], $_POST['ext'][$x], $_POST['pager'][$x], $_POST['cell'][$x], $_POST['other'][$x], $_POST['notes'][$x]);
}
$this->index($success);
}
What is happening is that the original page is accessed using:
localhost/myApp/myController
after the bulk update it is showing as:
localhost/myApp/myController/bulkSave
when I really want it to show the url as the index page again, meaning that the user never really sees the /bulkSave portion of the URL. This would also mean that if the user were to refresh the page it would call the index() function in the controller and not the bulkSave() function.
Thanks in advance.
Is this possible?
You are calling your index() funciton directly, within bulkUpdate() hence the uri does not change back to index because you are not making a new server request, you are just navigating within your controller class.
I usually use the same Controller function for tasks like this, directing traffic based on whether or not $_POST data has been passed or not like this...
function index() {
if($_POST) {
//process posted data
for ($x = 0; $x < sizeof($_POST['id']); $x++) {
$data['showMessage'] = Employee::updateEmployeeManualData($_POST['id'][$x], $_POST['ext'][$x], $_POST['pager'][$x], $_POST['cell'][$x], $_POST['other'][$x], $_POST['notes'][$x]);
}
}
else {
//show page normally
$data['showMessage'] = FALSE;
}
//continue to load page
$currentEmployee = $this->getCurrentEmployee();
$data['currentEmp'] = $currentEmployee;
$data['callList'] = $currentEmployee->getDirectReports();
$this->load->view('main', $data);
}
Then if it is a form that you are submitting, just point the form at itself in your view like this...
<?= form_open($this->uri->uri_string()) ?>
This points the form back at index, and because you are posting form data via $_POST it will process the data.
I usually do a redirect to the previous page as it prevent users to refresh (and submit twice) their data.
You can use the redirect() helper function of CI.
http://codeigniter.com/user_guide/helpers/url_helper.html (at the bottom)

Resources