Comment on posts - php

Hey Guys I'm trying to store comments for every service in my website
first I created the relationships between user,comment,service
then when I try to add a comment I get an error :
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'services_id' cannot be null (SQL: insert into comments (body, user_id, services_id, updated_at, created_at) values (ggg, 1, , 2018-03-20 21:12:17, 2018-03-20 21:12:17))
That's the service model : Service.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Service extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
public function comments(){
return $this->hasMany('App\comment');
}}
That's the model Comment.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
public function user() {
return $this->belongsTo('App\User');
}
public function services() {
return $this->belongsTo('App\Service');
}}
That's the model User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = ['username', 'email','password','tel','ville','description','image','diplomes','langues',
];
protected $hidden = [
'password', 'remember_token',
];
public function services(){
return $this->hasMany('App\Service');
}
public function comments(){
return $this->hasMany('App\Comment');
}}
the route:
Route::post('/services/{services_id}','CommentsController#store');
Store method in CommentsController :
public function store(Request $request, $services_id)
{
$this->validate($request,array(
'body'=>'required',
));
$comment=new Comment;
$service=Service::find($services_id);
$comment->body=$request->body;
$comment->user_id=$request->user()->id;
$comment->services()->associate($service);
$comment->save();
$request->session()->flash('notif','success');
return back(); }
And that's the blade page
<form class="col s12" method="post" action="/services/{$services->id}">
{{ csrf_field() }}
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">insert_comment</i>
<textarea id="textarea1" name="body" class="materialize-textarea"></textarea>
<label for="textarea1" style="color: black;">Commentaire</label>
</div>
</div>
<div class="row">
<div class="col s12 center-align">
<input type="submit" value="confirmer" class="btn-large purple hoverable">
</div>
</div>
</form>

Your answer is here:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'services_id' cannot be null (SQL: insert into comments (body, user_id, services_id, updated_at, created_at) values (ggg, 1, MISSING VALUE , 2018-03-20 21:12:17, 2018-03-20 21:12:17))
Your query want to put to database services_id but it is undefined in yoour request
So debug it:
Make dd($request) and see the services_id value
Guess CommentController should look like this:
public function store(Request $request, $services_id)
{
$this->validate($request,array(
'body'=>'required',
));
$comment=new Comment;
$service=Service::find($services_id);
$comment->body=$request->body;
$comment->user_id=$request->user()->id;
$comment->service_id=$services_id; //here I made change!!!
$comment->save();
$request->session()->flash('notif','success');
return back(); }

Related

Problem with Laravel Livewire : Attempt to read property "recipes" on array

I'm trying to do a search input from 2 datatables of my database, one containing vegetables and the other one containing recipes made of vegetables, i first made my search input with only the elements from the vegetable table. But now im trying to include the repice table but it wont work: I'm getting the error "Attempt to read property "recipes" on array" but I do't understand where the problem comes from.
This is my code:
Search.php:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Vegetable;
class Search extends Component
{
public $query = '';
public $vegetables;
public $recipes;
public function updatedQuery()
{
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')->get()->toArray();
}
public function render()
{
return view('livewire.search');
}
}
search.blade.php :
<div class="searchcomponent">
<h1>Recherche</h1>
<input wire:model="query" type="text" placeholder="Rechercher...">
#if(!empty($query))
<ul>
#if(!empty($vegetables))
<div class="vegetables">
#foreach($vegetables as $vegetable)
<li><span class="material-icons">lunch_dining</span>{{ $vegetable['name'] }}</li>
#endforeach
</div>
#else
<li>Pas de résultat</li>
#endif
<div class="recipes">
#foreach($vegetables as $vegetable)
#foreach($vegetable->recipes as $recipe)
<li><span class="material-icons">menu_book</span>{{ $recipe['name'] }}<span class="ingredient">Ingrédient: {{ $vegetable['name'] }}</span></li>
#endforeach
#endforeach
</div>
</ul>
#endif
</div>
My model Vegetable :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Vegetable extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['name'];
public function recipes(){
return $this->belongsToMany(Recipe::class, 'vegetables_recipes', 'vegetable_id', 'recipe_id');
}
public function getName($id) {
return $this->name;
}
}
My model Recipe :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Recipe extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['name'];
public function vegetables(){
return $this->hasOne(Vegetable::class, 'vegetables_recipes', 'recipe_id', 'vegetable_id');
}
public function getName($id) {
return $this->name;
}
}
The model from my pivot table VegetablesRecipe :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class VegetablesRecipe extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['vegetable_id', 'recipe_id'];
}
Thank you in advance
So I found the issue with your code; I didn't notice it yesterday as it was hidden off-screen in your Search.php's updatedQuery() function:
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->get()
->toArray();
When you call ->toArray(), you convert the Collection of Vegetable Model instances into an Array of Arrays. This means you cannot use Object Access to get Properties:
$vegetable->recipes; // Fails with error "Attempt to read property "recipes" on array"
Additionally, you cannot access any Model functions, as an Array is not an instance of a Model:
$vegetables['recipes']; // Undefined array key "recipes"
Since public function recipes() is a method of the Vegetable.php Model class, that won't work. It can work, if you load it first before casting to an Array:
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->with('recipes')
->get()
->toArray();
Now, $vegetable['recipes'] will work, but it's better to just drop the ->toArray() completely:
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->with('recipes')
->get();
Additionally, for performance reasons, you want to include ->with('recipes') to prevent N+1 queries being called while looping.
With those changes made, you can write your livewire/search.blade.php code as follows:
<div class="searchcomponent">
<h1>Recherche</h1>
<input wire:model="query" type="text" placeholder="Rechercher...">
#if(!empty($query))
<ul>
#if(!empty($vegetables))
<div class="vegetables">
#foreach($vegetables as $vegetable)
<li><span class="material-icons">lunch_dining</span>{{ $vegetable->name }}</li>
#endforeach
</div>
#else
<li>Pas de résultat</li>
#endif
<div class="recipes">
#foreach($vegetables as $vegetable)
#foreach($vegetable->recipes as $recipe)
<li><span class="material-icons">menu_book</span>{{ $recipe->name }}<span class="ingredient">Ingrédient: {{ $vegetable->name }}</span></li>
#endforeach
#endforeach
</div>
</ul>
#endif
</div>
Lastly, some cleanup:
Vegetable.php and Recipe.php
The methods getName($id) have no purpose; you're not doing anything with $id, and name is not a private property; you can simply do $vegetable->name or $recipe->name and it will do the same as what these methods are doing.
Recipe.php
As stated in the comments, belongsToMany() is the inverse of belongsToMany(), not hasOne():
public function vegetables(){
return $this->belongsToMany(Vegetable::class, 'vegetables_recipes');
}
Additionally, if the primary and foreign key names match the model names, you don't need them. The proper name for the pivot table would be recipes_vegetables (plural, alphabetical), so specifying that is required. You can do the same for Vegetable.php:
public function recipes(){
return $this->belongsToMany(Recipe::class, 'vegetables_recipes');
}
Lastly, your model VegetablesRecipe.php is not needed, and is currently not being used. You typically don't define a Model for a Pivot table, so you can either remove it, or keep it around should you ever need to directly modify the Pivot.

Laravel showing the categories of book with pivot table error

I am learning Laravel and i have two tables books and categories
i created a pivot table with the book_id and category_id columns to make a relationship between the tables, but when i tried to show the categories in the show book page and i made foreach on the $books->categories i faced an error saying that the foreach parameter is null
the Book model file:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
use HasFactory;
protected $fillable = ['title', 'desc', 'img'];
public function categories()
{
return $this->belongsTo('App\Models\Category');
}
}
the Category model file
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
protected $fillable = ['name'];
public function books()
{
return $this->belongsTo(Book::class)->withPivot('book_category');
}
}
the show.blade page:
#extends('layout')
#section('title')
Book #{{ $book->id }}
#endsection
#section('content')
<h2>{{ $book->title }}</h2>
<p>{{ $book->desc }}</p>
#foreach ($book->categories as $category)
<span class="text-muted mx-3">{{ $category->name }}</span>
#endforeach
<div class="row">
<div class="col-md-3 p-5">
<img src="{{ asset('uploads/books') }}/{{$book->img}}" class="w-100">
</div>
</div>
Back
Edit
Delete
#endsection
the pivot table:
the pivot table
the BookController code:
public function show($id)
{
$book = Book::findOrFail($id);
return view('books/show', compact('book'));
}
You can change relationship to belongsToMany since you are using pivot table.
In Book model
public function categories()
{
return $this->belongsToMany(Category::class);
}
and in Category model
public function books()
{
return $this->belongsToMany(Book::class);
}
In your controller
$book = Book::with('categories')->findOrFail($id);
so in your view
{{$book->$title}}
#foreach ($book->categories as $category)
<span class="text-muted mx-3">{{ $category->name }}</span>
#endforeach

How to fix error Base table or view not found: 1146 1146 Table 'pigeonbazar.cart' doesn't exist?

I am new of laravel and i am trying to add product into cart but when i click the cart button i got this error.
(SQLSTATE[42S02]: Base table or view not found: 1146 Table 'pigeonbazar.cart' doesn't exist (SQL: insert into cart (user_id, products_id, updated_at, created_at) values (?, ?, 2021-07-02 03:11:08, 2021-07-02 03:11:08)).
This is my cart migration
public function up()
{
Schema::create('carts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id');
$table->integer('products_id');
$table->timestamps();
});
}
This is cart form in blade
<form action="{{route('card.add')}}" method="POST">
{{ csrf_field() }}
{{method_field('POST')}}
<div class="quantity">
-
<input title="Qty" class="email input-text qty text" name="qty"
type="text" min="1" value="1">
+
</div>
<input type="hidden" name="products_id" value="{{ $products->id }}">
<button href="19_cart.html" class="btn btn-medium btn--primary">
<span class="text">Add to Cart</span>
<i class="seoicon-commerce"></i>
<span class="semicircle"></span>
</button>
</form>
This is controller
class ShoppingController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function card_to_add(Request $request)
{
$cart = new Cart;
$cart->user_id = $request->user_id;
$cart->products_id = $request->id;
$cart->save();
return redirect()->back();
}
}
This is model of cart
class Cart extends Model
{
protected $fillable = ['products_id','user_id'];
public $table="cart";
public function user()
{
return $this->belongsTo('App\User');
}
public function product()
{
return $this->belongsTo('App\Product');
}
}
In your case Define Table in Model like this,
public $table="carts";
protected $primaryKey = 'id';
protected $fillable = ['products_id','user_id'];
If you want to pass casting then Like this,
protected $casts = [
'products_id' => 'integer',
'user_id' => 'integer',
];
and your method here,
Public function card_to_add(Request $request) {
Cart::create([
'user_id' => Auth::user()->id,
'products_id' => $request->id,
]);
return redirect()->back();
}
For More Info Read this doc,
https://laravel.com/docs/8.x/eloquent#table-names
https://laravel.com/docs/8.x/eloquent-mutators#attribute-casting
Because your table is not found (car) in your database you have cars. In order to, you need use the Laravel Development Standars or declare the table for model like this:
protected $table = 'cars';
In your model Cart.php

Comment Table Giving SQLSTATE[42S02] laravel 5.8

I am trying to make an forum where the user can post a Thread and on the bottom of the thread the user can comment to thread but when I add the commenting part to the thread it throws the SQLSTATE[42S02] Error I am trying to use Morph relation ships from laravel https://laravel.com/docs/5.8/eloquent-relationships so I can connect the thread to the corresponding thread or comment. and the final product has to be someting like Reddits one http://prntscr.com/mwvors where comment go under each other and comment can be commented on other comments.
Edit:
after php artisan migrate it updated the the migrations but give this error instead
Error
"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'comments.commmentable_id' in 'where clause' (SQL: select * from `comments` where `comments`.`commmentable_id` = 1 and `comments`.`commmentable_id` is not null and `comments`.`commmentable_type` = App\Thread) (View: C:\Users\Merlijn\AppData\Roaming\Composer\Laravel Projects\Forum\resources\views\thread\single.blade.php
single.blade.php
{{--Answers/comments--}}
<div class="comment-list">
#foreach($thread->comments as $comment)
<h4>{{$comment->body}}</h4>
<lead>{{$comment->user->name}}</lead>
#endforeach
</div>
<div class="comment-form">
<form action="{{ route('threadcomment.store', $thread->id) }}" method="post" role="form">
{{csrf_field()}}
<h4>Create Comment</h4>
<div class="form-group">
<input type="text" class="form-control" name="body" id="" placeholder="Input...">
</div>
<button type="submit" class="btn btn-primary">Comment</button>
</form>
</div>
user model
public function threads(){
return $this->hasMany(Thread::class);
}
thread model
public function user()
{
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->morphMany(Comment::class,'commmentable');
}
comment model
public function commenttable()
{
return $this->morphTo();
}
public function user()
{
return $this->belongsTo(User::class);
}
comment controller
public function addThreadComment(Request $request, Thread $thread)
{
$this->validate($request,[
'body' => 'required|min:10|max:250'
]);
$comment = new Comment();
$comment->body = $request->body;
$comment->user_id = auth()->user()->id;
$thread->comments()->save($comment);
}
web.php
Route::resource('comment','CommentController', ['only' =>['update','destroy']]);
Route::post('comment/create/{thread}','ThreadController#storeComment')->name('threadcommment.store');
there where typos in the code
public function comments()
{
return $this- >morphMany(Comment::class,'commmentable');
}
Route::post('comment/create/{thread}','ThreadController#storeComment')->name('threadcommment.store');
triple MMM instead of 2 mm

Logical complex insert into 2 following tables - Laravel

I have a house management project and i am trying to execute a complex function that consists of:
Each time i insert a new Bill into the DB, another table will be filled creating a new row for each share of this bill according to the number of flatmates this house has. I managed to insert into the Bills table but the program returns me to the expected page but with no insert into the Shares table. Not sure if logically i'm doing alright. The code bellow is how i tried to retrieve information of the last insert into the Bills table, which should then have its objects properties used into the Shares table. Does someone have any clue on how i can i proceed?
This is my controller function:
public function store(Request $request){
$bill = Bill::create($request->all());
$users = User::where('house_id', Auth::user()->house->id);
$nflatmates = Auth::user()->house->nflatmates;
$shared_amount = $bill->bill_amount / $nflatmates;
foreach($users as $user){
$data = ['user_id'=>$user->id,
'bill_id'=>$bill->id,
'share_amount'=>$shared_amount];
Share::create($data);
}
return redirect('/admin/bills');
}
This is my form blade. I believe the problem doesnt come from here. Just in case.
{!! Form::open(['method'=>'post', 'action'=>'AdminBillsController#store']) !!}
<div class="form-group' has-error' : '' }}">
<div class="col-md-6">
{!! Form::text('description',null,['class'=>'form-control', 'placeholder'=>'Bill Description']) !!}
</div>
</div>
<div class="form-group' has-error' : '' }}">
<div class="col-md-6">
{!! Form::number('bill_amount',null,['class'=>'form-control', 'placeholder'=>'Amount', 'required|between:0,99.99']) !!}
</div>
</div>
<input type="hidden" name="house_id" value="{{Auth::user()->house->id}}">
<br>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Register
</button>
</div>
</div>
{!! Form::close() !!}
These are my relationships:
This is the Share Model
<?php
namespace App;
use App\User;
use App\Bill;
use Illuminate\Database\Eloquent\Model;
class Share extends Model{
protected $fillable = [
'id', 'user_id', 'bill_id', 'share_amount', 'share_status'
];
public function user(){
return $this->belongsTo('App\User');
}
public function bill(){
return $this->belongsTo('App\Bill');
}
}
And this is the Bill Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\House;
use App\User;
use App\Share;
class Bill extends Model{
protected $fillable = [
'id', 'description', 'bill_amount', 'house_id'
];
public function house(){
return $this->belongsTo('App\House');
}
public function share(){
return $this->hasMany('App\Share');
}
}
This is the User Model:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\House;
use App\Role;
use App\Task;
use App\Share;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'id','name', 'email', 'is_active','house_id','role_id','password',
];
protected $hidden = [
'password', 'remember_token',
];
public function house(){
return $this->belongsTo('App\House');
}
public function role(){
return $this->belongsTo('App\Role');
}
public function task(){
return $this->hasMany('App\Task');
}
public function share(){
return $this->hasMany('App\Share');
}
}
And this is the house Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\User;
use App\Bill;
class House extends Model {
protected $fillable = [
'id','house_address', 'house_admin', 'nflatmates'
];
public function user(){
return $this->hasMany('App\User');
}
public function bill(){
return $this->hasMany('App\Bill');
}
}
The thing is that you obviously have oneToMany relationship there, so what you want to do is something like this.
public function store(Request $request){
$bill = Bill::create($request->all());
$users = User::where('house_id', Auth::user()->house->id);
$nflatmates = Auth::user()->house->nflatmates;
$shared_amount = $bill->bill_amount / $nflatmates;
foreach($users as $user){
$data = [
'share_amount' => $shared_amount,
'share_status' => 'XXXXXX'
];
$share = new Share($data);
//Associating user with this share
$share->user()->associate($user);
//Associating bill with this share
$share->bill()->associate($bill);
//Saving share
$share->save();
}
return redirect('/admin/bills');
}
EDIT:
In order for the code above to work, you must have a valid relationships set across your models.
EDIT 2:
I thought that nflatmates was a oneToMany relationship, but it isn't so there is no need for attach function.
We are now creating a Share object and through it's relationships that are defined we are using associate function based on Belongs To Relationships which you can find on official docs, just scroll down a bit.

Categories