I have 3 models: Priority, Task and User
Priority
can be assigned to many tasks
belongs to one user
Code ...
class Priority extends Model
{
protected $fillable = ['name', 'hexcolorcode'];
protected $casts = [
'user_id' => 'int',
];
public function task()
{
return $this->hasMany(Task::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Task
has one priority assigned
belongs to one user
Code ...
class Task extends Model
{
protected $fillable = ['name'];
protected $casts = [
'user_id' => 'int',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function priority()
{
return $this->hasOne(Priority::class);
}
}
User
can have many tasks
can have many priorities
Code ...
class User extends Authenticatable
{
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function tasks()
{
return $this->hasMany(Task::class);
}
public function priorities()
{
return $this->hasMany(Priority::class);
}
}
TaskController
class TaskController extends Controller
{
protected $tasks;
private $priorities;
public function __construct(TaskRepository $tasks, PriorityRepository $priorities)
{
$this->middleware('auth');
$this->tasks = $tasks;
$this->priorities = $priorities;
}
public function index(Request $request)
{
return view('tasks.index', [
'tasks' => $this->tasks->forUser($request->user()),
'priorities' => $this->priorities->forUser($request->user())
]);
}
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
'description' => 'required',
'priority' => 'required'
]);
$request->user()->tasks()->create([
'name' => $request->name,
'description' => $request->description,
'priority_id' => $request->priority
]);
return redirect('/tasks');
}
public function edit(Task $task)
{
$this->authorize('edit', $task);
return view('tasks.edit', compact('task'));
}
public function update(Request $request, Task $task)
{
$this->validate($request, [
'name' => 'required|max:255',
]);
$task->update($request->all());
return redirect('/tasks');
}
public function destroy(Request $request, Task $task)
{
$this->authorize('destroy', $task);
$task->delete();
return redirect('/tasks');
}
}
Error
Now when I want to store a task it gives me following error:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails (tasks.tasks,
CONSTRAINT tasks_priority_id_foreign FOREIGN KEY (priority_id)
REFERENCES priorities (id)) (SQL: insert into tasks (name,
user_id, updated_at, created_at) values (test task, 1,
2016-05-01 14:11:21, 2016-05-01 14:11:21))
Is it possible with this construct or do I have to use Polymorphic Relations between priority table and tasks table?
My Tables
Database Model Picture: http://picpaste.de/mysql-kBH4tO5T.PNG
class CreatePrioritiesTable extends Migration
{
public function up()
{
Schema::create('priorities', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->char('name');
$table->char('hexcolorcode', 7);
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
}
class CreateTasksTable extends Migration
{
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('name');
$table->text('description');
$table->integer('priority_id')->unsigned();
$table->timestamps();
$table->foreign('priority_id')->references('id')->on('priorities');
$table->foreign('user_id')->references('id')->on('users');
});
}
}
UPDATE
PriorityController
class PriorityController extends Controller
{
protected $priorities;
public function __construct(PriorityRepository $priorities)
{
$this->middleware('auth');
$this->priorities = $priorities;
}
public function index(Request $request)
{
return view('priority.index', [
'priorities' => $this->priorities->forUser($request->user()),
]);
}
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
'hexcolorcode' => 'required|max:7'
]);
$request->user()->priorities()->create($request->all());
return redirect('/priorities');
}
public function edit(Priority $priority)
{
$this->authorize('edit', $priority);
return view('priority.edit', compact('priority'));
}
public function update(Request $request, Priority $priority)
{
$this->validate($request, [
'name' => 'required|max:255',
'hexcolorcode' => 'required|max:7'
]);
$priority->update($request->all());
return redirect('/priorities');
}
public function destroy(Request $request, Priority $priority)
{
$this->authorize('destroy', $priority);
$priority->delete();
return redirect('/priorities');
}
}
In your store method. The create method it says :
user->tasks(). This bit will only inserting data in user and tasks table. Thats why you have foreign key error. As you are not updating one of your tables(priority) and also you have added foreign keys in tables as i csn see from migration.
What you are trying to achieve is right if you had a pivot table called task_user where you had userid, taskid and a priority_id. That would be perfect as you would simply update the priority column with userid and taskid. Thats one way but it will require few changes OR you can insert data into user and tasks table seperately for which you will need to just change the query. What do you prefer? I can show you an example for which you like.
//for Priority
// store
$priorities = new Priority;
$priorities->name = Input::get('priority_name');
$priorities->hexcolorcode = Input::get('hexcolorcode');
$priorities->save();
$priority = Priority::select('id')->orderBy('created_at', 'desc')->first();
//for Task
$tasks = new Task;
$tasks->name = Input::get('task_name');
$tasks->priority_id = Input::get('priority');
$priorities->save();
// redirect
return Redirect::to('some view please change this');
Please explain views or show screenshots, how are you handling it. For now, I have given you the solution with one controller handling priorities and tasks.
SOLUTION
I added the priority_id attribute to the fillable array inside the task model.
protected $fillable = ['name', 'description', 'priority_id'];
I had an understanding problem, because user_id is assigned automatically from the framework, but it isn't specified in fillable array. That's because I say $request->user->tasks->create(); it is assigned from the framework, but priority_id is assigned through the user, so it is mass assigned and need to be specified in the fillable array.
#Murlidhar Fichadia
Related
trucks table have brand_id. When I create a truck I want to save the brand_id.
Truck one to one Brand.
Migration Brands
public function up()
{
Schema::create('brands', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
Migration Trucks
public function up()
{
Schema::create('trucks', function (Blueprint $table) {
$table->id();
$table->integer('brand_id');
$table->integer('year');
$table->string('owner_full_name');
$table->integer('number_of_owners')->nullable();
$table->text('comment')->nullable();
$table->timestamps();
});
}
Model Brand
class Brand extends Model
{
protected $table = 'brands';
protected $fillable = ['name'];
public function truck()
{
return $this->belongsTo(Truck::class);
}
}
Model Truck
class Truck extends Model
{
protected $table = 'trucks';
protected $fillable = [
'brand_id',
'year',
'owner_full_name',
'owner_numbers',
'comment'
];
public function brand()
{
return $this->hasOne(Brand::class);
}
}
Truck Form (I am using https://kristijanhusak.github.io/laravel-form-builder/) Form Builder
class TruckForm extends Form
{
public function buildForm()
{
$this
->add('brand_id', Field::SELECT, [
'empty_value' => 'Select Brand',
'choices' => Brand::pluck('name')->all()
])
->add('year', Field::NUMBER, [
'rules' => ['required', 'gt:1900', 'lte:' . Carbon::now()->year]
])
->add('owner_full_name', Field::TEXT, [
'rules' => ['required', new MinWordsRule(2)]
])
->add('number_of_owners', Field::NUMBER, ['rules' => 'nullable'])
->add('comment', Field::TEXTAREA, ['rules' => 'nullable'])
->add('Save or Create', Field::BUTTON_SUBMIT, [
'attr' => ['class' => 'btn btn-success']
]);
}
}
My need when create truck brand_id save being his brand
Truck Controller
public function create(FormBuilder $formBuilder)
{
$brandForm = $formBuilder->create(TruckForm::class, [
'method' => 'POST',
'url' => route('trucks.store')
]);
return view('landing.trucks.create', compact('brandForm'));
}
public function store(FormBuilder $formBuilder, Request $request)
{
$brandForm = $formBuilder->create(TruckForm::class);
$brandForm->redirectIfNotValid();
$object = new Truck();
$object->fill($request->all());
$object->save();
$object->brand()->save($request->input('brand_id'));
return redirect()->route('trucks.index');
}
First, make sure to validate your user inputs even if they came from an HTML select tag
//...
'brand_id' => 'required|exists:brands,id' // make sure your brand_id is a valid ID
//...
Then
Keep your controller simple
public function store(FormBuilder $formBuilder, Request $request)
{
$brandForm = $formBuilder->create(TruckForm::class);
$brandForm->redirectIfNotValid();
$object = new Truck();
// this line will map the brand_id attr to $obj->brand_id and link the 2 models to each others ...
$object->fill($request->all());
$object->save();
return redirect()->route('trucks.index');
}
Your relationships are switched around, as you can see here, since the Truck has the brand_id it should have the belongsTo and Brand should have the hasOne, like this:
Brand model:
class Brand extends Model
{
public function truck()
{
return $this->hasOne(Truck::class);
}
}
Truck model:
class Truck extends Model
{
public function brand()
{
return $this->belongsTo(Brand::class);
}
}
And as you can see here, you can simplify your store method to something like this:
public function store(FormBuilder $formBuilder, Request $request)
{
$form = $formBuilder->create(TruckForm::class);
$form->redirectIfNotValid();
Truck::create($form->getFieldValues());
return redirect()->route('trucks.index');
}
Or using the FormBuilderTrait:
use Kris\LaravelFormBuilder\FormBuilderTrait;
use App\Forms\TruckForm;
class TruckController extends Controller
{
use FormBuilderTrait;
public function store(Request $request)
{
$form = $this->form(TruckForm::class);
$form->redirectIfNotValid();
Truck::create($form->getFieldValues());
return redirect()->route('trucks.index');
}
}
I have a simple relationship in laravel eroquent
Here is the bidders table creation
public function up()
{
Schema::create('bidders', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('params_name');
$table->string('params_value');
$table->string('bidder_name');
$table->timestamps();
});
}
Here is bidder_parameter table creation
public function up()
{
Schema::create('bidder_parameters', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('bidder_id');
$table->foreign('bidder_id')->references('id')->on('bidders')->onDelete('cascade');
$table->timestamps();
});
}
Here is a bidder model
class Bidder extends Model
{
protected $table = 'bidders';
protected $fillable = [
"params_name",
"params_value",
"bidder_name"
];
public function page()
{
return $this->hasMany('App\Page');
}
public function parameters()
{
return $this->hasMany('App\BidderParameter');
}
}
and here is BidderParameter model
class BidderParameter extends Model
{
public function parameters()
{
return $this->belongsTo('App\Bidder');
}
}
Here is parameter controller for inserting data to database
public function store(Request $request){
// dd($request);
if($request->ajax())
{
$rules = array(
'params_name.*' => 'required',
'params_value.*' => 'required',
'bidders_name.*' => 'required'
);
$error = Validator::make($request->all(), $rules);
if($error->fails())
{
return response()->json([
'error' => $error->errors()->all()
]);
}
$params_name = $request->params_name;
$params_value =$request->params_value;
$bidders_name =$request->bidders_name;
for($count = 0; $count < count($params_name); $count++)
{
$data = array(
'params_name' => $params_name[$count],
'params_value' => $params_value[$count],
'bidders_name' => $bidders_name[$count],
);
$insert_data[] = $data;
// dd($insert_data);
}
Bidders:insert($insert_data);
return response()->json([
'success' => 'Data Added successfully.'
]);
}
}
Now when I submit data to the database 'bidders tablehave data saved into it butbidder_parameter` is empty
What is wrong with my code?
Many to many relationship contains 3 tables. 2 tables are main and 3rd table is combination of those 2 tables' primary keys.
For example
User can have many roles
and
Role can belong to many users
so that requires many to many relationship
So we need a database schema like this:
Users table -> (id, name ,...) e.g. Jonn Doe with id 1
Roles table -> (id, name, ...) e.g. SUPER_ADMIN with 1
role_user table (id, user_id, role_id) role_id is foreign key of roles table and user_id is foreign key of users table
Now in Model classes:
In User Model
public function roles(){
return $this->belongsToMany(Role::class,'role_user','user_id','role_id');
}
Now in Roles class
public function users(){
return $this->belongsToMany(User::class,'role_user','role_id','user_id');
//note keys are in opposite order as in roles() method
}
Now you can call function from User instance and Role instance where you want
$user->roles // as collection
$user->roles() // as eloquent instance
Also
$role->users // as collection
$role->users() // as eloquent instance
You can read more here
please I am new to Laravel, I want to use Laravel API Resource to store database inside database.
I have 3 Tables
Users
Category
Category_User (this is a pivot table)
In my Controller (OnboardsControllers), I have this to store data
public function store(Request $request)
{
$category_user = Category_User::firstOrCreate(
[
'user_id' => $request->user()->id,
'category_id' => $request->$category->id,
],
);
return new CategoryUserResource($category_user);
}
In my CategoryUserResource I have this
public function toArray($request)
{
return [
'user_id' => $this->user_id,
'category_id' => $this->category_id,
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at,
];
In my Pivot Table, I have this
public function up()
{
Schema::create('category_user', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('category_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->timestamps();
});
}
In my model, I added this
protected $fillable = [
'user_id', 'category_id',
];
In my route/api
Route::post('/category_user', 'OnboardsController#onboardupdate');
I believe the error is here
'user_id' => $request->user()->id,
When I removed it, it didn't returned any error
When I tried to save to my database using Postman to test, it not saving. Please, I don't know what I am doing wrong.
Thanks
To be honest, you do not need a model Category_User (but you need a table).
In Laravel a more concise approach is used:
public function store(Request $request)
{
$user = User::find($request->input('user_id'));
$user->categories()->attach($request->input('category_id'));
}
Also I'm not sure if you have declared a method categories() in model User:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
I also strongly doubt the existence of method user() of class Request.
If the request parameter has a name category_id, then you need to access it like this:
$request->input('category_id');
I'm working on my first Laravel project, and I want to create a REST Api for android application. In my system, I have two tables: categories and images. Table images has column category_id which is a foreign key that references column id on category table.
The categories table
//users table migration
class CreateCategoriessTable extends Migration
{
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
...
}
The images table
class CreateImagesTable extends Migration
{
public function up()
{
Schema::create('images', function(Blueprint $table){
$table->increments('id');
$table->string('name')
$table->integer('category_id')->unsigned();
$table->foreign('category_id')
->references('id')
->on('categories')
->onDelete('cascade');
$table->timestamps();
});
}
...
}
In the Images model class I did it:
class Images extends Model
{
protected $fillable = ['name'];
protected $hidden = array('created_at', 'updated_at');
public function category(){
$this->belongsTo('App\Category');
}
}
I also created CategoryResource() class as:
class CategoryResource extends JsonResource
{
public function toArray($request)
{
return [
'id'=> $this->id,
'name' => $this->name,
];
}
}
So, I created a CategoryController to with the API methods, and configured the routes to access the corresponding function. The api/category/ url via GET is redirect to the index function of my controller, and the function is like that:
public function index()
{
$categories = Category::get();
return CategoryResource::collection($categories);
}
With this, I can get the categories table data, but I would like merge the users and images table, and get something like this as response:
[
{
'id': 1,
'name': 'category_name',
'image': 'image_name'
}
]
How I can do this?
First add a hasOne relation in Category model for image like this
Category Model
public function image(){
return $this->hasOne('App\Image');
}
Now specify the relation in your CategoryResource
class CategoryResource extends JsonResource
{
public function toArray($request)
{
return [
'id'=> $this->id,
'name' => $this->name,
'image' => new ImageResource($this->whenLoaded('image'))
];
}
}
Create ImageResource for loading images
class ImageResource extends JsonResource
{
public function toArray($request)
{
return [
'id'=> $this->id,
'name' => $this->image_name,
];
}
}
Finally load images relations with eager load in your controller like this
public function index()
{
$categories = Category::with('image')->get();
return CategoryResource::collection($categories);
}
I'm having troubles to setup the right Eloquent relationships (belongsTo, hasMany, ...) for a pivot table.
I will abbreviate code for clarity.
I have two important tables: 'parties' and 'p2p_relations'.
This is the migration for parties
public function up()
{
Schema::create('parties', function ($table) {
$table->increments('id');
$table->string('name');
$table->unsignedInteger('kind');
$table->timestamps();
$table->softDeletes();
$table->foreign('kind')->references('id')->on('kinds');
});
}
This is the migration for p2p_relations (party to party relations)
public function up()
{
Schema::create('p2p_relations', function ($table) {
$table->bigIncrements('id');
$table->unsignedInteger('context');
$table->unsignedInteger('reference');
$table->datetime('start');
$table->datetime('end')->nullable();
$table->unsignedInteger('kind')->nullable();
$table->timestamps();
$table->softDeletes();
$table->foreign('context')->references('id')->on('parties');
$table->foreign('reference')->references('id')->on('parties');
$table->foreign('kind')->references('id')->on('kinds');
});
}
The model for Party
class Party extends Ardent
{
use SoftDeletingTrait;
protected $softDelete = true;
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
protected $table = 'parties';
public static $rules = array(
'name' => 'required',
'kind' => 'required|numeric'
);
}
The model for Relation
class Relation extends Ardent
{
use SoftDeletingTrait;
protected $softDelete = true;
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
protected $table = 'p2p_relations';
public static $rules = array(
'context' => 'required|numeric',
'reference' => 'required|numeric',
'kind' => 'required|numeric',
'start' => 'required|date',
'end' => 'date'
);
}
How can I set relationships so I can associate parties as context or reference in a relationship.
I thought belongsTo will help like so in class Relation
public function context() {
return $this->belongsTo('Party', 'context', 'id');
}
public function reference() {
return $this->belongsTo('Party', 'reference', 'id');
}
But when I run this unit-test I get an error: Undefined property: Relation::$context
$context = new Party();
$context->name = 'Person A';
$context->kind = 1;
$context->save();
$ref = new Party();
$ref->name = 'Company B';
$ref->kind = 2;
$ref->save();
$relation = new Relation();
$relation->start = new DateTime();
$relation->context()->associate($context);
$relation->reference()->associate($ref);
$relation->kind = 3;
$relation->save();
Any thoughts? I'm really a newbie to this framework.
Thanks to the comments provided I've learned a lot :-)
Updated my Party Model:
public function references() {
return $this->belongsToMany('Party', 'p2p_relations', 'context', 'reference')
->withPivot('reference', 'start', 'kind')
->withTimestamps() ;
}
No Relation model needed.
The pivot table works perfectly.
Thanks