Laravel First Or New - php

I seem to be getting the same error when I use UpdateOrNew or FirstOrNew in Laravel, to the best of my knowledge I have implemented the code correctly.
Current Code
$updateOrCreate = Rating::firstOrNew(
array(
'user_id' => Auth::user()->id,
'video_id' => $_POST['videoId']
)
);
$updateOrCreate->user_id = Auth::user()->id;
$updateOrCreate->video_id = $_POST['videoId'];
$updateOrCreate->rating = $_POST['rating'];
if($updateOrCreate->save()){
echo "saved";
}else{
echo "failed";
print_r($_POST);
};
Error
error: {type:Illuminate\Database\Eloquent\MassAssignmentException, message:user_id,…}
file: "/home/celeb/public_html/dev/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php"
line: 411
message: "user_id"
type: "Illuminate\Database\Eloquent\MassAssignmentException"

You need to enable mass assignment in your model as such:
class User extends Eloquent {
protected $fillable = array('first_name', 'last_name', 'email');
}
So any field that can be mass assigned should be in the $fillable variable.
Assigning values without mass assignment:
$user = new User;
$user->id = 3;
$user->name = "Joe";
$user->save();
Assigning values with mass assignment:
$userDetails = array('id' => 3, 'name' => 'Joe');
$user = User::create($userDetails);

"You may also use the create method to save a new model in a single line. The inserted model instance will be returned to you from the method. However, before doing so, you will need to specify either a fillable or guarded attribute on the model, as all Eloquent models protect against mass-assignment". [See Laravel Documentation on Eloquent Insert, Update, Delete ]
(http://laravel.com/docs/5.0/eloquent#insert-update-delete)
That means, only the create method can protect your codes from mass assignment:
/*$user=*/ User::create(array(
'name' => 'Max',
'email' => 'example#example.com'
));
When using the create method, you specify the model's name which is User from the example above. This model (usually User.php) is the place where you assign the mass assignable variables:
protected $fillable = ['name', 'email'];

Related

Why do I have error when inserting new data?

I'm trying to override Voyager view "edit-add view" by adding one new input with the same controller.
But when I try to add new data I face this error.
"SQLSTATE[HY000]: General error: 1364 Field 'Category_id' doesn't have
a default value (SQL: insert into `users` (`name`, `email`,
`password`, `role_id`, `updated_at`, `created_at`) values (ali12345,
ali12345#ali12345.com,
$2y$10$qrHhwTFhnjluM7heNE.WCOwSbFIVsag4GWJzunZQGSLgdcXD2r21a, 3,
2019-04-25 22:45:45, 2019-04-25 22:45:45))"
I had tried to add fillable in the model but I didn't have a solution.
protected $fillable = [
'id',
'role_id',
'name',
'email',
'avatar',
'password',
'remember_token',
'settings',
'created_at',
'updated_at',
'Category_id'
];
First of all, the issue is because you don't set the default value for Category_id in your table.
If you are sure that your request has the Category_id field, please ensure that you pass all the required fields when inserting a new record.
Let me give you some example of doing it with your case (Blocks of codes below should be somewhere in your Controller). Also I'll give you my favorite way to insert a new record.
Using Input facades:
public function create(Request $request)
{
$user = new User;
$user->username = Input::get('role_id');
$user->name = Input::get('name');
$user->email = Input::get('email');
$user->password = Hash::make(Input::get('password'));
$user->Category_id = Input::get('Category_id');
$user->save();
return Redirect::back();
}
This one is my favorite way to do it:
public function create(Request $request)
{
$user = new User;
$data = $this->cleanUnfillableFields($request->all(), $user->getFillable());
$user->create($data);
return Redirect::back();
}
/**
* This removes/unsets fields that are not fillable from the model.
* This is the magic method where you should put in a separate class or a trait,
* so all controllers can share this method.
*
* #param array $data
* #param array $fillableFields
*
* #return array
*/
protected function cleanUnfillableFields(array $data, array $fillableFields): array
{
foreach ($data as $key => $value) {
if (! in_array($key, $fillableFields))
unset($data[$key]);
}
return $data;
}
With my way above, you won't need to be hassle filling out each model's attribute and filtering out unnecessary fields anymore, as long as you set the fillable fields correctly and you have the required fields in your request.

SQLSTATE[HY000]: General error: 1364 Field 'name' doesn't have a default value laravel 5.5

I'm staring with Laravel and I'm having troubles trying to make a simple insert, but It seems that all of my fillable fields are not being included. This is the error:
SQLSTATE[HY000]: General error: 1364 Field 'name' doesn't have a default value
(SQL: insert into `addresses` (`updated_at`, `created_at`)
values (2017-12-25 09:31:49, 2017-12-25 09:31:49))
As you can see, only created_at and updated_at are about to be inserted, I thought that maybe I forgot my fillable vars, but this is my Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Addresses extends Model
{
protected $fillable = [
'name',
'city',
'suburb',
'street',
'o_number',
'i_number',
'postal_code',
'phone_s',
'email_s',
'google_map',
'customer_id'
];
}
And the Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Addresses;
use App\Customers;
class AddressesController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function store(Request $request){
$create = Addresses::create([
'name' => request('name'),
'city' => request('city'),
'suburb' => request('suburb'),
'street' => request('street'),
'o_number' => request('o_number'),
'i_number' => request('i_number'),
'postal_code' => request('postal_code'),
'phone_s' => request('phone_s'),
'email_s' => request('email_s'),
'google_map' => request('google_map'),
'customer_id' => Customers::where('code',$request->session()->get('customer_code'))->first()->id
]);
$success = $create ? $request->session()->flash('success', '¡Registro exitoso!') : $request->session()->flash('success', 'Ooops! Algo salio mal :(');
return redirect('addresses/'.$request->session()->get('customer_code'));
}
}
Echo the request() values works! So I'm missing right now, I have some other Models and Controller working good in the same way. Please Help!
This error show because you the NAME field is required on your database. Try to edit your migration script and put default value on this field or make it nullable.
eg.
$table->string('name')->nullable();
OR
$table->string('name')->default('');
Then run a migration refresh.
Goto "phpmyadmin" >> "Variables" then find "sql_mode" edit and remove "STRICT_ALL_TABLES or STRICT_TRANS_TABLES"
It is working for me.
Hope it will help for All.
This is late answer for this question, but it might help for others.
This error can be occurred due to error in $fillable data in modal.
You can try using
protected $guarded = []
instead of
protected $fillable = [
'name',
'city',
'suburb',
'street',
'o_number',
'i_number',
'postal_code',
'phone_s',
'email_s',
'google_map',
'customer_id'
];
But You have to validate the data that you passed within the controller.
The error occurs due to the strict mode of MYSQL5.7. Please change your config/database.php in the connections.mysql section by putting 'strict' => false.
I solved it using save()
$addresses = new Addresses;
$customer_id = Customers::where('code',$request->session()->get('customer_code'))->first()->id;
$addresses->name = $request->name;
$addresses->city = $request->city;
$addresses->suburb = $request->suburb;
$addresses->street = $request->street;
$addresses->o_number = $request->onumber;
$addresses->i_number = $request->inumber;
$addresses->postal_code = $request->postal_code;
$addresses->phone_s = $request->phone_s;
$addresses->email_s = $request->email_s;
$addresses->google_map = $request->map;
$addresses->customer_id = $customer_id;
$success = $addresses->save() ? $request->session()->flash('success', '¡Registro exitoso!') : $request->session()->flash('success', 'Ooops! Algo salio mal :(');
return redirect('addresses/'.$request->session()->get('customer_code'));
It's working properly
When you use the nullable() method on a field, that field will default to NULL.
For example, add this to your migration file:
$table->string('name')->nullable();
Update:
You can add:
$table->string('name')->nullable()->default(null);
You can check Null option in table structure, like this -
Make sure request() has key 'name'.Replace request('name') to random string and try again.
In my case I forgot to change - this is my code on my Controller
public function store(Request $request)
{
$message = new Message();
$message->name = $request->input('name');
$message->name = $request->input('message');
$message->save();
}
I made a duplication of the 'name' that's why it happened and made this
public function store(Request $request)
{
$message = new Message();
$message->name = $request->input('name');
$message->message = $request->input('message');
$message->save();
}
This way the solution to the problem.
I was having this problem because I didn't add a correct column under $fillable list.
class Chirp extends Model
{
use HasFactory;
protected $fillable = [
'message', // This line should be added.
];
}

Laravel hide foreign_key field on JSON response but access to create new entry

I would like to hide my foreign_key on JSON response :
return Response::json(['type' => 'success', 'data' => $my_object, 'status' => 200], 200);
I added in my model :
protected $hidden = ['fk_category_id'];
My foreign key is hide !
But in my controller I have this :
$new_question = $this->question_repository->create([
'text' => $question->text,
'fk_category_id' => 2,
]);
The problem : I don't create a new object in my database, the field fk_category_id is NULL, I think I have no access to this field
My foreign key in my JSON response it's hide (great!) but I can't set my foreign key in my database when I created new entry.
add this to your model
protected $fillable = [..,'fk_category_id','text'];
you are attempting to do mass assignment, fillable is a whitelist which field will be fillable by mass assignment. .. means you can add whatever field you want there.
I saw your entity in your last (deleted) question. Add a setter function, then you can call that! Your protected and private properties will remain hidden!
class MyEntity
{
private $hidden;
public function getHidden()
{
return $this->hidden;
}
public function setHidden($value)
{
$this->hidden = value;
}
// the rest of your code etc
}

Yii2 saving model with relationship property

iam trying to save model from form, that have relationship defined via junction table, but since the property is relationship object it is read-only and it fails on validation.
Model relationship:
public $payer
/**
* #return \yii\db\ActiveQuery
*/
public function getPayerRelationship()
{
return $this->hasMany(PartyRelationship::className(), ['contract_id' => 'id'])->where(['relationship' => 'P']);
}
public function getPayers(){
return $this->hasMany(ContractingParty::className(), ['id' => 'contracting_party_id'])
->via('payerRelationship');
}
public function getContractors() { // could be a static func as well
$model = ContractingParty::find()->asArray()->all();
return ArrayHelper::map($model, 'id', 'subject_name');
}
Form view:
<?= $form->field($model, 'payers')->widget(Select2::classname(), [
'data' => $model->getContractors(),
'language' => 'en',
'options' => ['placeholder' => '-- Select company --'],
'pluginOptions' => [
'allowClear' => true,
'multiple' => true,
],
'showToggleAll' => false
]) ?>
It wont validate or save, because of read-only property payers. I tried to use different property in $form->field($model, 'payer'... (instead of payers), then validation works and even saving works, but trouble is, that editing have no preselected values of that model, because they are in model->payers. And i have no idea, what iam supposed to pass here instead of this relationship object (or property of model in general).
Maybe iam plainly blind, but in manual there is a lot of information about getting data from db, but almost no info about saving.
(btw. i saw this post: Yii2 Invalid Call: Setting read-only property - but that didnt give me any new piece of information at all).
Is my form design wrong, or model design (Meaning i should just create form field using two models)? Thanks
Adding setters to model:
public function setPayer(){
$payer_id_array = array();
$payer_array = ArrayHelper::toArray($this->payers);
foreach ($payer_array as $value){
$payer_id_array [] = $value['id'];
}
$this->payer = $payer_id_array;
}
public function setRecipient(){
$recipient_id_array = array();
$recipient_array = ArrayHelper::toArray($this->recipients);
foreach ($recipient_array as $value){
$recipient_id_array [] = $value['id'];
}
$this->recipient = $recipient_id_array;
}
and manually into controller (action create and update):
$model->setPayer();
$model->setRecipient();
seems to fix the conflict between the names of relation and property passed into the field.

Laravel validation service with unique fields

I'm using a validation service to validate user submitted form input (something along the lines of: http://laravel.io/bin/vrk).
Using this approach (validation service classes) to validate user submitted form data against a set of rules, how can I validate user submitted data when rules have a unique rule. For example, if a user has the username of John then when I try to update the model validation fails (because John exists as a username, even though it belongs to the current model).
To solve this in Laravel I can do something like 'username' => 'required|alpha_dash|unique:users,username'.$id. How should I modify my current code, in the link, to best accommodate this? Should I have separate validator classes depending on the scenario (for example, UserCreateValidator, UserUpdateValidator, etc). Or should I do something like create separate validation rules in UserValidator class and pass which rule I want as an argument to either the constructor or the passes() method when calling UserValidator?
I think you could do something like this
First update UserValidator rules like this.
class UserValidator extends Validator {
// Override parent class $rules
protected $rules = [
'default' => [
'username' => 'required|alpha_dash|unique:users',
'password' => 'required|between:6,16|confirmed',
'password_confirmation' => 'required|between:6,16'
],
'update' => [
'username' => null,
]
];
}
Then modify Validator's passes method like this
public function passes($rule = null) {
$rules = $this->rules['default'];
if ($rule && isset($this->rules[$rule])) {
$rules = array_merge($rules, $this->rules[$rule]);
}
$validator = \Validator::make($input, $rules);
if ($validator->fails()) {
$this->validator = $validator;
return false;
}
return true;
}
Then in your controller's PUT method, this will merge update rules to default rules
$rule = 'update';
// user has changed his username
if ($input['username'] !== $old_username) {
$rule = 'create'; // validate uniqueness
}
else {
unset($input['username']); // remove it, we don't validate it anymore since it's the same
}
$validator->passes($rule); // override 'default' rules with 'update' rules
You don't have to change your controller's POST method, it'll stay the same
$validator->passes(); // use 'default' rules
If I'm understanding right, you have issues updateng data because of primary key constraints on your model. What you need to do is to create 2 sets of rules, one for insert, and one for update.
Asuming you have a set of rules like this:
protected $rules = [
'id' => 'required|unique:users'
]
You should implement something like this:
protected $rules = [
'id' => 'required|unique|unique:users,id,' . $this->id
];
This should tell laravel to ignore the duplicate id in the table users for the specified id, in this case, the id for the current object.
You can read more about this on laravel's documentation at http://laravel.com/docs/validation
unique:table,column,except,idColumn
The field under validation must be unique on a given database table.
If the column option is not specified, the field name will be used.
Well, what are you doing on post?
Because this is what you should be doing:
$user = User::find($userId);
$user->username = $input['username'];
$user->email = $input['email'];
$user->save();
To update a record.
Or
$input = array('username' => 'w0rldart', 'email' => 'hahafu#dumbledore.com');
// Retrieve the user by the attributes, or create it if it doesn't exist,
// based on the data above, which can come from an Input::all();
$user = User::firstOrCreate($input);
... many possibilities. But you could also do:
$input = array_forget($input, 'username');
To comply with your case, by removing the username index from the input array.
This is all I call tell you, based on the information you gave us. If you want more, post the controller's put method.
Update:
Here's my version of your PUT method: http://laravel.io/bin/OaX
I really think that try catch syntax is useless, since it's obvious that a User model will always be there. But I still don't know what you're trying to update. Even though I can't test it right now, I don't think that updating should be giving that problem, and if it does, retrieve user by username/id then unset the username index in your input array, and update it according to your specifications.
A little modification in UserValidator class
class UserValidator extends Validator {
// Override parent class $rules
protected $rules = [
'username' => 'required|alpha_dash|unique:users',
'password' => 'required|between:6,16|confirmed',
'password_confirmation' => 'required|between:6,16'
];
// ADD THIS
public function __construct(Array $rules = array())
{
parent::__construct();
if(count($rules)){
foreach($rules as $k => $v) $this->rules[$k] = $v;
}
}
}
In your controller putUpdate method
$user = User::whereUsername($username)->firstOrFail();
$rules = ['username' => 'required|alpha_dash|unique:users,username,'. $user->id];
// Pass the rule to update the rule for username in this method
$validator = \Services\Validators\UserValidator(Input::all(), $rules);
Check the manual here.

Categories