I'm actually new to Laravel and I'm trying to build a basic social network with this Framework. For this project, I created a page called post which users can add new posts. So I tried creating the posts table like this:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->text('caption');
$table->string('image');
$table->timestamps();
$table->index('user_id');
});
}
And on User.php model:
public function posts()
{
return $this->hasMany(Post::class);
}
And the Post.php which extends the model:
class Post extends Model
{
protected $guarded = [];
Public function user()
{
return $this->belongsTo(User::class);
}
}
And the controller which is named PostsController.php goes like this:
class PostsController extends Controller
{
public function create()
{
return view('posts.create');
}
public function store()
{
$data = request()->validate([
'caption' => 'required',
'image' => ['required','image'],
]);
auth()->user()->posts()->create($data);
dd(request()->all());
}
}
And here is the create.blade.php under the posts folder at resources dir:
#extends('layouts.app')
#section('content')
<div class="container">
<form action="/p" enctype="multipart/form-data" method="post">
#csrf
<div class="row">
<div class="col-8 offset-2">
<div class="row">
<h1>Add New Post</h1>
</div>
<div class="form-group row">
<label for="caption" class="col-md-4 col-form-label">Post Caption</label>
<input id="caption"
type="text"
class="form-control #error('caption') is-invalid #enderror"
name="caption"
value="{{ old('caption') }}"
autocomplete="caption" autofocus>
#error('caption')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
#enderror
</div>
<div class="row">
<label for="image" class="col-md-4 col-form-label">Post Image</label>
<input type="file" class="form-control-file" id="image" name="image">
#error('image')
<strong>{{ $message }}</strong>
#enderror
</div>
<div class="row pt-4">
<button class="btn btn-primary">Add New Post</button>
</div>
</div>
</div>
</form>
</div>
#endsection
And if you want to take a look at routes.php here it is:
Auth::routes();
Route::get('/p/create','PostsController#create');
Route::post('/p','PostsController#store');
Route::get('/profile/{user}', 'ProfilesController#index')->name('profile.show');
So everything looks nice and clean but the problem is whenever I try to upload some dummy pictures with a caption, I see this error:
SQLSTATE[HY000]: General error: 1 table posts has no column named caption
However I tried to run php artisan migrate syntax on CMD to check if the database migration missed anything or not, and it outputs: Nothing to migrate!
So if you know why this problem occurs or how can I fix this, please let me know, I would really appreciate that!
Thanks in advance.
In your migration you need to create the relationship, like this :
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->text('caption');
$table->string('image');
$table->timestamps();
// $table->index('user_id');
});
}
Error : You make a column for foreign key, $table->unsignedBigInteger('user_id');
But you didn't define it as a foreign key with a relationship, you need to add this line for make a relation with users table as, $table->foreign('user_id')->references('id')->on('userses')->onDelete('cascade');
Laravel 7 added Foreign Key Constraints method, in this method you can define a foreign key with one line code, as :
$table->foreignId('user_id')->constrained();
This is same as :
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
The foreignId method is an alias for unsignedBigInteger while the constrained method will use convention to determine the table and column name being referenced. If your table name does not match the convention, you may specify the table name by passing it as an argument to the constrained method:
Note : MySQL makes foreign key as an index automatically, so you don't need to define , so I delete this line $table->index('user_id'); You can find more about here.
Now, if you run php artisan migrate you will get the same Nothing to migrate! , because you already migrated all tables according to your migrations, and laravel saved all your migrated files name on a table called migrations. You need to run php artisan migrate:refresh, this command will delete your all previous table and make new table.
class Post extends Model
{
protected $guarded = [];
Public function user()
{
return $this->belongsTo(User::class,'user_id', 'id');
}
}
You can try to specify the corresponding foreign key, maybe your foreign key does not specify a pair, or you can provide your User's Model to have a look
i had the same probleme and i fixed it with this commande even if it will delete ur data in ur database but it will work
php artisan migrate:refresh
I have faced this error before and all I did was run this command:
php artisan migrate:refresh
Related
I have a model named Articles which contained three attributes: 'title', 'subtitle' and 'body' and it worked perfectly but after adding four columns to that model ('subtitle2', 'body2', 'subtitle3' and 'body3') the newly added columns stay NULL after creating articles.
There is clearly something that I missed but I can't figure out what.
This is the migration:
public function up()
{
Schema::table('articles', function (Blueprint $table) {
$table->string('subtitle2')->nullable()->default(null);
$table->text('body2')->nullable()->default(null);
$table->string('subtitle3')->nullable()->default(null);
$table->text('body3')->nullable()->default(null);
});
}
After migrating I edited my app/Http/Models/Article.php and it looks like this:
protected $fillable = [
'title',
'subtitle',
'body',
'subtitle2',
'body2',
'subtitle3',
'body3',
];
This is my app/Http/Livewire/CreateArticle.php
class CreateArticle extends Component
{
use WithFileUploads;
public $title;
public $subtitle;
public $body;
public $category;
public $subtitle2;
public $body2;
public $subtitle3;
public $body3;
public $temporary_images;
public $images = [];
public $article;
public function store()
{
$this->validate();
$this->article = Category::find($this->category)->articles()->create($this->validate());
$this->article->user()->associate(Auth::user());
$this->article->save();
if(count($this->images)){
foreach($this->images as $image){
$newImage = $this->article->images()->create(['path'=>$image->store('images', 'public')]);
dispatch(new ResizeImage($newImage->path, 600, 400));
}
}
}
And finally I added these lines to the form:
{{-- INSERT SUBTITLE 2 --}}
<div class="mb-3">
<label for="subtitle2" class="form-label">Second paragraph subtitle</label>
<input type="text" wire:model="subtitle2" class="form-control" id="subtitle2">
</div>
{{-- INSERT PARAGRAPH 2 --}}
<div class="mb-3">
<label for="body2" class="form-label">Second paragraph</label><br>
<textarea class="form-control" wire:model="body2" id="body2" cols="30" rows="3"></textarea>
</div>
{{-- INSERT SUBTITLE 3 --}}
<div class="mb-3">
<label for="subtitle3" class="form-label">Third paragraph subtitle</label>
<input type="text" wire:model="subtitle3" class="form-control" id="subtitle3">
</div>
{{-- INSERT PARAGRAPH 3 --}}
<div class="mb-3">
<label for="body3" class="form-label">Third paragraph</label><br>
<textarea class="form-control" wire:model="body3" id="body3" cols="30" rows="3"></textarea>
</div>
dd($this); is returning the following
Tinker is showing all columns
You need to specify
protected $rules
in order to use
$this->validate()
Assuming the dd(); image you provided is the latest. I can see the new columns does not exists in database. ('subtitle2', 'body2', 'subtitle3' and 'body3') all these are not available in list.
so I think you are missing to run the migrate command
php artisan migrate
I am beginner of laravel, I want to store a book to books database, but after click button, it shows "Method Illuminate\Database\Eloquent\Collection::books does not exist." What am I missing?
here are my codes.
BookController
public function create()
{
return view('books.create');
}
public function store(Request $request)
{
$this->validate($request, [
'book' => 'required|max:255',
'category' => 'required',
'quantity' => 'required|numeric',
'price'=>'required|numeric',
'info'=>'required'
]);
//$request->user()->member()->books()->create([
$member=auth()->user()->member()->get();
$member->books()->create([
'book' => $request->book,
'category' => $request->category,
'quantity' => $request->quantity,
'price'=>$request->price,
'info'=>$request->info
]);
return redirect('shops')->with('success', 'successful');
}
books.create
<form action="{{route('books.store')}}" method="POST" role="form">
#csrf
#method('POST')
<div class="form-group">
<label for="book">name:</label>
<input id="book" name="book" class="form-control" placeholder="enter book name">
</div>
<div class="form-group">
<label for="category">category:</label>
<input id="category" name="category" class="form-control" placeholder="enter category">
</div>
<div class="form-group">
<label for="quantity">quantity:</label>
<input id="quantity" name="quantity" class="form-control" placeholder="enter quantity">
</div>
<div class="form-group">
<label for="price">price:</label>
<input id="price" name="price" class="form-control" placeholder="enter price">
</div>
<div class="form-group">
<label for="info">info:</label>
<textarea id="info" name="info" class="form-control" rows="10" placeholder="enter info"></textarea>
</div>
<button type="submit" class="btn-sm btn-primary">create</button>
</form>
User and Member is one to one relation, and Book belongs to one Member
Book Model
public function member()
{
return $this->belongsTo(Member::class);
}
protected $fillable = ['book','category','quantity','price','info'];
Member Model
public function books()
{
return $this->hasMany(Book::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
User Model
public function member()
{
return $this->hasOne(Member::class);
}
books,user and member migration
books migration
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('member_id');
$table->foreign('member_id')->references('id')->on('members')->onDelete('cascade');
$table->string('name');
$table->integer('quantity');
$table->integer('price');
$table->string('path');
$table->string('info');
$table->string('category');
$table->timestamps();
});
}
member migration
public function up()
{
Schema::create('members', function (Blueprint $table) {
$table->increments('id');
$table->unsignedbigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('sex');
$table->string('email');
$table->string('address');
$table->string('tel');
$table->timestamps();
});
}
user migration
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->foreignId('current_team_id')->nullable();
$table->text('profile_photo_path')->nullable();
$table->timestamps();
});
}
You are receiving a Collection from this chain of calls:
$member = auth()->user()->member()->get();
get is going to always return a Collection when called on a relationship method. If you want a single model you can call first instead:
$member = auth()->user()->member()->first();
Though first could return null so you may need to check that.
Another method to access the result of this relationship would be to use the dynamic property for the relationship member:
$member = auth()->user()->member;
Since that relationship is defined as a HasOne it knows to load it for a single result or null.
Assuming $member isn't null at this point you should be fine with the rest how it is.
$member=auth()->user()->member()->get(); returns a collection not an object of Member class. Use $member=auth()->user()->member()->first(); or $member=auth()->user()->member;
Try this
public function store(Request $request)
{
$this->validate($request, [
'book' => 'required|max:255',
'category' => 'required',
'quantity' => 'required|numeric',
'price'=>'required|numeric',
'info'=>'required'
]);
$member=auth()->user()->member;
if($member){
$member->books()->create([
'book' => $request->book,
'category' => $request->category,
'quantity' => $request->quantity,
'price'=>$request->price,
'info'=>$request->info
]);
return redirect('shops')->with('success', 'successful');
}
//Member is not found, return with error
return redirect()->back()->with('error', 'Member not found');
}
That error is due to the fact that this call $member=auth()->user()->member()->get();. It's supposed to return a Collection of Member.
So when you try to call books on a collection hold by the variable member It' won't succeed as Illuminate\Support\Collection Class doesn't define a method books you have to loop trought that collection by using a foreach loop or a each or map method from Collection.
$member->each(function($member){
$member->books()->create([
//
]);
});
Or has you have already define in User Model that user will always have a single Member by using hasOne method.
So you can use auth()->user()->member()->first(); which return a single instance of type Member on which you call books method but with that you have to be sure that the Authenticated use has already one member which is attached to him to avoid any error. even though that is the case you can always check if variable $member is not null with an if statement
$member = auth()->user()->member()->first();
if($member){
// here you can have access to `books`
$member->books()->create([
//...
]);
}
Trying to write a function to create a new "profile" in my profiles table and get the following error:
"SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: profiles.about (SQL: insert into "profiles" ("dateofbirth", "state", "zipcode", "profilepic", "user_id", "updated_at", "created_at") values (2020-04-15, FL, 12345, /tmp/phpTT6CZr, 1, 2020-04-30 00:48:23, 2020-04-30 00:48:23))"
I've been reading answers to similar questions for the past few hours. Tried several different things, no luck so far. Hoping to see a solution that works in my code, and also get a better understanding of where exactly the error begins. The error message leads me to believe it's something to do with my "about" section in table. But unsure. I thought adding " protected $guarded = []; " to controller would solve but that gave the same result.
Here is what I'm working with:
Migration File:
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id'); //foreign key
$table->text('about')->nullable;
$table->text('profilepic')->nullable;
$table->date('dateofbirth')->nullable;
$table->unsignedinteger('zipcode')->nullable;
$table->string('state')->nullable;
$table->timestamps();
$table->index('user_id'); //index for foreign key
});
}
Profile Model:
class profile extends Model {
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
} }
I have also tried changing the profile model like below:
class profile extends Model {
public function user()
{
return $this->belongsTo(User::class);
}
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'dateofbirth' => 'datetime',
'zipcode' => 'unsignedinteger'
];
/*
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'about','profilepic','state', 'user_id', 'updated_at', 'created_at'
]; }
They both provide the same error message but with slightly different array values
Here is my controller store function:
public function store()
{
$data = request()->validate([
'dateofbirth' => 'required',
'state' => 'required',
'zipcode' => 'required',
'profilepic' => 'image'
]);
auth()->user()->profile()->create($data);
dd(request()->all());
}
Here is the view:
#extends('layouts.app')
#push('styles')
<link href="{{ asset('css/profile.css') }}" rel="stylesheet">
#endpush
#section('content')
{{-- This needs to present a create profile form --}}
<div class="row">
<h1 class="pl-4">CREATE YOUR PROFILE</h1>
</div>
<form action="/profile" class="pl-4" enctype="multipart/form-data" method="post">
#csrf
<div class="form-group row">
<label for="profilepic"
class="col-md-4 ocl-form-label"
>Upload a Profile Picture</label>
<input type="file"
class="form-control-file"
id="profilepic"
name="profilepic">
</div>
<div class="form-group">
<label for="about">Write your "About" Section here. What do you want us to know about you?</label>
<textarea type="text" class="form-control" id="about" name="about" rows="3"></textarea>
</div>
<div class="form-group">
<label for="dateofbirth">Date of Birth</label>
<input type="date"
id="dateofbirth"
name="dateofbirth">
</div>
<div class="form-group">
<label for="zipcode">Zipcode</label>
<input type="text" id="zipcode" name="zipcode">
</div>
<div class="form-group">
<label for="State">State</label>
<input type="text" id="state" name="state">
</div>
<div class="form-group row pt-4">
<button class="btn btn-primary">Submit</button>
</div>
</form> #endsection
That error means you're trying to set a foreign key column as null which is unacceptable, in this case, user_id on profiles table. Try to modify your code as such:
In your Profile model, add mass assignment columns:
protected $fillable = ['dateofbirth', 'state', 'zipcode', 'profilepic'];
In your controller store method:
//assuming the route method is authenticated such that there's always a logged in user
$user = auth()->user();
$data['user_id'] = $user->id;
$profile = Profile::create($data);
I'll add in also, I have since gotten this resolved with implementing #djunehor's answer. But one thing that helped get the problem resolved was adding in this to the controller:
public function store(Request $request)
At first I was not passing the request in and saving it to a variable like this, but this step seems to have made a big difference for the errors I was running into.
At first I was just doing this:
public function store()
I'm new at Laravel and not good with syntax. I have seen many tutorials and have read many answers, but still, my mind didn't get the point of how can I have a dropdown field for a foreign key.
I'm having one table "Section" and other "Class." I want to show the name of classes in section page.
Sections Migration
Schema::create('sections', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->integer('class_id')->unsigned();
$table->foreign('class_id')->references('id')->on('classses');
});
Classses Migration
Schema::create('classses', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->timestamps();
});
Honestly, I don't know if I should have changed my controller or not.
Blade/View
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" name="name" id="title">
</div>
<div class="form-group">
<label for="cid">Class</label>
???????????????
</div>
Index Function
public function index()
{ $sections = Section::all();
return view('sections.index', compact('sections'));
$classs = Classs::all()->pluck(['id', 'title']);
return view('sections.index')->with('classs', $classs); }
Error is Unreachable Statement at line $class & Expected string, got array at ([id,'title])
In your controller, you have a function to return the view.
Change it to include ->with(), so you can access the classes in the view:
// if the controller is not for the classes, add this up top:
use App\Classs; // include model name
$classs = Classs:all();
return view('yourView')->with('classe', $classs);
Then, in your view, you can just do this:
<div class="form-group">
<label for="cid">Class</label>
<select class="" name="cid">
<option value="null">Class</option>
#foreach($classs as $class)
<option value="{{$class->id}}">{{$class->title}}</option>
#endforeach
</select>
</div>
It loops over all the classes in your database and creates a <option> element for them. Looking at your first migration, you're using the id in the other table, so you need to set that as the value.
Change your index function to this:
public function index()
{
$sections = Section::all();
$classs = Class::all();
return view('sections.index')->with('sections', $sections)->with('classs', $classs);
}
Can you tell me where can I write conditions such as select * from class where role_id=2 etc.
Basically, in an MVC framework, you do all your queries in your controller and pass the data to the view, in which you display the data.
Laravel has a DB class which you can use for basic queries:
select * from class where role_id = 2
Would become this in Laravel, using the DB class.
DB::table('class')->where('role_id', 2)->get();
// or if it's a model:
Model::where('role_id', 2)->get();
I have now used this code in blade page
#php
use Illuminate\Support\Facades\DB;
$cid=DB::table('classses')->get();
$uid=DB::table('users')->where('role_id','3')->get();
$counter=0;
#endphp
<select class="" name="class_id">
<option value="null">Class</option>
#foreach($cid as $class)
#if($counter==0)
<option selected="selected" value="{{$class->id}}">{{$class->title}}</option>
{{$counter++}}
#else
<option value="{{$class->id}}">{{$class->title}}</option>
#endif
#endforeach
</select>
i am working on laravel phonebook application i want every phonebook to hasOne clients but the clients belongs to many phone books i have a column in my phonebook table called client_id now when i set relations how can i use them in controller and pass it into view as on object and here is some of my code
phonebook controller
public function index(){
$phonebooks = Phonebook::all();
$client = Phonebook::find(?dont know if its right place for it?)->client;
return view('admin.phonebooks.index',compact('phonebooks',$phonebooks),compact('client',$client));}
phonebook model
class Phonebook extends Model{protected $fillable = ['title','description','client_id','calldate','rememberdate'];public function client() {
return $this->hasOne('App\Client','id');} }
phonebook db migration
Schema::create('phonebooks', function (Blueprint $table) {
$table->increments('id');
$table->text('title');
$table->longText('description');
$table->integer('client_id');
$table->dateTime('calldate');
$table->dateTime('rememberdate');
$table->timestamps();
});
and the client db migration
Schema::create('clients', function (Blueprint $table) {
$table->increments('id');
$table->text('title');
$table->longText('description');
$table->integer('fax');
$table->text('adrress1');
$table->integer('telephone1');
$table->timestamps();
});
and the view that i want to show in it
#foreach($phonebooks as $phonebook)
<tr>
<th scope="row">{{$phonebook->id}}</th>
<th scope="row">{{$phonebook->title}}</th>
<td>{{$phonebook->description}}</td>
<td>{{$phonebook->calldate}}</td>
<td>{{$phonebook->created_at->toFormattedDateString()}}</td>
<td>{{$client->title}}</td>
<td>
<div class="btn-group" role="group" aria-label="Basic example">
<a href="{{ URL::to('admin/phonebooks/' . $phonebook->id . '/edit') }}">
<button type="button" class="btn btn-warning">edit</button>
</a>
<form action="{{url('admin/phonebooks', [$phonebook->id])}}" method="POST">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="submit" class="btn btn-danger" value="delete"/>
</form>
</div>
</td>
</tr>#endforeach
you have client property in Phonebook, use it
<td>{{$phonebook->client->title}}</td>
I would suggest loading all the clients with eager loading so it will be more efficient, you can read why on the docs
You could do this on your controller:
public function index()
{
$phonebooks = Phonebook::with('client')->get();
return view('admin.phonebooks.index',compact('phonebooks',$phonebooks);
}
Then in your view you can access the phonebook client thanks to the relationship you have defined doing this:
#foreach ($phonebooks as $phonebook)
{{ $phonebook->client->title }}
#endforeach