I am trying to track Semi-private tennis lesson records using Laravel 5.3 and mysql. I am attempting to follow the example set in the Laravel 5 Many to Many tutorial. I have a Players model that I am trying to sync with a Sharedlessonhours table via a Player_Sharedlessonhours pivot table. In the code my sharedlessonhours table gets an inserted record, but the pivot table does not. Sorry to be so verbose, but I want to be clear about what's happening.
First the table structure.
public function up()
{
Schema::create('sharedlessonhours', function (Blueprint $table) {
$table->increments('id');
$table->date('signup_date');
$table->integer('packages_id')->unsigned();
$table->timestamps();
});
Schema::table('sharedlessonhours', function (Blueprint $table) {
$table->foreign('packages_id')->references('id')->on('packages');
});
Schema::create('player_sharedlessonhour', function (Blueprint $table)
{
$table->integer('sharedlessonhours_id')->unsigned();
$table->integer('players_id')->unsigned();
$table->timestamps();
});
Schema::table('player_sharedlessonhour', function (Blueprint $table) {
$table->foreign('sharedlessonhours_id')->references('id')->on('sharedlessonhours')->onDelete('cascade');
$table->foreign('players_id')->references('id')->on('players')->onDelete('cascade');
});
}
The create and store methods:
public function createSharedLessonhours()
{
$players = Players::orderBy('lname')->pluck('fname', 'id');
$packages = Packages::orderBy('name')->pluck('name','id');
return view('admin.lessonhours.sharedlessonhours', compact('players', 'packages'));
}
public function storeSharedLessonhours(Request $request)
{
$sharedlessonhours = SharedLessonhours::create($request->all());
$sharedlessonhours->players()->attach($request->input('players'));
}
The Form:
<div class="col-md-4 col-sm-5">
{!! Form::open(['url' => 'sharedlessonhours']) !!}
<div class="form-group">
{!! Form::label('players', 'Player(s):') !!}
{!! Form::select('players[]', $players, null, ['class' => 'form-control', 'multiple']) !!}
</div>
<div class="form-group">
{!! Form::label('signup_date', 'Signup Date:') !!}
{!! Form::text('signup_date', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('packages_id', 'Lesson Package:') !!}
{!! Form::select('packages_id', $packages, null, ['class' => 'form-control', 'placeholder' => 'Choose Package']) !!}
</div>
<div class="form-group">
{!! Form::submit('Signup', ['class' => 'btn btn-default form-control']) !!}
</div>
{!! Form::close() !!}
</div>
The screenshot of the select box for the player ids:
And screenshot for error:
I am wondering if the array is simply in the incorrect order? dd($request) shows that everything is being collected from the form and but looking at the error page seems like it is trying to insert data into the wrong fields. The line that has (3,4) wouldn't be the correct order if that matters to mysql. I tried flipping the columns in mysql, but it didn't help.
I am very confused right now.
UPDATE:
First I will share the requested code then share further steps I have taken to debug.
Players model code:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Collective\Html\Eloquent\FormAccessible;
use Carbon\Carbon;
class Players extends Model
{
public $table = "players";
protected $fillable = array('fname', 'lname', 'gender', 'birthdate');
public function users()
{
return $this->belongsTo('App\User', 'users_id');
}
public function lessonHours()
{
return $this->hasMany('App\Lessonhours', 'players_id');
}
public function sharedlessonhours()
{
return $this->belongsToMany('App\SharedLessonhours', "player_sharedlessonhour","players_id", "sharedlessonhours_id" );
}
public function getFullName($id)
{
return ucfirst($this->fname ) . ' ' . ucfirst($this->lname);
}
protected $dates = ['birthdate'];
public function setBirthdateAttribute($value)
{
$this->attributes['birthdate'] = Carbon::createFromFormat('m/d/Y', $value);
}
}
SharedLessonhours:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Collective\Html\Eloquent\FormAccessible;
use Carbon\Carbon;
class SharedLessonhours extends Model
{
use FormAccessible;
protected $fillable = array('signup_date', 'packages_id');
public $table = "sharedlessonhours";
public function players()
{
return $this->belongsToMany('App\Players', "player_sharedlessonhour", "players_id", "sharedlessonhours_id");
}
public function sharedhoursused()
{
return $this->hasMany('App\SharedHoursused', 'id');
}
public function packages()
{
return $this->belongsTo('App\Packages');
}
public function setSignUpDateAttribute($value)
{
$this->attributes['signup_date'] = Carbon::createFromFormat('m/d/Y', $value);
}
}
I attempted to add a different record after changing the columns in mysql and get the error again. I switched the columns back and the error continues, eve`n after restarting tinker.
In addition to customizing the name of the joining table, you may also customize the column names of the keys on the table by passing additional arguments to the belongsToMany method. The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to
From laravel documentation for Many-To-Many relationship.
Accordingly the definition of players relationship in your SharedLessonhour model should be as
public function players()
{
return $this->belongsToMany('App\Players', "player_sharedlessonhour", "sharedlessonhours_id", "players_id");
}
Try changing the definition and see. I haven't tested but this seems to be the cause for constraint violation.
Related
Been at this for a very long time and I can't get it right. Would be really thankful for some help. Thanks in advance!
Im trying to build a little clone of reddit some learning purpose.
I think these models is correct for what I'm trying to do. Im able to save a Subreddit to DB with user_id. But my problem is that I can't post to the post table since it's telling me it cannot find the subreddits_id column. Im seems like the method im trying to call should be working but it doesnt.
protected $fillable = ['title', 'link','content', 'post_picture', 'user_id', 'subreddit_id'];
//Functions
public function user () {
return $this->belongsTo(User::class);
}
public function subreddit() {
return $this->belongsTo(Subreddit::class);
}
public function comments () {
return $this->hasMany(Comment::class);
}
Above is my Post model
protected $guarded = [];
//Functions
public function user () {
return $this->belongsTo(User::class);
}
public function posts () {
return $this->hasMany(Post::class);
}
public function comments () {
return $this->hasMany(Comment::class);
}
Above is my Subreddit Model
public function posts () {
return $this->hasMany(Post::class);
}
public function subreddit() {
return $this->hasMany(Subreddit::class);
}
public function commments () {
return $this->hasMany(Comment::class);
}
Above is my User model
I think these models is correct for what I'm trying to do. Im able to save a Subreddit to DB with user_id. But my problem is that I can't post to the post table since it's telling me it cannot find the subreddits_id column. Im seems like the method im trying to call should be working but it doesnt.
The Store method looks like this:
public function store(Request $request)
{ $data = request()->validate([
'title' => 'required',
'link' => 'required',
'content' => 'required',
]);
$post = auth()->user()->posts()->create($data);
return redirect('/home');
}
I'm getting this error General error: 1364 Field 'subreddit_id' doesn't have a default value (SQL: insert into posts (title, link, content, user_id, updated_at, created_at) values (awe, ew, we, 2, 2020-04-01 17:41:29, 2020-04-01 17:41:29))
your $data only takes the parameters you specify for validation, But you did not include subreddit_id, It should be like this:
public function store(Request $request)
{ $data = request()->validate([
'title' => 'required',
'link' => 'required',
'content' => 'required',
'subreddit_id' => 'required|exist:subreddits,id'
]);
$post = auth()->user()->posts()->create($data);
return redirect('/home');
}
I have referred all the other questions asked and did what they have told. Still i cant get rid of default_value error. I have added multiple connections. So i have 3 databases : Users , companya , companyb.
Company-A and Company-B has same structure.
Stocks have tag_no as primary key and i have specified it in model too.
Inside Stock model I have created a constructor to dynamically switch models based on users company.
Even after all this i keep getting this error.
I tried changing strict to false inside database.php but.. all the entries are showing value 0. So I stopped trying that.
So what can i do to solve this. Please help!
Below is my schemas:
For Users:
Schema::connection('mysql')->create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('company')->default('companya');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->string('user_type',50)->default('user');
$table->rememberToken();
$table->timestamps();
});
For company-A and company-B:
Schema::connection('companya')->create('stocks', function (Blueprint $table) {
$table->string('tag_no')->index();
$table->string('stock_type');
$table->timestamps();
});
Here is my Stock Model:
class Stock extends Model
{
protected $primaryKey = 'tag_no';
public $incrementing = false;
protected $fillable = [
'tag_no',
'stock_type',
];
public function __construct() {
if ( Auth::check() ) {
$this->connection = Auth::user()->company;
}
}
}
Code for store function:
public function store(Request $request)
{
if(Auth::check()){
if (Stock::where('tag_no','=',$request->input('tag_no'))->exists()) {
return back()->withInput()->with('errors', 'Tag number already used!');
}
$stock = Stock::create([
'tag_no' => $request->input('tag_no'),
'stock_type' => $request->input('stock_type'),
]);
}
if($stock){
return redirect()->route('stocks.index', ['stocks'=> $stock->tag_no])
->with('success' , 'Stock created successfully');
}
return back()->withInput()->with('errors', 'Error creating new Stock');
}
Just changed create to insert and removed stocks parameter.
public function store(Request $request)
{
if(Auth::check()){
if (Stock::where('tag_no','=',$request->input('tag_no'))->exists()) {
return back()->withInput()->with('errors', 'Tag number already used!');
}
$stock = Stock::insert([
'tag_no' => $request->input('tag_no'),
'stock_type' => $request->input('stock_type'),
]);
}
if($stock){
return redirect()->route('stocks.index')
->with('success' , 'Stock created successfully');
}
return back()->withInput()->with('errors', 'Error creating new Stock');
}
I'm using laravel 5.5 and im trying to add a comment to a post and i get the following error when i submit to the form
"SQLSTATE[23000]: Integrity constraint violation: 1048 Column
'post_id' cannot be null (SQL: insert into comments (comment_body,
user_id, post_id, updated_at, created_at) values (sdsd, 1, ,
2017-12-03 12:29:58, 2017-12-03 12:29:58))
im going to be using: <% %> is for angular, just letting everyone know.
In tinker this works
Comment::create(['comment_body' => 'this works', 'user_id'=> 1, 'post_id'=>8]);
**Route*
Route::post('post/comment', 'CommentController#create');
Post Model
use App\User;
use App\Like;
use App\Comment;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Post extends Authenticatable
{
protected $fillable = [
'title',
'body',
'user_id',
'created_at',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function likes()
{
return $this->hasMany('App\Like');
}
public function comments()
{
return $this->hasMany('App\Comment');
}
Comment Model
class Comment extends Model
{
protected $fillable = [
'comment_body',
'user_id',
'post_id'
];
public function user()
{
return $this->belongsTo('App\User');
}
public function post()
{
return $this->belongsTo('App\Post');
}
}
CommentConroller
public function create(Request $request, Post $post)
{
$data = request()->validate([
'comment_body' => 'required|max:1000'
]);
$data['user_id'] = auth()->user()->id;
$data['name'] = auth()->user()->name;
$data['post_id'] = $post->id;
$post = Comment::create($data);
$response = new Response(json_encode($data));
$response->headers->set('Content-Type', 'application/json');
if(!$response){
return 'something went wrong';
}
return response()->json($data);
}
Html
<div class="comment-class animated bounceInUp" ng-show="writecomment">
<div class="panel-body">
<ng-form ng-model="commentForm" name="commentForm" method="POST" novalidate>
<div class="form-group">
<label>Write a Comment</label>
<textarea ng-model="post.comment" type="text" class="form-control" name="comment_body" cols="2" rows="2"></textarea>
</div>
<button id="eli-style-button" ng-click="addComment(post)" class="btn btn-primary" type="submit">Submit</button>
</form>
</div>
<!-- END Comment form Inside Ng-repeat -->
</div>
<!-- End of ng-repeat post in mypost -->
</div>
Main.js
$scope.addComment = function(post){
$http.post('/post/comment',{
comment_body: post.comment,
}).then(function(result){
console.log(result.data);
$scope.myposts.push(result.data);
});
};
In order to use route model binding, you have to include the post as a parameter in your route:
Route::post('post/{post}/comment', 'CommentController#create');
Then call it like this:
$http.post('/post/' + post.id + '/comment' ...
Right now in your controller you are getting an empty Post instance that has no ID.
I'm learning laravel pivot table and here's what I'm doing. I have a student and subject model with many to many relationship. In my pivot table i have included columns for test1, test2 and test3 so that i can use it to store the student's score for each subject. These are my models
class Student extends Model
{
protected $guarded = ['id'];
public function subjects()
{
return $this->belongsToMany(Subject::class);
}
}
class Subject extends Model
{
protected $guarded = ['id'];
public function students()
{
return $this->belongsToMany(Student::class);
}
}
This is my migration
public function up()
{
Schema::create('subjects', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->timestamps();
});
Schema::create('student_subject', function (Blueprint $table) {
$table->integer('student_id');
$table->integer('subject_id');
$table->primary(['student_id', 'subject_id']);
$table->integer('test1')->nullable();
$table->integer('test2')->nullable();
$table->integer('test3')->nullable();
});
}
This is where it all got complicated for me. When a student record is created, user is redirected to an enroll page where subjects are selected for the student.
This is my StudController#store
public function store(Request $request)
{
$student = Student::create(request()->all());
Session::flash('status', "New student's record was added successfully");
Session::put('firstname', request('firstname'));
Session::put('lastname', request('lastname'));
Session::put('student_id', $student->id);
Session::put('class', $student->class_admitted);
return redirect('/enroll');
}
This is the enroll form
<form class="form-horizontal" role="form" method="POST" action="/enroll">
{{ csrf_field() }}
<input type="" name="student_id" value="{{ Session::get('student_id')}}" hidden>
<div class="col-md-6 form-group subjectList">
<ul>
#foreach ($subjects as $subject)
<li><label class="checkbox-inline"><input type="checkbox" name="subject_id[]" value="{{ $subject->id }}"> {{ ucwords($subject->name) }}</label></li>
#endforeach
</ul>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Enroll
</button>
</div>
</div>
</form>
And this is my EnrollController#store
public function store(Request $request)
{
//dd($request);
$student = request('student_id');
foreach ($request->input('subject_id') as $subject) {
$student->subjects()->attach($subjects);
}
}
I'm confused as to how I can do insert into the pivot table.
You can add an array in your attach() method, like this:
->attach($subjectId, ['test1' => 1, 'test2' => 2]);
The attach() method will create the entry in the pivot table, the additional attributes will be added.
You can also pass an array of subjects to attach(), like this:
->attach([1 => ['test1' => 1, 'test2' => 2], 2 => ['test1' => 3, 'test2' => 4]]);
And when you need to update the pivot data you can use sync().
As far as I can see now, you do not have anything in your form besides the subject, so I assume you want to update the pivot data later on.
Also, you might want to add some additional validation there on both the student and the subjects.
public function store(Request $request)
{
// making sure student exists
$student = Student::findOrFail(request('student_id'));
$subjectIds = Subject::whereIn('id', $request->input('subject_id', []))
->get()
->pluck('id')
->all();
$student->subjects()->attach($subjectIds);
// you can also use sync here, that way it will add new subjects, keep the ones that already exist (and are posted) and remove subjects not in post
// $student->subjects()->sync($subjectIds);
}
I am trying to retrieve data from the database by user_id. My view shows this error : Trying to get property of non-object. dd() return null.
This is my Controller :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\Complain;
use App\Feedback;
use App\Item;
use Illuminate\Support\Facades\Redirect;
use Session;
use Auth;
class ProfileController extends Controller
{
public function profile($id){
$complain = Complain::find($id);
dd($complain);
return view('user.profile')->with(['complains' => User::find($id)->complains]);
}
}
This is my User Model :
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Model;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'surname', 'regnumber', 'course', 'department', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function complains()
{
return $this->hasMany('App\Complain');
}
}
This is my Complain Model.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Complain extends Model
{
protected $fillable = [
'user_id', 'title', 'body', 'name', 'regnumber'
];
public function user(){
return $this->belongsTo('App\User');
}
}
This is my view :
#foreach($complains as $complain)
<div>
<h3 class="operator-complain-title">Title: </h3>
<p>{{ $complain->title }}</p>
<h3 class="operator-complain-title">Complain:</h3>
<p>{{ $complain->body }}</p>
</div>
<hr>
#endforeach
The user_id is a foreign key. How do I successfully show complains(data) based on the user_id?
This is my users table:
id | name | email | password
7 John email password
This is my complains table :
id | user_id | title | body
5 7 complain 1 Complain 1
Anyone with ideas please share.
As I understand You want to get complains by user $id.
So doing Complain::find($id) will not return user's complain, cuz find gets by id field.
But You want to get complains by user_id field.
So for that case: Complain::whereUserId($id)->get()
Check this one (recommended when You're going to show user's data and it's complains):
public function profile(Request $request, $id){
$User = User::with(['complains'])->find($id);
if(!$User) return abort(404, 'User with id:'.$id.' not found');
return view('user.profile')->with(['user' => $User, 'complains' => $User->complains]);
}
or this one (if You're going to show complains only):
public function profile(Request $request, $id){
$complains = Complain::whereUserId($id)->get();
if(!$complains) return abort(404, 'No complains for user (id:'.$id.') found');
return view('user.profile')->with(['complains' => $complains]);
}
In case of $id is name of user:
public function profile(Request $request, $name){
$User = User::with(['complains'])->whereName($name)->first();
if(!$User) return abort(404, 'User with name:'.$name.' not found');
return view('user.profile')->with(['user' => $User, 'complains' => $User->complains]);
}
You would try to check first if the object is null or empty before trying to consume it like
<?php
$var = 0;
// Evaluates to true because $var is empty
if (empty($var)) {
echo '$var is either 0, empty, or not set at all';
}
// Evaluates as true because $var is set
if (isset($var)) {
echo '$var is set even though it is empty';
}
?>
public function profile($id)
should be
public function profile(Request $request)
And on Eloquent
$complain = Complain::find($request->id);
Or get query from segment. Example domain/id/ = id from slug number 1
$complain = Complain::find($request->segment(1));