I a struggling to save the chosen information from my selection box. I get the message:
"SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (clientpad_notes.notebooks, CONSTRAINT notebooks_contact_id_foreign FOREIGN KEY (contact_id) REFERENCES contacts (id) ON DELETE CASCADE) (SQL: insert into notebooks (name, contact_id, note_description, note_body, user_id, updated_at, created_at) values (assddsaasdadasasd, 3, saS, ssss, 2, 2018-03-03 19:18:51, 2018-03-03 19:18:51)
My problem is that I am bringing in information to notes create page from contacts table. So I have my tables linked with authentication with user_id and inside the notes tables I have contacts_id. I am aiming to select and save a contact name fetching it by it's id, when creating a new note. It is possible I have been going around doing this in a wrong way, I am a beginner at Laravel so any help would be appreciated.
Here is my notes controllers and create a note page.
NotesController.php
public function create()
{
$user_id = auth()->user()->id;
$user = User::find($user_id);
$contacts = Contact::find($user->contacts)->pluck('fullName');
return view('notebooks.create')->with('contacts', $contacts)->with('user', $user);
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate($request,[
'name' => 'required',
'contact_id' => 'required',
'note_description' => 'required',
'note_body' => 'required',
]);
//Create a note
$notebook = new Notebook;
$notebook->name = $request->input('name');
$notebook->contact_id = $request->input('contact_id');
$notebook->note_description = $request->input('note_description');
$notebook->note_body = $request->input('note_body');
$notebook->user_id = auth()->user()->id; //currently logged in user show their notes
$notebook->save();
return redirect('/dashboard')->with('success', 'Your Note Was Created');
}
create.blade.php
<div class="col-6 col-sm-3">
{{Form::label('contact_id', 'Choose your Contact')}}
{{Form::select('contact_id', $user->contacts->pluck('fullName'), $contacts, ['class' => 'form-control'])}}
</div>
</div>
In the database which saved notes I have this:
Schema::create('notebooks', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->integer('contact_id')->unsigned()->nullable();
$table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
$table->string('name');
$table->mediumText('note_description');
$table->mediumText('note_body');
$table->timestamps();
});
You made small mistake when working with Id's from other tables. You should check if the ID actually exists in the target table.
$this->validate($request,[
'name' => 'required',
'contact_id' => 'required|exists:contacts', //This will validate that the contact ID actually exists.
'note_description' => 'required',
'note_body' => 'required',
]);
//Create a note
$notebook = new Notebook;
$notebook->name = $request->input('name');
$notebook->contact_id = $request->input('contact_id');
$notebook->note_description = $request->input('note_description');
$notebook->note_body = $request->input('note_body');
$notebook->user_id = auth()->user()->id; //currently logged in user show their notes
$notebook->save();
Laravel validation#rule-exists
Update
$this->validate($request,[
'name' => 'required',
'contact_id' => 'required|exists:contacts,id', //check contacts table, for column ID
'note_description' => 'required',
'note_body' => 'required',
]);
SO after lots of searching I found a solution. In Create I had to use mapping:
public function create(Contact $contact)
{
$user_id = Auth::user()->id;
$user = User::find($user_id);
$contacts = $user->contacts->mapWithKeys(function($contact){
return [$contact->id => $contact->fullName];
});
// dd ($contacts);
return view('notebooks.create')->with('contacts', $contacts)->with('user', $user);
}
Then in Select I just called for this:
{{Form::label('contact_id', 'Choose your Contact')}}
{{Form::select('contact_id', $contacts, null, ['class' => 'form-control'])}}
Works like a charm, in case anyone else finds this useful
Related
This is my first time creating an API. I want to insert data in two table at the same time.
I have a Listing table and Category table. Relationships of the table is one List => has many Category
Listing columns
id
title
description
Category columns
id
listing_id
category_name
This is my code so far in my controller
public function store(Request $request)
{
return Listings::create($request->all());
}
Listing Model
protected $table = 'testing_table';
public function categories(){
return $this->hasMany('App\Category', 'listing_id', 'id');
}
Category Model
protected $table = 'sample_category';
Routes
Route::post('listings', 'ListingsController#store');
Note: Listing and category will be saved together.
First, you have to make sure each model has the $fillables property set to avoid mass assignment issues. Second, you have to send the category name along with the request.
public function store(Request $request)
{
// You might want to do some validations
$listing = Listings::create($request->all());
$category = $listing->categories()->create([
'category_name' => $request->input('category_name')
]);
// And you can return the date however you see fit.
return response()->json([
'listing' => $listing,
'category' => $category
]);
}
public function store(Request $request)
{
try {
$input = $request->all();
\DB::beginTransaction();
$id = Listing::create($input)->id;
$cat = Category::create([
'listing_id' => $id,
'category_name' => $input['category_name'],
]);
\DB::commit();
return response()->json(['status' => 'success', 'code'=> '200', 'data' => 'as per your requirment'], 200);
} catch (\Throwable $th) {
\DB::rollBack();
echo "<pre>";print_r($th->__toString());die;
}
}
to insert more rows then we have to check another way. Please provide your request data.
Please let me know if this helps
I am trying to add a new record into 2 tables (using FK) at the same time, I had it working for me quite well but when I changed the FK to ON UPDATE: CASCADE, something happened. It allows me to insert a new record only if the clients name and phone number already exist in the clients table, that means it won't let me add a new one. When I try to use a different phone number it won't show me any errors.
Here how my reservation and client tables look like.
reservation:
id(PK), num, location, diners, re_date, re_time, phonenumber(FK)
clients:
fullname, phonenumber(PK)
Controller
//form to save new reservation
public function create() {
$newDate = date("Y-m-d",strtotime($this->input->post('re_date')));
$newTime = date("H:i", strtotime($this->input->post('re_time')));
$data = array(
'num' => $this->input->post('num'),
'location' => $this->input->post('location'),
'diners' => $this->input->post('diners'),
're_date' => $newDate,
're_time' => $newTime,
'phonenumber' => $this->input->post('phonenumber'),
);
$dataclient = array(
'fullname' => $this->input->post('fullname'),
'phonenumber' => $this->input->post('phonenumber'),
);
$this->Hosting_model->form_insert($data, $dataclient);
redirect(base_url("/hosting/tableMap"));
}
Model
public function form_insert($data, $dataclient){
$this->db->db_debug = FALSE;
$error = NULL;
if (!( ($this->db->insert('reservations', $data)) && ($this->db->insert('clients', $dataclient)))) {
$error = $this->db->error();
}
return $error;
}
I have three tables:
user
game
user_game
game.user_id - user which CREATE game. Table user_game describes users that ADDED games not create, it
has user_id and game_id fields. I have GameSearch Model which should search current user ADDED games. Here The search method;
public function search($params)
{
// HERE I SHOULD GET ONLY GAMES WHICH ADDED BY USER via table user_game
$query = Game::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => [
'sorting' => SORT_DESC,
]
],
]);
if (!empty($params['pageSize'])) {
$dataProvider->pagination->pageSize = $params['pageSize'];
}
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'user_id' => $this->user_id,
'visible' => $this->visible,
'sorting' => $this->sorting,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'slug', $this->slug])
->andFilterWhere(['like', 'image', $this->image])
->andFilterWhere(['like', 'description', $this->description])
->andFilterWhere(['>=', 'created_at', $this->date_from ? $this->date_from : null])
->andFilterWhere(['<=', 'created_at', $this->date_to ? $this->date_to : null])
->andFilterWhere(['>=', 'updated_at', $this->date_upd_from ? $this->date_upd_from : null])
->andFilterWhere(['<=', 'updated_at', $this->date_upd_to ? $this->date_upd_to : null]);
return $dataProvider;
}
So i need get games list via table user_game where user_id = current Id user, game_id = game id. Please help.
first of all you need two relation in first in Game model which will fetch one to many data from user_game table (model), then in model user_game you need write a relation to get user from user table (model)
$query->joinWith(['userGame', 'userGame.user']);
->andFilterWhere(['=', 'tbl_user.id', Yii::app()->user->id])
I have two tables:
Property (..., postcode_id, ...)
Postcode (id, postcode, latitude, longitude)
The relationship:
class Property extends AppModel {
public $belongsTo = array(
'Postcode' => array(
'className' => 'Postcode'
)
);
class Postcode extends AppModel {
public $hasMany = array(
'Property' => array(
'className' => 'Property'
)
);
What I'd like to happen:
Enter a postcode in the Property add form.
Check entered postcode is in the Postcode table.
If not, so some logic (possibly add it, just return validation error for now).
If so, then record the Postcode.id in Properties.postcode_id (the foreign key).
I can't figure out the best way to do this with cake. A custom Property validation function that does the check and adds it to data to be added? Or in beforeValidation? Or does Cake deal with this?
Thanks!
EDIT
Based on the answer, I think this is the best solution...
I think this is the better way to do it, as it validates too. Thanks Anubhav for the putting me on the right track!
As per Anubhav's answer, in the Postcode model:
public function checkPostcode($postcode = null){
$record = $this->find('first', array(
'conditions'=>array('postcode' => $postcode),
'fields' => array('id')
));
if (!empty($record)){
return $record['Postcode']['id'];
} else {
return false;
// Logic for finding and adding new postcode
}
}
But and in the Property model:
public $validate = array(
'postcode' => array(
'exists' => array(
'rule' => 'postcodeExists',
'message' => 'Postcode does not exist'
)
)
);
public function postcodeExists($check) {
$id = $this->Postcode->checkPostcode($check);
if ($id) {
$this->data['Property']['postcode_id'] = $id;
return true;
}
return false;
}
public function beforeSave($options = array()) {
unset($this->data['Property']['postcode']);
}
By modifying the values to save here, the controller is kept skinny, and, rather than making sure postcode is real then finding the id, both are done at once, so only one query is needed.
Follow the steps:
Step 1: Create one action in Postcode.php
function checkPostcode($postcodeValue = null){
$returnData = $this->find('first',
array('conditions'=>array('postcode'=>$postcodeValue),
'fields'=>array('id'))
);
if(!empty($returnData)){
return $returnData['Postcode']['id'];
}else{
$saveData['Postcode']['postcode'] = $postcodeValue;
$this->save($saveData);
return $this->getLastInsertID();
}
}
The above function will check postcode from postcode model and insert postcode if not exist and returns the id of postcode table for corresponding row.
Step 2: Call this function controller action as
function someFuntion(){
$postcode_id = $this->Postcode->checkPostcode($userInputPostcodeHere);
// Write code to save property here
}
Hope this will give you some idea about the logic...
I have created a database with two tables, "goals" and "partgoals". The practial use is to make a savings goal (money) and have milestones along the way (partgoals). I want the partgoals obviously be linked to a specific goal. The relationships are created but I run into trouble when trying to create my seed data.
My goal is to set up two goals table like this (GoalsTableSeeder.php):
<?php
class GoalsTableSeeder extends Seeder {
public function run()
{
DB::table('goals')->delete();
$goals = array(
array(
'max' => 1850000,
'avgsav' => 3500,
'duedate' => date('2015-03-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
),
array(
'max' => 1100000,
'avgsav' => 5000,
'duedate' => date('2013-11-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
)
);
DB::table('goals')->insert( $goals );
}
}
And my partgoals table like this (PartgoalsTableSeeder.php):
<?php
class PartgoalsTableSeeder extends Seeder {
public function run()
{
DB::table('partgoals')->delete();
$partgoals = array(
array(
'id' => 1,
'milestone' => 100000,
'duedate' => date('2014-03-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
),
array(
'id' => 1,
'milestone' => 20000,
'duedate' => date('2013-06-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
),
array(
'id' => 2,
'milestone' => 400000,
'duedate' => date('2013-09-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
),
array(
'id' => 2,
'milestone' => 200000,
'duedate' => date('2014-10-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
)
);
DB::table('partgoals')->insert( $partgoals );
}
}
The migration table for "goals":
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateGoalsTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('goals', function(Blueprint $table)
{
$table->increments('id');
$table->integer('max');
$table->float('avgsav');
$table->date('duedate');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('goals');
}
}
The migration table for partgoals:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePartgoalsTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('partgoals', function(Blueprint $table)
{
$table->foreign('id')
->references('id')->on('goals')
->onDelete('cascade');
$table->increments('id');
$table->float('milestone');
$table->date('duedate')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('partgoals');
}
}
What am I doing wrong? I am new to Laravel (and Laravel 4).
I see a few problems with your code:
1) The way you create the foreign key
When assigning the Foreign key constraint, you should make that column unsignedInteger.
In the code below I will correct the mistake you made of naming two columns 'id'.
Schema::create('partgoals', function(Blueprint $table)
{
$table->increments('id');
$table->unsignedInteger('goal_id');
$table->foreign('goal_id')
->references('id')->on('goals')
->onDelete('cascade');
$table->float('milestone');
$table->date('duedate')->nullable();
$table->timestamps();
});
2) The way you seed your database
If you specify a foreign key, you should declare the value when creating the entry in the table seeder.
If you want to specify a NULL value, this can be done by allowing the column to accept such value (by default it doesn't). In this case, we should add ->nullable()->default(NULL)
Schema::create('partgoals', function(Blueprint $table)
{
$table->increments('id');
$table->unsignedInteger('goal_id')->nullable()->default(NULL);
$table->foreign('goal_id')
->references('id')->on('goals')
->onDelete('cascade');
$table->float('milestone');
$table->date('duedate')->nullable();
$table->timestamps();
});
Minor mistake
3) You are passing the 'id' => 1 twice in your seeder
When using increments in the query builder, that automatically makes that your primary key, auto-incremented, and unique. You can't have a foreign key also be your primary key unless it's a one-to-one relationship. That's just bad design though. Your schema should look something like below.
Schema::create('partgoals', function(Blueprint $table)
{
$table->increments('id');
$table->foreign('goal_id')
->references('id')->on('goals')
->onDelete('cascade');
$table->float('milestone');
$table->date('duedate')->nullable();
$table->timestamps();
});
Also, when seeding, if you use the insertGetId when inserting, it will return the ID of the record you just inserted. This you can use in another insert, like inserting into another table, later. However, this has to take place in the same script. You may be able to pass it back out to DatabaseSeeder and then back into another seed script, but I haven't tried this.
I'm not familiar with Laravel, or what you're trying to do, but based on the error you added in the comments it seems that your problem is a result of trying to enter multiple records with the same primary key (1) into your partgoals table.
I'm not sure how you've set your tables up, but it seems like you've defined a partgoals table with a unique primary key column ID, which you're also trying to use as a foreign key to reference the goals table. It may be worth creating another field to hold your foreign key in the partgoals table.
To seed tables with relationship, you need to defined model factories in the ModelFactory.php file and then create a seeder class to run the seeder.
For ex. ModelFactory.php
$factory->define(App\Category::class, function (Faker\Generator $faker) {
$name = $faker->name;
return [
'name' => $name,
'visible' => 1
];
});
$factory->define(App\Video::class, function (Faker\Generator $faker) {
return [
'title' => $faker->name,
'description' => '',
'status' => 1
];
});
Then the seeder class can be as follows
<?php
use Illuminate\Database\Seeder;
class CategoriesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
$categories = factory(App\Category::class, 20)->create()->each(function ($u) {
for ($i=0; $i<5; $i++)
{
$u->videos()->save(factory(App\Video::class)->make());
}
});
}
}
You can refer this article on how to generate seeds for two tables with relationship http://deepdivetuts.com/seeding-two-tables-using-laravel-5-3