I'm trying to seed a couple of databases with laravel seeder, but it seems that it skips some fields..
I'm doing it this way:
Item::create(array(
'name' => 'Category 2',
'photo' => 'Description of category 2',
'order' => 1
'price' => 2.30
'category_id' => 1,
));
The fields 'category_id' and order are not setup in the database..
I'm calling the seeder this way
Artisan::call('db:seed',array('--database' => 'tenant_'.$user, '--class' => 'TenantSeeder'));
Any idea why does it happen?
If I use the standard
$item = new Item;
$item->allfields = "its_value";
$item->save();
It works perfectly
UPDATE
Here comes the model:
<?php
class Item extends Model {
//============================================================================
// PARENT VARIABLES
//============================================================================
protected $table = "items";
protected $softDelete = true;
protected $hidden = ['created_at','updated_at'];
protected $fillable = ['name','price','description','photo']; //Items that can be mass assigned
protected $guarded = array('id');
protected static $rules = [
'name' => 'required|min:3',
'price' => '',
'description' => '',
];
//============================================================================
// METHODS
//============================================================================
public function getId() { return $this->getKey(); }
public function getName() { return $this->name; }
public function getPhotoSrc() { return $this->photo; }
public function item_category(){
return $this->belongsTo('Items_category');
}
public function scopeActive($query)
{
return $query->where('active', '=', true);
}
}
And the Scheme
Schema::create('items', function(Blueprint $table)
{
// auto increment id (primary key)
$table->increments('id');
$table->string('name')->default('New Item');
$table->float('price')->default(0);
$table->string('photo')->nullable();
$table->integer('order')->unsigned();
$table->boolean('active')->default(true);
$table->string('description')->nullable();
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('items_categories')->onDelete('cascade');
// created_at, updated_at DATETIME
$table->timestamps();
$table->softDeletes(); //It is not really deleted, just marked as deleted
});
Any idea?
As User2094178 said,
I didn't have the fields in the $fillable
Related
I'm new to Laravel so I struggle. I have a comment system that worked perfectly fine but now I want to also add a reply system to it. So the way I decided to do it, is by adding a parent_id column to the comments table and then check if a comment has a parent. But I don't know how exactly the store method, in this case, should work. Here's my database set up for comments:
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->foreignId('post_id')->constrained()->cascadeOnDelete();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->text('body');
$table->timestamps();
});
}
And now a set up for the reply column:
public function up()
{
Schema::table('comments', function (Blueprint $table) {
$table->unsignedBigInteger('parent_id')->nullable();
$table->foreign('parent_id')->references('id')->on('comments');
});
}
Model:
class Comment extends Model{
use HasFactory;
protected $guarded = [];
public function post()
{
return $this->belongsTo(Post::class);
}
public function author()
{
return $this->belongsTo(User::class, 'user_id');
}
public function replies() {
return $this->hasMany('App\Comment', 'parent_id');
}
}
Controller:
public function store(Post $post){
request()->validate([
'body' => 'required'
]);
$post->comments()->create([
'user_id' => request()->user()->id,
'parent_id' => request()->get('id'),
'body' => request('body')
]);
return back();
}
I just don't know how exactly I can get parent_id in the store function so I would appreciate some suggetstions
it should be the comment id that got the reply
something like this
$post->comments()->create([
'user_id' => request()->user()->id,
'parent_id' => request()->get('comment_id'),
'body' => request('body')
]);
I hope it's helpful
use code :
public function store(Post $post) {
request()->validate([
'body' => 'required'
]);
$post->comments()->create([
'user_id' => request()->user()->id,
'parent_id' => request()->get('comment_id'),
'body' => request('body')
]);
return back();
}
i have manytomany relation ship between categroy and product
category model
class Attribute extends Model implements Auditable
{
use HasFactory, AuditableTrait;
protected $fillable = ['category','sub_categ'];
public function products(): BelongsToMany
{
return $this->belongsToMany(Product::class);
}
}
product model
class Product extends Model implements Auditable
{
use HasFactory, AuditableTrait;
protected $table = 'products';
protected $fillable = ['name','price','description', 'details'];
public function products(): BelongsToMany
{
return $this->belongsToMany(Product::class);
}
}
the pivot table
Schema::create('attributes_products', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->foreignId('product_id')->constrained('products')->onUpdata('cascade')->onDelete('cascade');
$table->foreignId('attribute_id')->constrained('attributes')->onUpdata('cascade')->onDelete('cascade');
});
what should i do after this i did not undrestant how attach will work in pivot table and return it with the product as json response ?
edit
this is the schema i am working on
i want to give each product it's own category
and this is my product controller store function
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'price' => 'required|numeric',
'description' => 'required',
'details' => 'required',
'stocks' => 'required|numeric',
//'discounts' => 'required|numeric'
]);
$product = Product::create($request->only('name','price','description', 'details'));
$product->stocks()->create([
'quantity' => $request->stocks,
'product_id' => $product->id
]);
$product->discounts()->create([
//'discount' => $request->discounts,
'product_id' => $product->id
]);
if($request->hasFile('images'))
{
foreach( $request->file('images') as $file)
{
$file->store('public/products');
$product->images()->create([
'product_id' => $product->id,
'file_path' => $file->hashName()
]);
}
}
$product->categories()->sync([
'product_id' => $product->id,
'attribute_id'=> 1
]);
}
In your product model check your relation.
public function categories()
{
return $this->belongsToMany(Category::class);
}
Also usually the pivot table needs to have only 2 Ids. So in your case only 2 columns: product_id & category_id.
Your table name by convention should be category_product, otherwise, you should specify it on the second parameter on the relationship.
Fix this too, you got a typo on update:
$table->foreignId('attribute_id')->constrained('attributes')->onUpdate('cascade')->onDelete('cascade');
And finally to attach:
$product = Product::find(1);
$product->categories()->attach($categoryId);
All is explained very well on documentation too: https://laravel.com/docs/8.x/eloquent-relationships
Hi I have more than 500k records in items table Its takes more than 9 seconds to execute this query ineed to make it milliseconds to execute this query using mysql index
$products = \App\items::with([
'item_store' => function($query) {
$query->select('size', 'item_id', 'item_store_id');
},
'pics' => function($query) {
$query->select('img_url', 'item_id');
},
'brand' => function($query) {
$query->select('item_id', 'brand_id');
},
'brand.brand' => function($query) {
$query->select('brand_id', 'brand_name');
}
])
->select('item_id', 'short_name', 'price', 'price_above')
->orderBy('Price', 'Asc')->whereIn('category_id', $arr)
->groupBy('Sku')
->paginate(20);
my database structure is [st] https://screenshots.firefox.com/JAmaKENMYRhQkEjx/ourweds.com
this is item table migration
Schema::create('item', function (Blueprint $table) {
$table->bigIncrements('item_id');
$table->string('item_name');
$table->integer('Sku');
$table->text('Description');
$table->text('short_description');
$table->text('category_id');
$table->string('color');
$table->double('price');
$table->double('indian_price');
$table->string('old_price');
$table->string('indian_old_price');
$table->timestamps();
});
item eloquent model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class items extends Model
{
//
protected $table = 'items';
protected $primaryKey = 'item_id';
protected $fillable = [
'category_id',
'item_name',
'Sku',
'Description',
'short_description',
'color',
'kik_cash_percentage',
'status',
'price',
'price_old',
'indian_price',
'short_name',
'price_above',
'short_name_alter',
'availability'
];
public function pics(){
return $this->hasOne( 'App\item_pics', 'item_id' );
}
public function item_store()
{
return $this->hasMany('App\item_store','item_id');
}
public function category()
{
return $this->belongsTo('App\categories','category_id');
}
public function brand()
{
return $this->hasOne('App\item_has_brand','item_id');
}
}
I'm studying some Laravel and at some point I had to re-migrate the database because I had to change a table. I'm using postman to do testing, and one of the api methods give me the error:
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: events.user_id (SQL: insert into "events" ("sport", "title", "players", "when", "description", "location", "updated_at", "created_at") values (Hockey, Grass Hockey, 12, 30/09/2018, Come join us, Fairview park, 2018-11-08 22:19:45, 2018-11-08 22:19:45))
so it seems to be a problem with the events.user_id which I changed on a table called Events to have a relationship with the Users table. Some examples I found by researching is on table fields that were not ids, so I don't how to figure this one out, maybe some of you can help me!
here are the migrations for Events and Users:
public function up()
{
Schema::create('events', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
$table->string('sport');
$table->string('title');
$table->decimal('players', 8, 2);
$table->date('when');
$table->mediumText('description');
$table->string('location');
$table->timestamps();
});
}
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Here are the models:
class Event extends Model
{
protected $fillable = [
'sport',
'title',
'players',
'when',
'description',
'location'
];
public function user()
{
return $this->belongsTo('App\User');
}
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function events()
{
return $this->hasMany('App\Event');
}
}
And below is the api method that is giving me the error:
Route::post('/admin/create-event', function (Request $request) {
$data = $request->all();
$event = Event::create(
[
'sport' => $data['sport'],
'title' => $data['title'],
'players' => $data['players'],
'when' => $data['when'],
'description' => $data['description'],
'location' => $data['location'],
]
);
return $event;
});
Thanks guys!
Edit:
Route::middleware('auth:api')->post('/admin/create-event', function (Request $request) {
$user = $request->user();
$data = $request->all();
$event = Event::create(
[
'user_id' => \Auth::user()->id,
'sport' => $data['sport'],
'title' => $data['title'],
'players' => $data['players'],
'when' => $data['when'],
'description' => $data['description'],
'location' => $data['location'],
]
);
return $event;
});
I think you have to add 'user_id' to $fillable of Event class:
class Event extends Model
{
protected $fillable = [
'sport',
'title',
'players',
'when',
'description',
'location',
'user_id'
];
public function user()
{
return $this->belongsTo('App\User');
}
}
You need to pass the user_id:
'user_id' => \Auth::user()->id
The example above requires an authenticated user in the session, but if you are making the request using postman you probably don’t have one.
Anyway, you need to provide the user_id that will be stored in the database.
EDIT
Eloquent's method create will copy to the model only the attributes defined as fillable. So you have two options:
Add user_id to $fillable
Use newInstance instead of create, manually set the user_id with $event->user_id = ..., and manually save the $event model with $event->save();
I have a model Foo, which has many Bars:
class Foo extends Model
{
public function bars()
{
return $this->hasMany('App\Bar');
}
}
class Bar extends Model
{
public function foo()
{
return $this->belongsTo('App\Foo');
}
}
When saving a new Foo, the request payload comes with an array of Bar ids. I want to save these at the same time. This works:
public function store(StoreFoo $request)
{
$foo = Foo::create($request->validated());
foreach ($request->barIds as $barId) {
$foo->bars()->create(['bar_id' => $barId]);
}
}
My question is: is there a way to do this without a loop? I've tried sync and attach but these aren't applicable in this case.
The only way I can think of that you can achieve this without writing a loop yourself is by using the saveMany method on the HasMany relation. You can create instances of your Bar model and pass them all as an array to the saveMany method and that will save all of them and return an array of the created entities in response.
$foo->bars()->saveMany([new Bar(['id' => 1]), new Bar(['id' => 2])]);
That being said, Laravel uses a loop to save these models one by one under the hood so it doesn't really do much different to what you're doing now.
Similarly, there's also a createMany method that you can use in the same way as saveMany but instead of providing newly created models, you can provide arrays of attributes instead.
migration table sample
Schema::create('logs', function(Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id')->default(0)->index();
$table->string('type', 10)->index(); // add, update, delete
$table->string('table', 50)->index();
$table->unsignedBigInteger('row');
$table->dateTime('created_at');
});
Schema::create('log_fields', function(Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('log_id')->index();
$table->string('field', 50)->index();
$table->longText('old');
$table->longText('new');
});
model Log.php file
class Log extends Model
{
const UPDATED_AT = null;
protected $fillable = [
'user_id',
'type',
'table',
'row'
];
public function logFields()
{
return $this->hasMany(LogField::class);
}
}
model LogField.php file
class LogField extends Model
{
public $timestamps = false;
protected $fillable = [
'field',
'old',
'new'
];
public function log()
{
return $this->belongsTo(Log::class);
}
}
boot function for another model for save change in database.
hook created, updating and deleting for answer your question
public static function boot()
{
parent::boot();
static::created(function($resorce) {
$_log = new Log;
$_log->create([
'user_id' => session('uid', 0),
'type' => 'add',
'table' => $resorce->getTable(),
'row' => $resorce->fresh()->toArray()['id']
]);
return true;
});
static::updating(function($resorce) {
$_log = new Log;
$log = $_log->create([
'user_id' => session('uid', 0),
'type' => 'update',
'table' => $resorce->getTable(),
'row' => $resorce->fresh()->toArray()['id']
]);
foreach($resorce->getDirty() as $field => $new) {
$log->logFields()->create([
'field' => $field,
'old' => $resorce->fresh()->toArray()[$field],
'new' => $new
]);
}
return true;
});
static::deleting(function($resorce) {
$_log = new Log;
$log = $_log->create([
'user_id' => session('uid', 0),
'type' => 'delete',
'table' => $resorce->getTable(),
'row' => $resorce->id,
]);
foreach($resorce->fresh()->toArray() as $field => $value) {
$log->logFields()->create([
'field' => $field,
'old' => '',
'new' => $value
]);
}
return true;
});
}
Hope I have helped you to understand this.