How the save autoincrement values using laravel eloquent - laravel-5

I am trying to save data into a database using Laravel eloquent models. However, the primary key is an auto-increment integer and it's throwing an error:
SQLSTATE[HY000]: General error: 1364 Field 'property_valuation_id' doesn't have a default value.
Any help on how this can be solved.
Here is the controller:
public function index(Request $request)
{
$property_valuation = new PropertValuation();
$property_valuation->property_valuation_id="";
$property_valuation->integer('property_valuation_id')->default(1);
$property_valuation->district_id = $request->input('district');
$property_valuation->propertyneighbourhood = $request->input('neighborhood');
$property_valuation->propertystreet = $request->input('street');
$property_valuation->numberofbedrooms =$request->input('bedrooms');
$property_valuation->currency=$request->input('currency');
$property_valuation->monthlyrent=$request->input('rent');
$property_valuation->save();
}
And here the model:
class PropertValuation extends Model
{
protected $table = 'property_valuation';
public $primaryKey = 'property_valuation_id';
public $timestamps = false;
}

You're overwriting Laravels default behaviour with this lines
$property_valuation->property_valuation_id="";
$property_valuation->integer('property_valuation_id')->default(1);
Remove it and it should be ignored within the SQL query and the auto-increment value should be set.

First of all you should use
$table->bigIncrements('property_valuation_id');
or
$table->increments('property_valuation_id');
in your migration file and then run in console php artisan migration:fresh to update your db structure. Aslo your why you are using custom field increment name instead of default 'id' ?
Second you must do is to set value for fillable variable in your Model. No need to include autoincrement field in this array.
protected $fillable = ['neighborhood', 'district',.....];
And the last thing. It is unnessessary to set all values for model from request, laravel do it itself. So your controller store method might be
public function store(Request $request)
{
PropertValuation::create($request->all());
return redirect()->back();
}
Much cleaner, yeah? :)

Related

How do I declare a composite primary key in the Lumen Model?

I have a table with three primary keys, I'm trying to create a model for it, and I'd like to use the find () function, but it throws the error:
Code:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Visit extends Model
{
protected $table = 'ft_visit';
protected $primaryKey = ['sk_time', 'sk_region', 'sk_device'];
protected $fillable = [
'sk_time', 'sk_region', 'sk_device', 'ds_page',
];
public $timestamps = false;
public function time()
{
return $this->belongsTo(Time::class, 'sk_time');
}
}
Error:
(1/1) ErrorException
mb_strpos() expects parameter 1 to be string, array given
You can try the solution presented in this article Solved: Eloquent doesn’t support composite primary keys.
Adding the setKeysForSaveQuery method below on your model, and removing the $primaryKey attribute, you might be able to add this otherwise not supported functionality to your Eloquent model.
<?php
use Illuminate\Database\Eloquent\Builder;
class Visit extends Model {
public $incrementing = false;
protected function setKeysForSaveQuery(Builder $query)
{
$query
->where('sk_time', '=', $this->getAttribute('sk_time'))
->where('sk_region', '=', $this->getAttribute('sk_region'));
->where('sk_device', '=', $this->getAttribute('sk_device'));
return $query;
}
}
EDIT: As noted by #Devon this might affect Eloquent in other ways and should be tested thoroughly before use. However, this should give you some clearance on the way to solve it, should you not be in a position where you can (preferably) restructure the application or data.
Eloquent does not support composite keys. The best thing to do in this scenario to ensure Eloquent compatibility is to convert your existing primary composite key to a unique composite key and add an autoincrement primary key (id) for Eloquent to use.
Unfortunately you can't. Laravel and lumen (using Eloquent) do not support composite keys.

Can eloquent ignore irrelevant data in Laravel 5.7

This is basically the same question as this here from 2013. Except the answer doesn't work for me.
I have a Model App\Post:
class Post extends Model
{
protected $fillable = ['title'];
// This Model doesn't contain an 'authorname' field
public function author()
{
return $this->belongsTo('App\Author');
}
}
and a Model App\Author:
class Author extends Model
{
protected $fillable = ['name'];
public function posts()
{
return $this->hasMany('App\Post');
}
}
And an array I want to save to that Model:
$posts = [
['title'=>'one post', 'authorname' => 'Mickey'],
['title'=>'another post', 'authorname' => 'Minny'],
];
foreach($posts as $post){
$authorModel=App\Author::firstOrCreate(['name'=>$post['authorname']]);
App\Post::create($post)->author()->associate($authorModel)->save();
}
According to this question, that should work, but I get an
SQL error 42522: Column not found: 1054 Unknown column 'authorname' in 'field list'
which suggests Laravel forwards the whole array to mySQL. Is there a way to make this work without unsetting the authorname key?
Obviously this is a simpified version of what I want to do and keeping track of what to unset seems unnecessary - as would be assigning all array keys to their respective database fields manually.
The only idea I have here is that you run this code in DatabaseSeeder (which automatically unguards models) or you somewhere manually call Eloquent::unguard() (or code similar to this). This would explain why any other fields are used when creating model no matter of $fillable property.

Why can't use create method when not all attributes are in $fillable array in Laravel

I am using laravel framework and I am trying to create a new record in the table "product"
and the table has 4 fields ('id','name','price','sec').
when I am writing this code a new row is added to the table successfully
class productModel extends Model
{
public $fillable = ['price','name'];
public $table = 'product';
public $timestamps = false;
public static function add(){
$model = new productModel();
$model->price = 6;
$model->name = 'pro2';
$model->sec = 33;
$model->save();
}
}
but when I write this code an error shows:
QLSTATE[HY000]: General error: 1364 Field 'sec' doesn't have a default value (SQL: insert into product (name, price) values (Flight 10, 44))
class productModel extends Model
{
public $fillable = ['price','name'];
public $table = 'product';
public $timestamps = false;
public static function add(){
productModel::create(['name' => 'Flight 10','price' => 44,'sec' =>
'content']);
}
}
but when I put the 'sec' field in the $fillable array it works well so what the problem?
The error you're getting is coming from your database, not Laravel.
When you assign the value explicitly (as in your first snippet), you aren't mass assigning it, so it doesn't matter what's in $fillable. You're giving it a value, so your database is happy.
When you don't have 'sec' in the fillable array, it's not getting assigned a value when you use create (which is mass-assigning the values). So, when Laravel goes to save your data, it's passing null to the database, which then responds with, "hey, this field isn't nullable and there's no default, so you have to tell me what to put into it."
So, your options are:
Update your database schema to make the field nullable, or add a default value at the database level.
Put "sec" into your $fillable array, so that it can be mass-assigned.
Set it explicitly somewhere in the create flow (either where you're setting the data or in some middleware layer, such as validation).
Which way you choose will depend on your needs.

laravel Eloquent ORM custom field name

I am trying to get record from a products table with the field productsid by using Eloquent and using the following code. My model name is Products_description.
In my route file.
Route::get('product/{productsid}','productscontroller#show');
In my controller file
public function show($productid)
{
$Products = Products_description::find($productid);
return $Products;
}
But it showing me the error that Unknown column 'products_description.id'. Looks like Eloquent try to get record through the field name id by default like it do with the table names. But how to get records through a table field other than id. e.g. if it is productid, what we would do/use?
In your model, declare your $primaryKey
class Products_description {
protected $primaryKey = "productid";
//
}
This way you can use ::find or firstOrFail and not where.
like this
$Products = Products_description::where('pruductid',$productid)->first();
or you can try this
Products_description model
class Products_description extends Eloquent {
protected $primaryKey = 'productid';
}
I am assuming your need is to query your table for a field other than the primary key . You can use:
Products_description::where('productid',$productId)->first()
If you are speaking about foreign keys, then you should define them in the model like so :
return $this->hasOne('App\Phone', 'foreign_key');
Here is the relevant documentation :
https://laravel.com/docs/5.1/eloquent-relationships#one-to-one

How to use a protected property in an Eloquent model without Laravel trying to save it to the database

In one of my models, I have an attribute named "slug". When the slug is changed, I need to record the original slug before updating it to the new one, so my model has a protected property "originalSlug". Before saving the model, I do something like this in my model:
protected $originalSlug;
public function customSave($newSlug){
$this->originalSlug = $this->slug;
$this->slug = $newSlug;
return $this->save();
}
Then I have an event that does other tasks using that originalSlug after a successful save.
The problem is Laravel is trying to save the originalSlug to the database though it isn't actually an attribute and doesn't have a database column. So it fails with the "Column not found" error.
What could I do to get Laravel to ignore that originalSlug property, or is there a better way I should be doing this?
If you want Eloquent to ignore a property, it needs to be accessible to set, otherwise __set will be called and Eloquent will treat it as an attribute.
You can alternatively use mutator for this.
So here's what you need:
public $originalSlug;
public function customSave($newSlug){
$this->originalSlug = $this->slug;
$this->slug = $newSlug;
return $this->save();
}
or:
protected $originalSlug;
public function customSave($newSlug){
$this->originalSlug = $this->slug;
$this->slug = $newSlug;
return $this->save();
}
public function setOriginalSlugAttribute($value)
{
$this->originalSlug = $value;
}
Then Eloquent will not set an originalSlug attribute , so it won't be saved to the db.
You can do that with events, like suggested in the comments, and I would suggest this way too.

Resources