Eloquent create says column has no default value using Laravel 5 - php

I have an small API that i want to save into client mysql database.
For this purpose i'm using guzzle.
my controller:
public function index()
{
$http = new \GuzzleHttp\Client;
$res = $http->request('GET', 'http://localhost:8080/api/address');
$addresses = json_decode($res->getBody(),true);
// dd($addresses);
Address::create($addresses);
}
my model:
class Address extends Model
{
protected $primaryKey = 'Adresse';
protected $fillable = ['Adresse', 'Mandant', 'Kategorie', 'Matchcode', 'Name1'];
public $timestamps = false;
}
my migration:
public function up()
{
Schema::create('addresses', function (Blueprint $table) {
$table->integer('Adresse')->primary();
$table->smallInteger('Mandant');
$table->smallInteger('Kategorie')->nullable();
$table->string('Matchcode', 50);
$table->string('Anrede', 50)->nullable();
$table->string('Name1', 50)->nullable();
});
}
my api content:
[
{"Adresse":"1111","Mandant":"0","Kategorie":"0","Matchcode":"fgh8881","Anrede":"Firma","Name1":"Sample name"},{"Adresse":"2399","Mandant":"0","Kategorie":"0","Matchcode":"fgh8882","Anrede":"Firma","Name1":"Sample name 1"}
]
the problem is i get an error
SQLSTATE[HY000]: General error: 1364 Field 'Adresse' doesn't have a
default value (SQL: insert into addresses () values ())
when i limit the api content to one array i can save it without a problem. But if i have more arrays in my api i get this error.
$fillable property on the model is set.

If your primary key is not auto-incrementing the framework needs to know about it.
class Address extends Model
{
protected $primaryKey = 'Adresse';
protected $fillable = ['Adresse', 'Mandant', 'Kategorie', 'Matchcode', 'Name1'];
public $incrementing = false;
public $timestamps = false;
}
Then to add all of the models:
public function index()
{
$http = new \GuzzleHttp\Client;
$res = $http->request('GET', 'http://localhost:8080/api/address');
$addresses = json_decode($res->getBody(),true);
foreach ($addresses as $address) {
Address::create($address);
}
}

Your API content is essentially 2 records. For mass inserting using eloquent you need to use insert not create
So either
1) have your api return 1 result
2) or change Address::create($addresses); to Address::insert($addresses);

Set Adresse be auto-increment as well with primary key and your issue will be solved or If you do not want to set it to auto-increment then assign it to a default value.

check the table structure of addresses whether it have default value NULL need to change default

Related

Why is laravel push giving me a error 1364: Field 'question_entity_id' doesn't have a default value?

I'm very new to Laravel (this is my first time using it) and I'm trying to store some data that I made in a post request to my api. I keep on getting a General error: 1364 Field 'question_entity_id' doesn't have a default value.
I'm trying to use Laravel's push method to save the itemBank model and all it's relationships I define below but I get the error above. I've tried manually setting foreign_key relationships like `$itemBank->question_entity_id = $questionEntity->id' but this gives me the same error. I'm specifically trying to figure out why question_entity_id isn't getting filled (I know that the error could be resolved by making the field nullable or giving question_entity_id a default value).
Here are the relevant models:
class ItemBank extends Model
{
// table name
protected $table = "item_bank";
// do no use default timestamp fields
public $timestamps = false;
// item_bank relationships to other Models/tables
public function questionEntity() {
return $this->hasOne('App\QuestionEntity', 'id', 'question_entity_id');
}
public function optionEntity() {
return $this->hasMany('App\OptionEntity', 'item_id', 'id');
}
public function tagItemRel() {
return $this->hasOne('App\TagItemRel', 'item_id', 'id');
}
}
class QuestionEntity extends Model
{
// table name
protected $table = 'question_entity';
// disable default timestamps
public $timestamps = false;
public function itemBank() {
return $this->belongsTo('App\ItemBank', 'id', 'question_entity_id');
}
}
Here is the code where I'm trying to store my data:
public function store(Request $request)
{
$data = $request->all();
$itemBank = new ItemBank();
//save question body text
$questionEntity = new QuestionEntity();
$questionEntity->question = $data['questionBody'];
$itemBank->questionEntity()->save($questionEntity);
// save correct answer
$itemBank->correct_answers = $data['correctAnswer'];
//save question options
$choices = ['A', 'B', 'C', 'D'];
//$optionEntities = [];
foreach($choices as $choice) {
$optionEntity = new OptionEntity();
$optionEntity->choice = $data['choice' . $choice];
$optionEntity->choice_label = $choice;
$optionEntity->itemBank()->associate($itemBank);
}
//$itemBank->optionEntity()->saveMany($optionEntities);
//create new ItemTag Model
$itemTag = new ItemTag();
$itemTag->tag_name = $data['topic'];
//create new TagItemRel Model
$tagItemRel = new TagItemRel();
$tagItemRel->itemTag()->save($itemTag);
$tagItemRel->itemBank()->associate($itemBank);
$itemBank->push();
return $itemBank;
}
Here are the relevant migration files:
QuestionEntity:
Schema::create('question_entity', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('question', 500);
});
ItemBank:
Schema::create('item_bank', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('question_entity_id');
$table->string('correct_answers', 1);
$table->foreign('question_entity_id')->references('id')->on('question_entity');
});
Add question_entity_id in your ItemBank model, like this.
protected $fillable = [
'question_entity_id',
];
So your ItemBank model will look like this.
class ItemBank extends Model
{
// table name
protected $table = "item_bank";
protected $fillable = [
'question_entity_id','correct_answers'
];

Eloquent Many to Many attach() is passing a null model ID

I am developing an application using Laravel and Eloquent ORM, it uses a database filled with event information.
I have successfully implemented attach() in the relevant controllers for both my user and role models.
My Event model can have many Links. A Link can have Many events.
My problem is that the attach() is not supplying the ID of the object it is being called on, instead it supplies null and I receive the following error message:
SQLSTATE[23000]: Integrity constraint violation:
1048 Column 'link_id'
cannot be null (SQL: insert into 'event_link' ('created_at', 'event_id',
'link_id', 'updated_at') values (2018-06-09 11:27:15, 2, , 2018-06-09 11:27:15))
I've triple checked my models and database structure.
I can't even imagine how this error could occur since the id lacking in the SQL query is the id of the object that the attach() method is actually being called on. If I use sync($eventID, false) instead of attach(), the result is the same.
Event table:
Link table:
Event_Link table:
The following is the problematic method in the controller responsible for storing the record and creating an entry in the event_link weak entity.
The $link object is created successfully if the attach() line is commented out, a JSON representation of a link is returned which confirms this (but it lacks the 'id' field).
public function store(StoreLink $request) {
$link = Link::create([
'title' => $request->title,
'url' => $request->url,
]);
if ($request['eventId']) {
// $request->eventId is passed successfully, $link id is not passed.
$link->events()->attach($request->eventId);
}
return response()->json($link, 201);
}
Link Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Link extends Model
{
protected $table = 'links';
public $incrementing = false;
public $timestamps = true;
protected $primaryKey = "id";
protected $fillable = ['title', 'url'];
public function events()
{
return $this->belongsToMany('App\Event')->withTimestamps();
}
}
Event Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
{
protected $table = 'events';
public $incrementing = false;
public $timestamps = true;
protected $primaryKey = "id";
protected $fillable = ['description', 'date', 'image', 'category_id'];
public function category()
{
return $this->belongsTo('App\Event', 'category_id');
}
public function links()
{
return $this->belongsToMany('App\Link', 'event_link')->withTimestamps();
}
public function history()
{
return $this->belongsToMany('App\User', 'user_history');
}
public function favourites()
{
return $this->belongsToMany('App\User', 'user_favourites');
}
}
The problem is public $incrementing = false;: Remove the line from both your models.
Your id columns are defined as AUTO_INCREMENT, so $incrementing has to be true.

Laravel Multiple linking column in another table with relationships?

I'm trying to create a league table in Laravel but I'm running into some issues with guess what, relationships, again. They never seem to work for me in Laravel. It's like they hate me.
I have a modal for matches
<?php
namespace App\Database;
use Illuminate\Database\Eloquent\Model;
class Match extends Model
{
protected $primaryKey = 'id';
protected $table = 'matches';
public $timestamps = false;
protected $guarded = ['id'];
}
And a modal for teams, but with a matches() function
<?php
namespace App\Database;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
protected $primaryKey = 'id';
protected $table = 'teams';
public $timestamps = false;
protected $guarded = ['id'];
public function matches() {
return $this->hasMany('App\Database\Match', 'team_one_id, team_two_id');
}
}
I think the issue comes with team_one_id, team_two_id as the teams primary key could be in either one of them columns for the other table. When calling count() on matches() it throws an error.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'matches.team_one_id, team_two_id' in 'where clause' (SQL: select count(*) as aggregate from matches where matches.team_one_id, team_two_id = 1 and matches.team_one_id, team_two_id is not null)
can you try this syntax
return $this->hasMany('modelPath', 'foreign_key', 'local_key');
Does Match table have a column maned 'team_id'?
because it's the default naming convention in the laravel docs for mapping the tables.
if you do have the column and populate the data you can just remove the foreign & local keys from matches() relationship. you don't need it. Laravel will automatically map it for you.
if you do not have the 'team_id' on Matches table please add the column and add the respective team ids for matches.
<?php
namespace App\Database;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
protected $primaryKey = 'id';
protected $table = 'teams';
public $timestamps = false;
protected $guarded = ['id'];
public function matches() {
return $this->hasMany('App\Database\Match');
}
}
This way you can implement it, Add these relationship and a method in Team Model
public function homeMatches() {
return $this->hasMany('App\Database\Match', 'team_one_id');
}
public function awayMatches() {
return $this->hasMany('App\Database\Match', 'team_two_id');
}
public function matches() {
return $this->homeMatches->merge($this->awayMatches);
}
Now Fetch the data
$team = Team::find(1);
$matches = $team->matches(); //now it will fetch all matches for both columns
If you want to fetch matches as attributes then you can add one method
in your Team model
public function getMatchesAttribute()
{
return $this->homeMatches->merge($this->awayMatches);
}
Now you can fetch the matches as $matches = $team->matches;
Here is the difference
$team->matches returns Illuminate\Database\Eloquent\Collection
And
$team->matches() returns Illuminate\Database\Eloquent\Relations\{Relation Name}
You can't use matches in Eager loading like Team::with('matches') because matches is not a relationship and that causing your Error. What you can do is add homeMatches and awayMatches in eager loading and then call $team->matches().
$teams = Team::with('homeMatches', 'awayMatches')->get();
$teams->each(function ($team) {
print_r($team);
print_r($team->matches());
});

Laravel 5.5: Getting id after insert

I have a model hotel.php to insert hotel data.insert data using create() but it dosen't return id, the returning collection hasn't id field!
Controller.php
/** "/user/2/create" */
public function store(User $user, HotelRequest $request)
{
$slug = (new hotel)->uniqueSlug( $request->name );
$request->merge([
'cat_id' => 1,
'slug' => $slug,
'created_by' => auth()->user()->id,
]);
$hotel = $user->hotels()->create( $request->all() );
dd($hotel);
................
hotel.php (model)
namespace App;
use Illuminate\Http\UploadedFile;
use Illuminate\Database\Eloquent\Model;
class hotel extends Model
{
protected $fillable = ['name', 'description','address','street','city','email',
'phone','web','cat_id','slug','created_by'];
protected $primaryKey = 'slug';
/**
unique slugs genarating
*/
protected $slug_guards = ['create','room'];
public $incrementing = false;
User.php (model)
public function hotels( )
{
return $this->hasmany('App\Hotel');
}
and the final result
It dosen't have id attribute. I need id to upload image!
NB: I changed that primarykey to default 'id' but no change in result.
Create_hotels... migration
public function up()
{
Schema::create('hotels', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->index();
$table->integer('created_by');
$table->integer('cat_id');
$table->string('name');
Your hotel model set the primary key as the slug :
protected $primaryKey = 'slug';
What i usually do, is for all my migrations, i set an autoincrements like following :
$table->increments('id');
this way laravel handles everything for you. Each create, update or whatever method handle the id of your items.
With this, you can then return the id of a stored data this way :
$id = create($data)->id;
where $data is your model with new datas. $id should now contain the id value of the newest stored model datas.
You have to change the Hotel model (or remove the whole line):
public $incrementing = true;
You are dumping the data you just inserted into the db which does not contain a id field.
create a show method in your Controller class as follows
public function show(User $user){
dd($user)
}
with a route as follows:
Route::get('user/{user}', 'Controller#show')
In hotel.php before the protected $fillable declaration try adding
protected $guarded = [
'id',
];
In your controllers store() method just after $slug = (new hotel)->uniqueSlug( $request->name );
try adding a $slug->save(); then returned slug should have an ID returned with it.
and/or possible the same similar strategy after line
$hotel = $user->hotels()->create( $request->all() );
by adding $hotel->save();
I changed the primarykey to default id and $incrementing = true; now its returning id of the created data. I changed whole methodes in Controller

relationship array null when eager loading in laravel

I am having issues getting the relationship array back when eager loading in laravel 4. for example:
controller:
foreach (Apps::with('extra')->get() as $app)
{
print_r($app->toArray());//returns array but my relationship array at the bottom says null
echo $app->extra; //this will show my relationship details
}
model:
class Apps extends Eloquent
{
protected $connection = 'mysql_2';
protected $table = 'apps';
public $timestamps = false;
protected $primaryKey = 'name';
public function host()
{
return $this->belongsTo('Hosts','name');
}
public function extra()
{
$this->primaryKey='app_ip';
return $this->hasone('Extra','ip');
}
//other functions below.......
}
class Extra extends Eloquent
{
protected $connection = 'mysql_3';
protected $table = 'extra';
public $timestamps = false;
protected $primaryKey = 'ip';
public function app(){
return $this->belongsTo('Apps', 'app_ip');
}
mysql:
My mysql tables were not created through laravel they were previously existent. the app_ip column in the Apps table relates to the ip column in the extra table. it is a 1 to 1 relationship and I have specified the primary key in the relationship function. I am getting relationships back so I know that it is working.
I am able to get relationship data back when I call the function directly, but it does not show the relationship data when I try and print the full array. The main goal is to be able to return both the relationship columns and the app columns in one response.
You need to do this:
$apps = Apps::all();
$apps->load('extra');
foreach ($apps as $app)
{
print_r($app->toArray()); // prints your relationship data as well
}
What you have should work and iterating through the collection or using ->load() to eager load shouldn't make a difference. Are you using the visible restriction on your models? If so you will need to include the relationships.
class Apps extends Eloquent {
protected $visible = array(
'id',
'name',
'created_at',
'extra', // Make the relationship 'visible'
);
public function extra()
{
return $this->hasMany('Extra');
}
}

Categories