If I create a comment like this:
$post->comments()->create(array('body' => 'Comment message'));
And I have the model on my post:
public function comments()
{
return $this->morphMany('Comment', 'shared_comments');
}
It fills the polymorphic relationship field between post and comment.
I also have the model on my comment:
public function author()
{
return $this->belongsTo('User');
}
How can I also fill the 'user_id' field in the comment table?
You can just explicitly specify the user id in the array.
$post->comments()->create(array(
'body' => 'Comment message',
'user_id' => Auth::user()->id
));
Alternatively, you could create the comment and then insert the relationship with both the posts and users tables.
$post = Post::find($whatever);
$user = Auth::user()->id;
$comment = Comment::create(array(
'body' => 'Comment message'
));
$post->comments()->insert($comment);
$user->comments()->insert($comment);
In Laravel 4, you would use save($comment) instead of insert($comment) for the last two lines. This is a breaking change from Laravel 3.
Related
I just started learning Laravel, I'm newbie. I've got a problem, I'm watching Laravel Course for beginners and learning, was doing exactly the same as in he tutorial, but still ended up with a problem. I hope to find a solution soon. I'll explain it a little bit.
The project is kind of a clone of Instagram. Users can post images to page.
I have this function in User model
User.php
public function posts()
{
return $this->hasMany(Post::class);
}
And I'm trying to access it from my PostsController
PostsController.php
class PostsController extends Controller
{
public function create()
{
return view('posts.create');
}
public function store()
{
$user = auth()->user();
$data = request()->validate([
'caption' => 'required',
'image' => ['required', 'image']
]);
auth()->user()->posts()->create($data);
\App\Models\Post::create($data);
dd(request()->all());
}
}
I'm doing exactly as in tutorial, but for some reason this line is failing at posts() call.
auth()->user()->posts()->create($data);
I'm getting that it's undefined method. But it is indeed defined in User.php
EDIT:
Exact error I'm getting is:
Illuminate\Database\QueryException
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: posts.user_id (SQL: insert into "posts" ("caption", "image", "updated_at", "created_at") values (Caption, C:\xampp\tmp\php2E32.tmp, 2021-05-19 12:16:08, 2021-05-19 12:16:08))
And foreign key is user_id.
Actually I just checked my posts table and it seems it is stored in database, so it's working, but how to get rid of this error then?
this is a silly mistake of you..you are adding same post twice. once with relationship association and again from post model.
auth()->user()->posts()->create($data);
\App\Models\Post::create($data); //this is causing the issue here.
with relationship association auth()->user()->posts()->create($data), post is inserted to the database. as the foreign key user_id is coming from relationship. but in the next line \App\Models\Post::create($data), your $data array is missing user_id and thus the NOT NULL constraint failed error occurs. you can't insert a row with user_id being null. and this line is actually adding duplicate data. remove this line. use either one of the method.
with relationship association
$data = request()->validate([
'caption' => 'required',
'image' => ['required', 'image']
]);
auth()->user()->posts()->create($data);
or using model directly
$data = request()->validate([
'caption' => 'required',
'image' => ['required', 'image']
]);
$data['user_id'] = auth()->user()->id; //added user_id in the validated data array
\App\Models\Post::create($data);
and vs code always don't know all of your functions. depending on vs code to find a problem is not the best way.
Note:: you need to use Post Model and you can directly create data Using Post::create() method.
//Import Data
use Illuminate\Http\Request;
use App\Modes\Post;
class PostsController extends Controller
{
public function create()
{
return view('posts.create');
}
public function store(Request $request)
{
//Check Validation
$data = request()->validate([
'caption' => 'required',
'image' => ['required', 'image']
]);
//Get Login User Data in $user variable
$user = auth()->user();
//Store user id into $data variable which we can pass into $data Variable.
$data[‘user_id’] = $user->id;
//Create Data Using create() method.
$post = Post::create($data);
//Final Save Your Data
if( $post->save() ) {
dd(“data save successfully”);
}else{
dd(“something went wrong”);
}
}
}
I am new on Laravel 6 and would like to add data to a column. I have a table called 'projects'. This table has a column named 'comments'. My purpose is to only add data to the 'comments' column by updating a project.
I have a ProjectController containing a method storeComment which is as follows:
public function storeComment(Request $request, Project $project)
{
$validData = $request->validate([
'project_id' => 'required',
'comments' => 'required'
]);
$project->comments = $validData['comments'];
$project->save();
return redirect('home')->with('status', 'Comment created successfully');
}
The problem is that the method creates a new record instead of updating an existing one. Is there anybody who could help? Thanks in advance
public function updateComments(Request $request, $id)
{
$projects = Project::find($id);
$projects->comments = $request->comments;
$projects->save();
}
You need to fetch the record first, then update comments of that record like this:
use App\Project;
public function storeComment(Request $request) {
$request->validate([
'project_id' => 'required',
'comments' => 'required'
]);
$project = Project::find($request->project_id);
$project->comments = $request->comments;
$project->save();
return redirect('home')->with('status', 'Comment created successfully');
}
Update I have solved the problem I just forgot the get() here
$userDiplomas = UserDiploma::query()->where( 'user_id', Auth::user()->id );
but still didn't understand why I was not able to use this
Auth::user()->diplomas as $diploma
Here is my case
each user may registered to a diploma or more, now in the user profile I want to display all the diplomas that users registered to.
I made a new table called user_diplomas and here is the table migration
$table->integer( 'user_id' )->unsigned();
$table->foreign( 'user_id' )->references( 'id' )->on( 'users' );
$table->integer( 'diploma_id' )->unsigned();
$table->foreign( 'diploma_id' )->references( 'id' )->on( 'diplomas' );
when user are login and clicks on register now, it inserts 2 values to the user_diplomas table (user_id, diploma_id) this is working fine.
now comes the question
I need to get the user registered diplomas and display them in his profile, please take a look at the User Model and the UserDiploma Model.
User Model
public function diplomas() {
return $this->hasMany( 'App\Models\UserDiploma', 'diploma_id' );
}
UserDiploma Model
public function diplomaId() {
return $this->belongsTo( 'App\Models\Diploma', 'diploma_id' );
}
now trying to fetch the diplomas I try this
#foreach(Auth::user()->diplomas as $diploma)
....
..........
#endforeach
But no results are coming out!
I also try to do something like this in the HomeController
public function index() {
$userDiplomas = UserDiploma::query()->where( 'user_id', Auth::user()->id );
return view( 'trainees.profiles', compact('userDiplomas') );
}
but it didn't work too.
any ideas please how to make it work.
Change method in 'User' model to
public function diplomas() {
return $this->hasMany( 'App\Models\UserDiploma', 'diploma_id','diploma_id' );
}
I'm working on laravel e-commerce project where I need to add Attributes to my posts (image below as example)
My question is how to achieve that? should i create new tables or can I add manually from post.create like any other e-commerce cms?
Personally I prefer to be able to add fields in post.create like I
add + button and each time I click on it 2 input fields add and I
can put key and value in it. (if you can help me with that)
Thanks.
Update:
With suggest of #anas-red I've created this structure now:
attributes table.
Schema::create('attributes', function (Blueprint $table) {
$table->increments('id');
$table->string('title')->unique();
$table->timestamps();
});
and product_attributes table
Schema::create('product_attributes', function (Blueprint $table) {
$table->increments('id');
$table->integer('product_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products');
$table->integer('attribute_id')->unsigned();
$table->foreign('attribute_id')->references('id')->on('attributes');
$table->string('attribute_value')->nullable();
$table->timestamps();
});
now i have this store method on my controller when i save my posts:
public function store(Request $request)
{
//Validating title and body field
$this->validate($request, array(
'title'=>'required|max:225',
'slug' =>'required|max:255',
'user_id' =>'required|numeric',
'image_one' =>'nullable|image',
'image_two' =>'nullable|image',
'image_three' =>'nullable|image',
'image_four' =>'nullable|image',
'image_one' =>'nullable|image',
'short_description' => 'nullable|max:1000',
'description' => 'nullable|max:100000',
'subcategory_id' => 'required|numeric',
'discount' => 'nullable|numeric',
'discount_date' => 'nullable|date',
'price' => 'required|numeric',
));
$product = new Product;
$product->title = $request->input('title');
$product->slug = $request->input('slug');
$product->user_id = $request->input('user_id');
$product->description = $request->input('description');
$product->short_description = $request->input('short_description');
$product->subcategory_id = $request->input('subcategory_id');
$product->discount = $request->input('discount');
$product->discount_date = $request->input('discount_date');
$product->price = $request->input('price');
if ($request->hasFile('image')) {
$image = $request->file('image');
$filename = 'product' . '-' . time() . '.' . $image->getClientOriginalExtension();
$location = public_path('images/');
$request->file('image')->move($location, $filename);
$product->image = $filename;
}
$product->save();
$product->attributes()->sync($request->attributes, false);
//Display a successful message upon save
Session::flash('flash_message', 'Product, '. $product->title.' created');
return redirect()->route('admin.products.index');
}
The process i want to do is this:
Store my attributes
Select my attributes while creating new post
Give value to selected attribute
save post_id arribute_id and atteribute_value in product_attributes table.
here is the error i get:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'attributes_id'
in 'field list' (SQL: select attributes_id from product_attributes
where product_id = 29)
UPDATE:
Product model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use jpmurray\LaravelCountdown\Traits\CalculateTimeDiff;
class Product extends Model
{
use CalculateTimeDiff;
protected $table = 'products';
protected $fillable = [
'title', 'slug', 'image_one', 'image_two', 'image_three', 'image_four', 'short_description', 'description', 'price', 'discount', 'discount_date',
];
public function category(){
return $this->belongsTo(Category::class);
}
public function subcategory(){
return $this->belongsTo(Subcategory::class);
}
public function attributes()
{
return $this->belongsToMany(Attribute::class, 'product_attributes', 'product_id', 'attribute_id');
}
public function order(){
return $this->hasMany(Order::class);
}
public function discounts(){
return $this->hasMany(Discount::class, 'product_id', 'id');
}
}
Attribute model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Attribute extends Model
{
protected $fillable = [
'title',
];
public function products(){
return $this->belongsToMany(Product::class);
}
}
I think you can add new table lets say "post_attributes" with the following columns:
id - post_id - key - value
in the PostAttribute model add this:
public function post
{
return $this->belongsTo(Post::class);
}
in the Post model add the following:
public function attributes
{
return $this->hasMany(PostAttributes::class, 'post_attributes');
}
Now the app is flexible enough to handle multiple attributes to one post or a single attribute to another.
Other approach is to implement JSON in your database. Hope that helped you.
update Product model
public function attributes()
{
return $this->belongsToMany(Attribute::class, 'product_attributes', 'product_id', 'attribute_id')->withPivot('attribute_value')->withTimestamps();
}
and update Attribute model to
public function products()
{
return $this->belongsToMany(Product::class, 'product_attributes', 'attribute_id', 'product_id')->withPivot('attribute_value')->withTimestamps();
}
If I see your Product and Attribute Models I will be in a better position to answer you properly.
But any way, I think your problem is with the product_attributes table.
This table is now acting as a pivot (intermediate) table and it is not following Laravel naming convention. The convention is to name it as follows: attribute_product.
Next, you have to add the following into both models i.e. Product and Attribute.
in Attribute Model add:
$this->belongsToMany(Product::class)->withPivot('value');
in Product Model add:
$this->belongsToMany(Attribute::class)->withPivot('value');
To add value to more_value column on pivot table. Use the following:
$product->attributes()->attach($attributeId, ['more_value' => $string]);
or use sync:
$product->attributes()->sync([$attributeId => ['more_value' => $string]]);
lol. the important part is repo code is:
<input type="hidden" id="appOrderItems" name="orderItems[]">
trace appOrderItems in my JS section and you will get it.
in simple words:
when the user adds attributes to a product (in my case, items to an order) then, the appOrderItems array will get the id of the attribute and any additional value that you need to add into the pivot table (other than the product_id and attribute_id. in your case the mores_value). After gathering these attributes into appOrderItems JS array I push its value to the hidden HTML field (name="orderItems[]"). in this case it will be sent to the controller for further process.
I'm trying to join my comment table with my user table like this comment.userId=user.id
unfortunately when i print_r($this->user); i get nothing. what am i doing wrong here?
in my comment model
public function relations()
{
return array(
'user' => array(self::BELONGS_TO, $this->module->user, 'userId'),
);
}
public function getLastName()
{
print_r($this->user);
die;
return is_null($this->user) ? '' : $this->user->{$this->module->lastNameAttribute};
}
where
$this->module->user = 'User'; //User is the model name
and
$this->module->lastNameAttribute = 'last_name';
in my view
$comments = $model->getCommentDataProvider();
$comments->setPagination(false);
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$comments,
'itemView'=>'application.modules.comment.views.comment._view', //view file location
'emptyText' => '<div class="alert alert-info">No comments yet.</div>',
'summaryText' => '<h4>'.Yii::t('commentTitle','{n} comment|{n} comments',$comments->totalItemCount).'</h4>'
));
I see a small typo, maybe you mistaken while making a post:
comment.userid=user.id
here it's userid and in relation you referenced it with userId
check it out please
EDIT - after question edit
I'm not familiar with CommentableBehavior but it seems to me that you need to eager load User model with each Comment:
$comments = Yii::createComponent($this->module->commentModelClass)->with('user')->findAll($this->getCommentCriteria());
I added with('user') in getComments() method