i am facing a problem. i am new in laravel . i created many to many relation in my application.but it's shown error. please check bellow code :
Error
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'post_id' cannot be null (SQL: insert into `category_post` (`category_id`, `created_at`, `post_id`, `updated_at`) values (1, 2019-11-09 17:00:29, ?, 2019-11-09 17:00:29))
Post Model code :
public function categories()
{
return $this->belongsToMany('App\Category')->withTimestamps();
}
Category model code
public function posts()
{
return $this->belongsToMany('App\Post')->withTimestamps();
}
PostController Code
public function store(Request $request)
{
$this->validate($request,[
]);
$image = $request->file('image');
$slug = str_slug($request->name);
if(isset($image))
{
$imageName = $slug.'-'.time().uniqid().'.'.$image->getClientOriginalExtension();
if(!Storage::disk('public')->exists('posts/'))
{
Storage::disk('public')->makeDirectory('posts/');
}
$postImage = Image::make($image)->resize(1600,1066)->stream();
Storage::disk('public')->put('posts/'.$imageName,$postImage);
}else{
$imageName = 'default.png';
}
$posts = new Post();
$posts->user_id =Auth::id();
$posts->title = $request->title;
$posts->slug = $slug;
$posts->body = $request->body;
$posts->image = $imageName;
$posts->categories()->attach($request->categories);
$posts->tags()->attach($request->tags);
$posts->is_approved = true;
if(isset($request->status))
{
$posts->status = true;
}else{
$posts->status = false;
}
$posts->save();
// $posts->tags()->attach($request->tags);
Toastr::success('Post Is created successfully','Success');
return redirect()->route('admin.posts.index');
}
My create.blde.php file code is okey all request goes appropriately but above error shown when i submit my post..Thank in advance
You have a belongs to many relationship between posts and categories. In order to create that relationship on your pivot table, you must have a category_id and a post_id.
This line in your code:
$posts->categories()->attach($request->categories);
is correct, but you are trying to attach the categories to the post object before you have saved it. Thus, the unsaved post object has no id yet.
Save your post, and then attach the categories with the attach() method you have already written.
Same thing with your tags() attachment. Stick it in after you have saved the post object.
Related
I have this 3 table:
stations (id,station_name)
products (id,product_name)
pivot table
product_station (station_id,product_id, tank_volum)
Station Model
public function products(){
return $this->belongsToMany(Product::class)
->withTimestamps()
->withPivot('tank_volume');
}
Product Model
public function stations(){
return $this->belongsToMany(Station::class);
}
I'm trying to create a station with many products and every product
have it's tank volume but i can't save the tank volume value to
database:
product_station table
this is my controller:
public function store(StationsRequest $request)
{
// dd($request);
$input = $request->all();
if($file = $request->file('photo_id')) {
$name = time() . $file->getClientOriginalName();
$file->move('images', $name);
$photo = Photo::create(['file'=>$name]);
$input['photo_id'] = $photo->id;
}
$station = Station::create($input);
$station->products()->sync($request->products , false);
return redirect('/admin/stations');
}
Q: How can i Save Tank volume inside product_station table "pivot table" ?
if you want to sync() related extra fields :
$product_ids = [];
foreach ($station->products as $product) {
//collect all inserted record IDs
$product_ids[$product->id] = ['tank_volume' => 'tank_volume_value'];
}
//if you want to pass new id from new query
//$product_ids['new_created_product->id'] = ['tank_volume' => 'tank_volume_value'];
then
$station->products()->sync($product_ids);
in this case, better use attach() :
$station = Station::create(['fields']);
$station->products()->attach([$product->id => ['tank_volume'=>'value']]);
So I got posts page, where I have my post. The post has ID which leads to posts table. For it I have PostsController where everything is accessible thru $post->id, $post->name etc.
But I have another table named orders and on submit button, it needs some of the information from posts table by id.
I have post with url posts/{id} and there's submit button in the view
The button needs to get $post information to OrdersController with submit information.
I've tried this in OrdersController
public function store(Request $request)
{
$this->validate($request, [
]);
$post = Post::all();
$order = new Order;
$order->client = Auth::user()->name;
$order->phone = Auth::user()->phone;
$order->vehicle = $post->id;
$order->date_from = $request->input('date_from');
$order->save();
return redirect('/posts')->with('success', 'Rezervēts');
}
$posts = Post::all(); is getting all array information from table but cannot use specific id.
And I have this in PostsController
public function show($id)
{
$post = Post::find($id);
$images = Image::All();
return view('posts.show')->with(compact('post', 'images'));
}
Route for show function
Error that I'm getting with shown code: Property [id] does not exist on this collection instance.
Expected results:
orders table
Error: Property [id] does not exist on this collection instance.
Problem: Can't get exact id from view to another controller, so I can access posts table records that I need from OrdersController.
Ps. I've been thru most of the pages on this error, but can't seem to find the one that would help.
I would modify the route so that the affected post.
Route:
Route::post('/order/{post}/store', 'OrderController#store')->name('order.store');
Controller (store method):
public function store(Post $post, Request $request){
$this->validate($request, [
]);
$order = new Order;
$order->client = Auth::user()->name;
$order->phone = Auth::user()->phone;
$order->vehicle = $post->id;
$order->date_from = $request->input('date_from');
$order->save();
return redirect('/posts')->with('success', 'Rezervēts');
}
Okay, thanks.
Solved: {{ Form::hidden('id', $post->id) }} in view.
Controller: $post = Post::findorfail($request->id);
Then: $post->(whatever you need from table)
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've created a form which adds a category of product in a Categories table (for example Sugar Products or Beer), and each user has their own category names.
The Categories table has the columns id, category_name, userId, created_At, updated_At.
I've made the validation and every thing is okay. But now I want every user to have a unique category_name. I've created this in phpMyAdmin and made a unique index on (category_name and userId).
So my question is this: when completing the form and let us say that you forgot and enter a category twice... this category exist in the database, and eloquent throws me an error. I want just like in the validation when there is error to redirect me to in my case /dash/warehouse and says dude you are trying to enter one category twice ... please consider it again ... or whatever. I am new in laravel and php, sorry for my language but is important to me to know why is this happens and how i solve this. Look at my controller if you need something more i will give it to you.
class ErpController extends Controller{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('pages.erp.dash');
}
public function getWarehouse()
{
$welcome = Auth::user()->fName . ' ' . Auth::user()->lName;
$groups = Group::where('userId',Auth::user()->id)->get();
return view('pages.erp.warehouse', compact('welcome','groups'));
}
public function postWarehouse(Request $request)
{
$input = \Input::all();
$rules = array(
'masterCategory' => 'required|min:3|max:80'
);
$v = \Validator::make($input, $rules);
if ($v->passes()) {
$group = new Group;
$group->group = $input['masterCategory'];
$group->userId = Auth::user()->id;
$group->save();
return redirect('dash/warehouse');
} else {
return redirect('dash/warehouse')->withInput()->withErrors($v);
}
}
}
You can make a rule like this:
$rules = array(
'category_name' => 'unique:categories,category_name'
);
I am totally new on Laravel, and I have implement the User table provided by Laravel Auth, and also I have create a table for the user meta data that is a Key Value pare table.
The user meta table is created by the following code :
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class UserMeta extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('user_meta', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->char('meta_key', 255);
$table->longText('meta_value')->nullable();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onUpdate('cascade')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('user_meta');
}
}
In my User model I have the following method:
public function meta() {
return $this->hasMany('App\Models\UserMeta');
}
and inside my UserMeta model I have the following method:
public function user() {
return $this->belongsTo('App\User');
}
Until now anything is fine. So, when I register a new user I perform the following actions:
$user = User::create(
[
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt( $data['password'] ),
]
);
if ( $user ) {
$telephone_number = new UserMeta;
$telephone_number->user()->associate($user);
$telephone_number->meta_key = 'telephone_number';
$telephone_number->meta_value = $data['telephone_number'];
$telephone_number->save();
$company = new UserMeta;
$company->user()->associate($user);
$company->meta_key = 'company';
$company->meta_value = $data['company'];
$company->save();
$web_site = new UserMeta;
$web_site->user()->associate($user);
$web_site->meta_key = 'web_site';
$web_site->meta_value = $data['web_site'];
$web_site->save();
}
return $user;
I suppose that should be a better way to perform that same actions, but I don't know what is the other way :( :)
So, the above code works very nice for me, but now the problem is with the value update. In this case, how can I update the Meta Data when I update the user profile ?
In my update method of my UserControler, I perform the following actions:
$user = User::where( 'id', '=', $id )->first();
$user->name = $request->input( 'name' );
$user->email = $request->input( 'email' );
$user->password = bcrypt( $request->input( 'password' ) );
$user->save();
My $request->input(); has the following extra fields that corresponding to meta values telephone_number, web_site, company.
So, how can I update the meta values in the user_meta table ?
Looping through values
Firstly, you are right that you could loop through the three keys in your create method to:
// Loop through all the meta keys we're looking for
foreach(['telephone_number', 'web_site', 'company'] as $metaKey) {
$meta = new UserMeta;
$meta->meta_key = $metaKey;
$meta->meta_value = array_get($data, $metaKey);
$meta->save();
}
The Update Method: Approach One
Then, in your update method
// Loop through all the meta keys we're looking for
foreach(['telephone_number', 'web_site', 'company'] as $metaKey) {
// Query for the meta model for the user and key
$meta = $user->meta()->where('meta_key', $metaKey)->firstOrFail();
$meta->meta_value = array_get($data, $metaKey);
$meta->save();
}
Note the firstOrFail() to end the query. This is just me being strict. If you wanted to add a meta value if it didn't exist, then you could replace that line with
// Query for the meta model for the user and key, or
// create a new one with that key
$meta = $user->meta()->where('meta_key', $metaKey)
->first() ?: new UserMeta(['meta_key' => $metaKey]);
The Update Method: Approach Two
This approach is a little more efficient, but a more complex (but also potentially teaches about a cool feature of Eloquent!).
You could load in all of the meta keys first (see lazy eager loading).
// load the meta relationship
$user->load('meta');
// Loop through all the meta keys we're looking for
foreach(['telephone_number', 'web_site', 'company'] as $metaKey) {
// Get the first item with a matching key from the loaded relationship
// Or, create a new meta for this key
$meta = $user->meta
->first(function($item) use ($metaKey) {
return $item->meta_key === $metaKey;
}) ?: new UserMeta(['meta_key' => $metaKey]);
$meta->meta_value = array_get($data, $metaKey);
$meta->save();
}