I am trying to cache request for counting number of users in different categories
my function without caching:
public function getNumOfUsersInCat()
{
$numUsers = count($this -> users);
$otherCategories = Category::where('id', '<>', $this -> id) -> get();
foreach($otherCategories as $categ){
if($this -> isAncestorOf($categ))
$numUsers += count($categ -> users);
}
return $numUsers;
}
I was trying to cache requests like:
public function getNumOfUsersInCat()
{
$numUsers = count($this -> users);
$otherCategories = Cache::remember('cache_numuserscat)',60*60*12,function(){
return
Category::where('id', '<>', $this -> id) -> get();
foreach($otherCategories as $categ){
if($this -> isAncestorOf($categ))
$numUsers += count($categ -> users);
}
});
return $numUsers;
}
But I am getting only 0
Laravel 5.7.2
It is because you have put the calculation loop inside your cache and before reaching that part, you return with the category list. So the code you run is actually this:
public function getNumOfUsersInCat()
{
$numUsers = count($this -> users);
$otherCategories = Cache::remember('cache_numuserscat)', 60*60*12, function(){
return Category::where('id', '<>', $this -> id) -> get();
});
return $numUsers;
}
Before the correct code, there are a few things you should note:
Your cache name should only work for this model you are in, so I added $this->id to the name.
You can use withCount to get the count of all model users in a single query. Your approach have N+1 problem.
The Final code can be like this:
public function getNumOfUsersInCat()
{
$cacheName = "cache_num_users_cat_" . $this->id;
return Cache::remember($cacheName, 60 * 60 * 12, function() {
$numUsers = count($this->users);
$otherCategories = Category::query()
->where('id', '<>', $this->id)
->withCount('users')
->get();
foreach ($otherCategories as $categ) {
if ($this->isAncestorOf($categ)) {
$numUsers += $categ->users_count;
}
}
return $numUsers;
});
}
Related
Situation:
$post_1 = 'john';
$post_2 = 30;
$arr = array(['name'=>'john','number'=>70],['name'=>'clark','number'=>50]);
$collection = collect($arr);
if($post_1 == 'john')
{
$collection->where('name',$post_1);
}
if($post_2 == 70)
{
$collection->where('number',$post_2);
}
var_dump($collection->all());
But this doesn't work. I want to include filters but it depends on the post parameters to exist.
I think you can use when
$result= $collection->when(($post_1=="john"), function ($collection)use($post_1) {
return $collection->where('name',$post_1);
})->when(($post_2 == 70), function ($collection)use($post_2) {
return $collection->where('number',$post_2);
})->all();
dd($result);
or
$collection->when(($post_1=="john"), function ($collection)use($post_1) {
return $collection->where('name',$post_1);
})->when(($post_2 == 70), function ($collection)use($post_2) {
return $collection->where('number',$post_2);
});
dd($collection->all());
Ref:https://laravel.com/docs/8.x/collections#method-when
I need to save size by kb in database to view it in frontend, this is the controller I am using. I am using Laravel 5.8
So my question is does Laravel provide any Facade to deal with such situations? Or any other framework have more suitable capabilities for problem is?
public function addCourse(Request $request) {
if ($request -> isMethod('post')) {
$data = $request -> all();
$course = new Courses;
$course -> course_name = $data['course_name'];
$course -> category_id = $data['course_sector'];
$course -> course_code = $data['course_code'];
if (!empty($data['course_description'])) {
$course -> description = $data['course_description'];
} else {
$course -> description = "";
}
$course -> start_date = $data['start_date'];
$course -> end_date = $data['end_date'];
$course -> location = $data['course_location'];
$course -> price = $data['course_price'];
if ($request -> hasFile('course_image')) {
$courseImage = Input::file('course_image');
if ($courseImage -> isValid()) {
$extension = $courseImage -> getClientOriginalExtension();
$filename = rand(111,99999).'.'.$extension;
$large_image_path = "assets/manage_display/images/courses/large/".$filename;
$medium_image_path = "assets/manage_display/images/courses/medium/".$filename;
$small_image_path = "assets/manage_display/images/courses/small/".$filename;
Image::make($courseImage) -> save ($large_image_path);
Image::make($courseImage) -> resize (600,null, function ($constraint) {
$constraint -> aspectRatio();
}) -> save ($medium_image_path);
Image::make($courseImage) -> resize (300,null, function ($constraint) {
$constraint -> aspectRatio();
}) -> save ($small_image_path);
$course -> image = $filename;
}
}
$course -> save();
return redirect('/control/courses') -> with('flash_message_success', 'New Courses Added Successfully');
}
$coursesCategories = CoursesCategory::where(['parent_id' => 0]) -> get();
$coursesCategories_dropdown ="<option selected disabled>Select</option>";
foreach ($coursesCategories as $coursesCategory) {
$coursesCategories_dropdown .= "<option class='font-weight-bold' value='".$coursesCategory -> id."'>".$coursesCategory -> name."</option>";
$subCoursesCategories = CoursesCategory::where(['parent_id' => $coursesCategory -> id]) -> get();
foreach ($subCoursesCategories as $subCoursesCategory) {
$coursesCategories_dropdown .= "<option class='blockquote-footer' value='".$subCoursesCategory -> id."'> - ".$subCoursesCategory->name."</option>";
}
}
return view('layouts.manage_layouts.courses.add_course') -> with(compact('coursesCategories_dropdown'));
}
You can use getSize() method to get size of uploaded file and then store it in the database:
$request->file('file')->getSize();
In my controller I retrieve a list of messages from the message model. I am trying to add a filter, but the filters are cancelling each other out.
// Controller
public function __construct(Message $messages)
{
$this->messages = $messages;
}
public function index($filter = null)
{
$messages = $this->messages
->actioned($filter == 'actioned' ? false : true)
->ignored($filter == 'ignored' ? true : false)
->get();
return view('...
}
// Model
public function scopeActioned($query, $actioned = true)
{
$constraint = ($actioned ? 'whereNotNull' : 'whereNull');
return $query->$constraint('ts_actioned');
}
public function scopeIgnored($query, $ignored = true)
{
return $query->where('is_ignored', ($ignored ? 'Yes' : 'No'));
}
How can I setup Eloquent so that scopeActioned is only called if $filter is set to 'actioned', and the same for ignored?
Simple Approach:
public function index($filter = null)
{
$query = $this->messages->query();
//applying filter
if($filter == 'actioned') {
$query->actioned();
}
if($filter == 'ignored') {
$query->ignored();
}
$messages = $query->get();
return view('...
}
Another Approach is work in Scope Function.
// Model
public function scopeActioned($query, $actioned = true)
{
if($actioned) {
$query->whereNotNull('ts_actioned');
}
return $query;
}
public function scopeIgnored($query, $ignored = true)
{
if($ignored) {
$query->where('is_ignored', 'Yes');
}
return $query;
}
i have a controller function that needs to be redirected to a route with a different function to avoid redundancy of codes. is it possible to put a redirect to a different function?
Here is the code:
public function index()
{
$x = Auth::user()->id;
$id = DB::table('requests')->where('id', $x)->lists('userid');
if (!is_null($id)) {
$frnd = DB::table('users')->whereIn('id', $id)->get();
if (!is_null($frnd)) {
return view('friendlist', compact('frnd'));
} else {
$frnd = null;
return view('friendlist', compact('frnd'));
}
} else {
$frnd = null;
return view('friendlist', compact('frnd'));
}
}
public function respond()
{
$frnds = new Friend;
$id = Auth::user()->id;
$friendid = Request::input('friendid');
$frnds->id = $id;
$frnds->friendid = $friendid;
if (Input::get('accept')) {
$frnds->save();
}
DB::table('requests')->where('id', $id)->where('userid', $friendid)
return // this is where i should redirect to page with function index()
}
Name the index route in routes definition like this
Route::get('home', ['uses' => 'YourController#index', 'as' => 'home']);
Then use redirect method to redirect to this route:
return redirect()->route('home');
For more info on redirects use official docs
http://laravel.com/docs/5.1/responses#redirects
I don't think is a perfect, but someone prefer this way:
private function _index()
{
$x = Auth::user()->id;
$id = DB::table('requests')->where('id', $x)->lists('userid');
if (!is_null($id)) {
$frnd = DB::table('users')->whereIn('id', $id)->get();
if (!is_null($frnd)) {
return view('friendlist', compact('frnd'));
} else {
$frnd = null;
return view('friendlist', compact('frnd'));
}
} else {
$frnd = null;
return view('friendlist', compact('frnd'));
}
}
public function index()
{
$this->_index();
}
public function respond()
{
$frnds = new Friend;
$id = Auth::user()->id;
$friendid = Request::input('friendid');
$frnds->id = $id;
$frnds->friendid = $friendid;
if (Input::get('accept')) {
$frnds->save();
}
DB::table('requests')->where('id', $id)->where('userid', $friendid)
$this->_index();
}
private function for repeated code.
I can't see where I'm going wrong with my code. I believe I have my relationships/models set up correctly but my bannerclicks table will not insert a row, and worse it seems to break the banner redirect.
MIGRATION
const TBL_BANNER_CLICKS = 'banner_clicks';
public function up()
{
// Create the clicks table
Schema::create(self::TBL_BANNER_CLICKS, function($table){
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('banner_id')->unsigned();
$table->string('ip_address', 45);
$table->integer('clicks')->unsigned()->default(0);
$table->integer('created_at');
$table->foreign('banner_id')
->references('id')->on('banners')
->onUpdate('cascade')
->onDelete('cascade')
;
});
}
MODELS
Banner.php
public function bannerclicks()
{
return $this->hasMany('BannerClick');
}
BannerClick.php
protected $table = 'banner_clicks';
public function banner()
{
return $this->belongsTo('Banner');
}
BannerController.php
public function redirect($id)
{
try {
// Original (want to keep)
$banner = Banner::where('id', $id)
->where('active', 1)
->firstOrFail();
$banner->clicks++;
$banner->save();
// new banner_clicks table
$bannerclick = new BannerClick($id);
$bannerclick->banner_id = $id;
$bannerclick->clicks = 1;
$bannerclick->bannerclicks()->save($bannerclick);
return Redirect::to($banner->url);
} catch (Exception $ex) {
return Redirect::to('/');
}
}
HTML
<a href="{{URL::action('BannerController#redirect', $banner->id)}}" target="_blank" rel="nofollow">
<img src="{{$banner->image}}" class="img-responsive" alt="{{$banner->title}}"></a>
I think you should be saving your relation with something like this:
public function redirect($id)
{
try {
// Original (want to keep)
$banner = Banner::where('id', $id)
->where('active', 1)
->firstOrFail();
$banner->clicks++;
$banner->save();
// new banner_clicks table
$bannerclick = new BannerClick(array('clicks' => 1));
$banner->bannerclicks()->save($bannerclick);
return Redirect::to($banner->url);
} catch (Exception $ex) {
return Redirect::to('/');
}
}
See here: http://laravel.com/docs/eloquent#inserting-related-models
Or just do this:
$banner = Banner::where('id', $id)
->where('active', 1)
->firstOrFail();
$banner->clicks++;
$banner->save();
// new banner_clicks table
$bannerclick = new BannerClick;
$bannerclick->clicks = 1;
$bannerclick->banner_id= $banner->id;
$bannerclick->save();