When I use Query Builder I Always find myself doing something like this:
$item = \DB::table('table')->where('slug',$slug)->first();
if ($item===null)
throw \Exception('Not found');
This could be easly solved if there were a firstOrFail() like Eloquent:
$item = \DB::table('table')->where('slug',$slug)->firstOrFail();
Is Eloquent the only way to use firstOrFail()? Does Query Builder allow something like this?
You can add it yourself to the query builder, via a macro:
DB::query()->macro('firstOrFail', function () {
if ($record = $this->first()) {
return $record;
}
throw new Exception('No records found');
});
Then you can use it the same way you do Eloquent:
$item = DB::table('table')->where('slug', $slug)->firstOrFail();
you are almost there, laravel does provide a way to check something like this
DB::table('table')->where('slug', $slug)->exists()
DB::table('table')->where('slug', $slug)->doesntExist()
it will return boolean, hope this helps
Update:
how i did it in projects was
function checkIfExists($table, $value, $field = 'id'){
return DB::table($table)->where($field, $value)->exists()
}
function getFirst($table, $value, $field = 'id'){
return DB::table($table)->where($field, $value)->first()
}
and then use this function like this
if(checkIfExists('users', 2))
$user = getFirst('users', 2)
else
// throw exception or something
Hope this helps
Related
I am trying to cache a sitemap generated from a controller for a website that I am working on, but apparently I am doing something wrong, as I don't understand the Error message.
Here is the code snippet causing the trouble (it is a controller Method). Everything works correctly until I add the caching.
public function mapContent($type, Request $request)
{
$cachingKey = $request->fullUrl();
if ($type !== 'news' && $type !== 'pages') {
abort(404);
} elseif (Cache::has($cachingKey)) {
$items = Cache::get($cachingKey);
} else {
$items = $this->_getElementsSitemap($type);
Cache::put($cachingKey, $items, now()->addDays(7));
}
return Response::make($items, '200')->header('Content-Type', 'application/xml');
}
Seems that $items = $this->_getElementsSitemap($type); returns not serializable instance.
Your class should implement __serialize method
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.
when i using postman get the result from chunk,but the result will return empty,how can i solve this?
enter image description here
here's my code
public function downloadMemberInfo()
{
error_log('download');
set_time_limit(240); //testing
$memberListsArray = array();
Member::select('vipcode')->where('vipcode','!=','')
->chunk(3000,function($members) use($memberListsArray){
foreach($members as $member){
$memberListsArray[] = $member;
}
});
return response()->json($memberListsArray);
}
You need to call get before use chunk; because chunk works with collections. Try with the next code.
public function downloadMemberInfo()
{
error_log('download');
set_time_limit(240);
$members = Member::select('vipcode')
->where('vipcode', '!=', '')
->get()
->chunk(3000)
->toArray();
return response()->json($members);
}
By the way, I recommend you to use paginate or some query limit to avoid performance issues
I have a list of properties for a real estate application and im trying to implement a like/unlike functionality based on each property detail. The idea is to add a like or remove it matching the current property and user. This is my code so far, but it only remove likes so it doesnt work as expected. If anyone can suggest for a better approach ill be appreciated.
//Controller
public function storeLike($id)
{
$like = Like::firstOrNew(array('property_id' => $id));
$user = Auth::id();
try{
$liked = Like::get_like_user($id);
}catch(Exception $ex){
$liked = null;
}
if($liked){
$liked->total_likes -= 1;
$liked->status = false;
$liked->save();
}else{
$like->user_id = $user;
$like->total_likes += 1;
$like->status = true;
$like->save();
}
return Redirect::to('/detalle/propiedad/' . $id);
}
// Model
public static function get_like_user($id)
{
return static::with('property', 'user')->where('property_id', $id)
->where('user_id', Auth::id())->first();
}
// Route
Route::get('store/like/{id}', array('as' => 'store.like', 'uses' => 'LikeController#storeLike'));
#Andrés Da Viá Looks like you are returning object from model. In case there is no data in database, it will still return an object - so far my guessing. Can you do something like below in the if($liked){ code?
Try this instead:
if(isset($liked -> user_id)){
Also try to print $liked variable after try and catch blocks. Use var_dump.
If this still does not work for you then let me know. I will try to create code based on your question.
Fix it by adding a where clause in my model to make the status equal to True ->where('status', 1)->first();
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!