If statement inside elseif statement causing error - php

Okay, so I used to have this code and it worked fine:
$lastpost = ForumPos::where('user_id', '=', Auth::id())->orderby('created_at', 'desc')->first();
if ($validator->fails())
{
return Redirect::to('/forum/topic/'.$id.'/new')
->withErrors($validator->messages());
}
elseif ($lastpost->created_at->diffInSeconds() < 15)
{
return Redirect::to('/forum/topic/'.$id.'/new')
->withErrors('You really need to slow down with your posting ;)');
}
else
{
$new_thread = new ForumThr;
$new_thread->topic = $id;
$new_thread->user_id = Auth::id();
$new_thread->title = Input::get('title');
$new_thread->save();
$new_post = new ForumPos;
$new_post->thread = $new_thread->id;
$new_post->user_id = Auth::id();
$new_post->body = Input::get('body');
$new_post->save();
return Redirect::to('/forum/thread/'.$new_thread->id.'');
}
and this worked fine, until I noticed a little problem so I had to change this a bit to get this:
$hasposted = ForumPos::where('user_id', '=', Auth::id())->count();
if ($validator->fails()){
return Redirect::to('/forum/topic/'.$id.'/new')
->withErrors($validator->messages());
} elseif ($hasposted != 0) {
$last_post = ForumPos::where('user_id', '=', Auth::id())->orderBy('created_at', 'DESC')->first();
if ($last_post->created_at->diffInSeconds() < 15) {
return Redirect::to('/forum/topic/'.$id.'/new')
->withErrors('You really need to slow down with your posting ;)');
}
} else {
$new_thread = new ForumThr;
$new_thread->topic = $id;
$new_thread->user_id = Auth::id();
$new_thread->title = Input::get('title');
$new_thread->save();
$new_post = new ForumPos;
$new_post->thread = $new_thread->id;
$new_post->user_id = Auth::id();
$new_post->body = Input::get('body');
$new_post->save();
return Redirect::to('/forum/thread/'.$new_thread->id.'');
}
Now when I post a thread and get to the if statement inside the elseif statement, I hit a roadblock. I get the following error:
I only get this error when I haven't specified the title variable in the controller so the view gets it, however there shouldn't be a view. Any ideas? :S

Take a look at your elseif block (second condition)
if(...)
{
//first condition
return ...;
}
elseif ($hasposted != 0) {
{
//second condition
$last_post = ForumPos::where('user_id', '=', Auth::id())->orderBy('created_at', 'DESC')->first();
if ($last_post->created_at->diffInSeconds() < 15) {
return Redirect::to('/forum/topic/'.$id.'/new')
->withErrors('You really need to slow down with your posting ;)');
}
}
else
{
//third condition
return ...;
}
When your nested if statement fails
$last_post->created_at->diffInSeconds() < 15
this block finishes, and the rest of the conditional finishes without issuing a Redirect. That is, your nested if statement knows nothing about the third conditional. PHP/Laravel are doing what you told it to -- so tell it to do something else.
This is purely a style suggestion, but I've reached a point where I avoid multiple branch conditionals whenever possible, especially when returning from inside a branch. A style more like
if(...)
{
return Redirect(); //...
}
if(...)
{
return Redirect(); //...
}
if(...)
{
return Redirect(); //...
}
if(...)
{
return Redirect(); //...
}
might look longer on the page, but it's much clearer what's going on.
If this? Do something and go away (`return`)
Still here? Well if this-other-thing then do something and go away (`return`)
**Still** here? Well if this-other-thing then do something and go away (`return`)
You end up thinking in a series of yes/no tests, and avoid the very human/programmer problem you ran into with nested conditional logic.

In all your other conditions you do a redirect. If the elseif succeeds, but the if does not succeed then you do nothing. It is then trying to render a page using your master template but you have not set any of the variables that it needs. You could fix this by adding another redirect:
if ($last_post->created_at->diffInSeconds() < 15) {
return Redirect::to('/forum/topic/'.$id.'/new')
->withErrors('You really need to slow down with your posting ;)');
}
else
{
return Redirect::to('/somewhere/else/');
}

After discussing this in the Laravel IRC room, we found the solution (and I believe answers here would have sufficed too)
In the end, I came up with this:
$hasposted = ForumPos::where('user_id', '=', Auth::id())->count();
if ($validator->fails()){
return Redirect::to('/forum/topic/'.$id.'/new')
->withErrors($validator->messages());
} elseif ($hasposted != 0) {
$last_post = ForumPos::where('user_id', '=', Auth::id())->orderBy('created_at', 'DESC')->first();
if ($last_post->created_at->diffInSeconds() < 15) {
return Redirect::to('/forum/topic/'.$id.'/new')
->withErrors('You really need to slow down with your posting ;)');
}
}
$new_thread = new ForumThr;
$new_thread->topic = $id;
$new_thread->user_id = Auth::id();
$new_thread->title = Input::get('title');
$new_thread->save();
$new_post = new ForumPos;
$new_post->thread = $new_thread->id;
$new_post->user_id = Auth::id();
$new_post->body = Input::get('body');
$new_post->save();
return Redirect::to('/forum/thread/'.$new_thread->id.'');
If it passes all the if statements, it'll get through to the final request and now I'm happy to say it all works as planned. Thanks, lads!

Related

OctoberCMS Pagination

I use octobercms and User Extended plugin(Clacke). I try to render a pagination because for now i have a lot of registered users and they display on one page.
I use random users function from \classes\UserManager.php
public static function getRandomUserSet($limit = 7)
{
$returner = new Collection;
$userCount = User::all()->count();
if(!isset($userCount) || empty($userCount) || $userCount == 0)
return [];
if($userCount < $limit)
$limit = $userCount;
$users = User::all(); //paginate(5)
if(empty($users))
return $returner;
$users->random($limit);
$friends = FriendsManager::getAllFriends();
foreach($users as $user)
{
$userAdd = true;
if(!$friends->isEmpty())
{
foreach($friends as $friend)
{
if($user->id == $friend->id)
{
$userAdd = false;
break;
}
}
}
if($user->id == UserUtil::getLoggedInUser()->id)
$userAdd = false;
if($userAdd)
{
$returner->push($user);
}
}
return $returner->shuffle();
}
try to do this with changing return $returner->paginate(25); and $users = User::paginate(25); but throws me an error
An exception has been thrown during the rendering of a template
("Method paginate does not exist.").
After that i try to change directly in \components\User.php
public function randomUsers()
{
return UserManager::getRandomUserSet($this->property('maxItems'))->paginate(12);
}
But again the same error.
Tryed and with this code and render in default.htm {{ tests.render|raw }}
public function randomUsers()
{
$test = UserManager::getRandomUserSet($this->property('maxItems'));
return $test->paginate(10);
}
Again with no success. Could anyoune give me some navigation and help to fix this?
If you are using random users function from \classes\UserManager.php
I checked the code and found that its using Illuminate\Support\Collection Object. So, for that Collection Object pagination works differently
You need to use forPage method.
On the other hands paginate is method of Illuminate\Database\Eloquent\Collection <- so both collection are not same
Use forpage
// OLD return UserManager::getRandomUserSet($this->property('maxItems'))
// ->paginate(12);
TO
return UserManager::getRandomUserSet($this->property('maxItems'))
->forPage(1, 12);
forPage method works like forPage(<<PAGE_NO>>, <<NO_OF_ITEM_PER_PAGE>>);
so if you use forPage it will work fine.
if any doubt please comment.

Save method not working in laravel controller with no error message

I'm in a situation that i still couldn't figure out how to solve.
I have a function in a Laravel controller that ends in save, everything goes nice and i got no errors but the data don't go to the DB.
I already made a lot of tests and everything is as expected but don't persist the data.
Can someone help me?
I've looked in a lot of places and didn't find anything that could help me, find some things about the id typo but is not my case.
Here's the function in the controller:
public function saveCodeList(Request $request)
{
try{
\DB::beginTransaction();
$input = $request->all();
foreach ($input as $i){
$pecaId = $this->TecmanutencaoPecaM
->where('peca', $i['peca'])
->select('id')
->first();
if($pecaId){
$codPeca = new TecManutencaoEstoqueCodPeca();
$codPeca->idPeca = $pecaId->id;
$codPeca->codigo = $i['codigo'];
$codPeca->emEstoque = 's';
if ($codPeca->save()) {
return response()->json('salvo', 200);
} else {
return response()->json('Erro ao salvar');
}
} elseif ($i['codigo'] !== null || $i !== '') {
return response()->json('Sem códigos a adicionar', 200);
}
}
\DB::commit();
} catch (\Exception $e){
\DB::rollback();
return response()->json($e.'erro');
}
}
I'm using Vue in the frontend.
Any help will be most appreciated.
Thanks in advance.
You are committing the database after you have a returned a response, as a result you are never actually committing the transaction to the database. You could solve this by making sure you commit the transaction before returning the json response.
For example:
if ($codPeca->save()) {
\DB::commit();
return response()->json('salvo', 200);
} else {
...

How can I do a self-join in Laravel?

Here is my code:
$role_id = Auth::user()->role_id;
$related = Page::where('path', $request->path())->where('method', $_SERVER["REQUEST_METHOD"])->first()->related;
$pages = Page::where('related', $related)->get();
foreach ($pages as $page){
$accessGiven = page_role::where('role_id', $role_id)->where('page_id', $page->id)->first();
if ( sizeof($accessGiven) > 0 ) {
return $next($request);
}
}
return redirect('/');
It works well logically, but it is a little slow for huge dataset. You know, it's actually a middleware and will be executed before most of requests.
Anyway, I guess I can combine line 2 and line 3 and make one query of them. Any idea how can I do that?
Try this:
In your Page model:
public function relatedPages(){
return $this->hasMany(self::class, 'related', 'related');
}
then
$pages = Page::where('path', $request->path())->where('method', $_SERVER["REQUEST_METHOD"])->first()->relatedPages
Look in this example (I didn't test it):
$requestPath = $request->path();
$serverMethod = $_SERVER["REQUEST_METHOD"];
$pages = Page::where('related', function($query) use($requestPath,$serverMethod) {
$query->where('path', $requestPath )->where('method',
$serverMethod)->first()->related; }
)->get()

How to open specific page of paginate?

I get comments paginated. And I need to check, if I have the id of a comment, then open the page that comment is in. Here is my code:
public function show_comments(Request $request) {
$cmnt_id = $request->input('cmnt_id');
if ( isset( $cmnt_id ) ){
// I need to get all comments paginated but start from the page that $cmnt_id is in it
} else {
// starts from page 1
$comments = Cmnt_tb::paginate(10);
}
return View('show_cmnts', compact('comments'));
}
How can I do that? any idea?
I think I have to make a new URL and redirect to it.
Maybe there is a better solution, but I guess something like this will work for you:
public function show_comments(Request $request) {
$cmnt_id = $request->input('cmnt_id');
$perPage = 10;
if (isset($cmnt_id)){
// Get row number.
$rowNumber = Cmnt_tb::where('id', '<=', $cmnt_id)->count();
// Get page.
$page = ceil($rowNumber / $perPage);
return redirect('show-comments-url?page='.$page);
} else {
$comments = Cmnt_tb::paginate($perPage);
return view('show_cmnts', compact('comments'));
}
}

Eloquent logic refactor

Today I came up with a legacy code. I have a function that sometimes generates very long runtimes and often occurs timeout at our partner. Mainly the function checks for reserved seats at a theatre but instead of get all the data and check for empty seats it runs the query for every single seat. which (i think) generates the huge runtime.
Here is the correspondig code:
public function printTicketChaos(){
$input = Input::all();
if( isset($input['date_id']) && !isset($input['reserve_id']) ){
$program_date = \Model\ProgramDate::find($input['date_id']);
if($input['piece'] > $program_date->available_capacity){
//dd($input['piece'] . ' ??? ' . $program_date->available_capacity);
return true;
}
$reserved_seats = Session::get('reserved_seats');
if($reserved_seats != null && count($reserved_seats) > 0){
foreach ($reserved_seats as $row => $seats) {
foreach ($seats as $key => $seat) {
$reserve = \Model\Reserve::whereForeignDateId($program_date->id)->whereTableName('programs')->whereHas('seats', function($query) use($row, $seat){ $query->whereRow($row)->whereSeat($seat); })->first();
if($reserve != null){
return true;
}
$oi = \Model\OrderItem::whereForeignId($program_date->id)->whereTableName('programs')->whereHas('order', function($query){ $query->whereStorno(0); })->whereHas('seats', function($query) use($row, $seat){ $query->whereRow($row)->whereSeat($seat); })->first();
if($oi != null){
return true;
}
}
}
}
}
return false;
}
I think the solution could be that i query all the seats and then check for the empty ones in the foreach. Is this a good idea or what do you think which is the best way to do it?
The code uses Laravel 4.2
Thank you for your aswers!
Okay, i made changes in the query and the logic aswell but it was still slow as hell.
The system uses a 3rd party PDF generator to create the "ticket" for the costumer and this was the "bad guy".

Categories