laravel live-wire comment system N+1 problem Occur - php

I create the comment section and everything work fine but I have an n+1 problem and I quit don't know how to solve it I have Debug the application to check where the problem here What Happen
I am Creating an App like Instagram
First I load the post of the user and The one he follows In for each loop Here is the Query
$ids = Auth::user()->followings->pluck('id');
$ids->push( Auth::user()->id);
$posts= Post::with('user', 'comments', 'likers')->whereIn('user_id', $ids)->latest()->get();
return view('dashboard', [
'posts' =>$posts
'user' => Auth::user()
]);
For Each loop
I have Strip the Unnesserry Code
#foreach($posts as $post)
<livewire:comments :post="$post" />
#endforeach
So for Everything Work, Fine Here Occurs The Problem
Livewire Comment Component
public function mount($post)
{
$this->post = $post;
}
// This is the Method The Work Fine But I Want Pagination
public function render()
{
return view('livewire.comments', ['comments' => $this->post->comments]);
}
// and If I use The pagination I Ran Into n+1 Problem
public function render()
{
return view('livewire.comments', ['comments' => $this->post->comments()->paginate(5)]);
}
if You have Any Question I if you need I extra Information Just Tell Me ok
best Regards

Related

Laravel Eloquent $model->save() not saving but no error

When updating my Post model, I run:
$post->title = request('title');
$post->body = request('body');
$post->save();
This does not update my post. But it should according to the Laravel docs on updating Eloquent models. Why is my model not being updated?
I get no errors.
The post does not get updated in the db.
Besides not being updated in the db, nothing else seems odd. No errors. Behavior as normal.
Result of running this test to see if save succeeded was true.
This Laravel thread was no help
Post model:
class Post extends Model
{
protected $fillable = [
'type',
'title',
'body',
'user_id',
];
....
}
Post controller:
public function store($id)
{
$post = Post::findOrFail($id);
// Request validation
if ($post->type == 1) {
// Post type has title
$this->validate(request(), [
'title' => 'required|min:15',
'body' => 'required|min:19',
]);
$post->title = request('title');
$post->body = request('body');
} else {
$this->validate(request(), [
'body' => 'required|min:19',
]);
$post->body = request('body');
}
$post->save();
return redirect('/');
}
Bonus info
Running dd($post->save()) returns true.
Running
$post->save();
$fetchedPost = Post::find($post->id);
dd($fetchedPost);
shows me that $fetchedPost is the same post as before without the updated data.
Check your database table if the 'id' column is in uppercase 'ID'. Changing it to lower case allowed my save() method to work.
I had the same and turned out to be because I was filtering the output columns without the primary key.
$rows = MyModel::where('...')->select('col2', 'col3')->get();
foreach($rows as $row){
$rows->viewed = 1;
$rows->save();
}
Fixed with
$rows = MyModel::where('...')->select('primary_key', 'col2', 'col3')->get();
Makes perfect sense on review, without the primary key available the update command will be on Null.
I had the same problem and changing the way I fetch the model solved it!
Was not saving even though everything was supposedly working just as you have mentioned:
$user = User::find($id)->first();
This is working:
$user = User::find($id);
You have to make sure that the instance that you are calling save() on has the attribute id
Since Laravel 5.5 laravel have change some validation mechanism I guess you need to try this way.
public function store(Request $request, $id)
{
$post = Post::findOrFail($id);
$validatedData = [];
// Request validation
if ($post->type == 1) {
// Post type has title
$validatedData = $request->validate([
'title' => 'required|min:15',
'body' => 'required|min:19',
]);
} else {
$validatedData = $request->validate([
'body' => 'required|min:19',
]);
}
$post->update($validatedData);
return redirect('/');
}
Running dd() inside a DB::transaction will cause a rollback, and the data in database will not change.
The reason being, that transaction will only save the changes to the database at the very end. Ergo, the act of running "dump and die" will naturally cause the script to cease and no therefore no database changes.
Check your table if primary key is not id ("column name should be in small letters only") if you have set column name with different key then put code in your Model like this
protected $primaryKey = 'Id';
So this might be one of the possible solution in your case also if your column name contains capital letters.
Yes this worked for me fine,
You should have column names in small letter,
If you don't have then mention it in the model file, mainly for primaryKey by which your model will try to access database.
For use save () method to update or delete if the database has a primary key other than "id". need to declare the attribute primaryKey = "" in the model, it will work
Try this
public function store($id,Request $request)
{
$post = Post::findOrFail($id);
// Request validation
if ($post->type == 1) {
// Post type has title
$request->validate([
'title' => 'required|min:15',
'body' => 'required|min:19',
]);
$post->update([
'title' => request('title');
'body' => request('body');
]);
} else {
$request->validate([
'body' => 'required|min:19',
]);
$post->update([
'body' => request('body');
]);
}
return redirect('/');
}
In my experience, if you select an Eloquent model from the db and the primary_key column is not part of the fetched columns, your $model->save() will return true but nothing is persisted to the database.
So, instead of doing \App\Users::where(...)->first(['email']), rather do \App\Users::where(...)->first(['id','email']), where id is the primary_key defined on the target table.
If the (sometimes micro-optimization) achieved by retrieving only a few columns is not really of importance to you, you can just fetch all columns by doing \App\Users::where(...)->first(), in which case you do not need to bother about the name of the primary_key column since all the columns will be fetched.
If you using transactions.
Do not forget call DB::commit();
It must look like this:
try{
DB::beginTransaction();
// Model changes
$model->save();
DB::commit();
}catch (\PDOException $e) {
DB::rollBack();
}
I have the same issue although there are try / catch block in controller#action() but there were no response, it just stops at $model->save(); there is no log entry either in apache error.log or laravel.log. I have just wrapped the save() with try / cactch as follows, that helped me to figure out the issue
try{
$model->save();
}
catch (\PDOException $e) {
echo $e->getMessage();
}
I have been experiencing the same issue and found a workaround. I found that I was unable to save() my model within a function called {{ generateUrl() }} on my home.blade.php template. What worked was moving the save() call to the controller that returns the home.blade.php template. (IE, save()ing before the view is returned, then only performing read operations within {{ generateUrl() }}.)
I was (and am) generating a state to put in a URL on page load:
<!--views/home.blade.php-->
Add Character
Below is what did not work.
// Providers/EveAuth.php
function generateUrl()
{
$authedUser = auth()->user();
if (!$authedUser) {
return "#";
}
$user = User::find($authedUser->id);
$user->state = str_random(16);
$user->save();
$baseUrl = 'https://login.eveonline.com/oauth/authorize?state=';
return $baseUrl . $user->state;
}
This was able to find() the User from the database, but it was unable to save() it back. No errors were produced. The function appeared to work properly... until I tried to read the User's state later, and found that it did not match the state in the URL.
Here is what did work.
Instead of trying to save() my User as the page was being assembled, I generated the state, save()d it, then rendered the page:
// routes/web.php
Route::get('/', 'HomeController#index');
Landing at the root directory sends you to the index() function of HomeController.php:
// Controllers/HomeController.php
public function index()
{
$authedUser = auth()->user();
if ($authedUser) {
$user = User::find($authedUser->id);
$user->state = str_random(16);
$user->save();
}
return view('home');
}
Then, when generating the URL, I did not have to save() the User, only read from it:
// Providers/EveAuth.php
function generateUrl()
{
$authedUser = auth()->user();
$user = User::find($authedUser->id);
$baseUrl = 'https://login.eveonline.com/oauth/authorize?state=';
return $baseUrl . $user->state;
}
This worked! The only difference (as far as I see) is that I'm save()ing the model before page assembly begins, as opposed to during page assembly.

one to one relationship in laravel (Error)

I am new in Laravel, when I practice I get an error.
at HandleExceptions->handleError('8', 'Trying to get property of non-object', 'C:\xampp\htdocs\cms\app\Http\routes.php', '144', array('id' => '1')) in routes.php line 144
my routes.php file
Route::get('/user/{id}/post',function ($id){
return User::find($id)->post->title;
});
in my User.php file
public function post(){
return $this->hasOne('App\Post');
}
I have two tables 1-posts 2-users
and I have also Post class
I also google and search different sites but can't understand.
Please me,how to rid this Error.
your posts are one user .
this renlship is "one-to-many" relationship .
you must for this reason using this method in modal user :
public function posts()
{
return $this->hasMany('App\Post');
}
one to many is array from posts .
for show resualt you must using foreach :
$comments = App\Post::find(1)->comments;
foreach ($comments as $comment) {
$comment->title ;
}
and reading this links : https://laravel.com/docs/5.2/eloquent-relationships#one-to-many
1:are you shure the relation is one to one;
2:if you shure add primary and foreign key and add this function in Post model.
public function user(){
return $this->hasOne('App\User','id','user_id');
}

How to filter records with RESTful models and controllers in Yii2

I'm creating a RESTful API with Yii2 and have successfully setup a model named Contacts by following the Quick Start Tutorial*. I love how records can be created, listed, updated and deleted without creating any actions.
However I can't see how to filter results. I would like to only return contacts where contact.user_id is equal to 1 (for example) as it currently will reply with all records. Is this possible without creating the actions?
I am unsure also how I can limit results. From what I've read I feel it should append the URI with ?limit=5.
http://www.yiiframework.com/doc-2.0/guide-rest-quick-start.html
You should return a dataprovider instead of a set of objects, that supports pagination for you.
Perhaps this approach will be a bit more useful:
public function actionIndex()
{
return new \yii\data\ActiveDataProvider([
'query' => Contact::find()->where(['user_id' => \Yii::$app->user-id]),
]);
}
You could also leave the index action intact, but provide the preset action with a prepareDataProvider-callback:
public function actions()
{
$actions = parent::actions();
$actions['index']['prepareDataProvider'] = function($action)
{
return new \yii\data\ActiveDataProvider([
'query' => Contact::find()->where(['user_id' => \Yii::$app->user-id]),
]);
};
return $actions;
}
Hope that helps.
I have had to override the index method despite not wanting to. My solution looks like this:
public function actions()
{
$actions = parent::actions();
unset($actions['index']);
return $actions;
}
public function actionIndex()
{
return Contact::findAll(['user_id' => \Yii::$app()->user-id]);
}
I guess this solution means I need to write my own pagination code however which is something else I was hoping to avoid.

How to store homepage in cache in laravel 4

I am new in laravel and php. I am developing a magazine site with laravel 4. I want to store home page in laravel cache . But In my homepage , there are many queries . Please see details below.:
My HomepageController index method:
public function index()
{
return View::make('homepage');
}
My Query Helper Function which is used for post by category in my Homepage:
public static function cat_post($category, $limit)
{
$posts = Post::whereHas('categories', function($q) use ($category)
{
$q->where('category_slug', 'like', $category);
})->with('categories')->take($limit)->orderBy('created_at', 'DESC')->get();
return $posts;
}
In My homepage.blade.php , I used this helper function many times. like below:
<?php $national = Helper::cat_post('national', 3); ?>
#foreach ($national as $post)
{{ Helper::img_src($post) }}
<h4>{{ $post->title }}</h4>
</div>
#endforeach
Now i want to put homepage in cache and when new post created, then delete old homepage from cache and store new one.
Please help me. Is it possible ?????
To store a value in cache you can use Laravel's Cache:
public function index()
{
return Cache::rememberForever('homepageCache', function()
{
return View::make('homepage');
});
}
This snipped tries to retrieve a cached version of View::make('homepage') and otherwise creates it.
Every time a post is created, updated or deleted you need to invalide your homepageCache:
Cache::forget('homepageCache');

Laravel 4 - view query

I have 3 views (which display settings for each): Users, Groups, Options
Each of these views is successfully rendering, using the below. The controller passes the database info into each view.
#extends('master')
#section('main-title')
Title
#stop
#section('main-content')
// All the divs, content etc (working fine)
#stop
I also have one more view: Settings
The idea of this view is simple, to be an overview of all the settings from the Users, Groups and Options. So essentially I'm trying to pull together each of the 3 views 'main-content' output, and put it within the #section('main-content') within my Settings view. However I have no idea how.
The only option I can think of is to duplicate the content within the Settings view (index function) - however this will cause issues when I want to change something as I'll need to do it in two templates.
My controller:
public function index()
{
$users = User::all();
$options = Option::all();
$groups = Group::all();
return View::make('layouts.settings', array('users' => $users, 'options' => $options, 'groups' => $groups));
}
public function users()
{
$users = User::all();
return View::make('layouts.settings.users', array('users' => $users));
}
public function options()
{
$options = Option::all();
return View::make('layouts.settings.options', array('options' => $options));
}
public function groups()
{
$groups = Group::all();
return View::make('layouts.settings.groups', array('groups' => $groups));
}
Is there anyway, I can say within my Settings view: include the content within 'main-content' from the following views (Users, Groups, Options). Or, use nested view which I have tried but cannot get working.
Thanks in advance.
Here you go - may need fine-tuning: http://paste.laravel.com/xZr

Categories