I want to use this code: Model::update($request);, However all fields in the table might be modified by a malicious user so I change the $fillable in the model to modify only the ones that user can modify not others. But now the problem is that I can't modify it myself by own values.
id name verified
1 Alex 0
if the data the malicious user sends inside $request is:
[
'name' => 'ModifiedAlex',
'verified' => 1,
]
so it will modify the table and get verified that is not good And when setting $fillable to only name:
$fillable = [
'name'
];
then I myself can't modify that with Model::where('id', $userId)->update(['verified' => 1]).
What to do then? Use $fillable or not?
Keep using fillable and eloquent for the malicious users.
You can use Query Builder to avoid the fillable for yourself. It doesn't check the fillable.:
DB::table('users')->where('id', $userId)->update(['verified' => 1]); // update with verified.
You can update records by object
$user = \App\User::find(1);
$user->verified = 1;
$user->save();
Where user is giving data you can use Model::where('id', $userId)->update($request->except('_token')) so it avoids any other fields.
$request->except('_token') gives you all the post data except the _token index
But for admin you can use save on object to update / create users
Related
I am using the updateOrCreate() function to update the record if a record is already available in the table based on some condition. However, I do not want to update one of my columns that contains a unique value.
I want to perform the same action to this column like created_at is working
while creating the records value is adding to the created_at column but while updating it contains the same.
To prevent this issue I removed that column name from $fillable in my model. But, in this case, it is not adding any value to this column.
protected $fillable = ['uid', 'channel', 'updated_at'];
$data = [
'uid' => Helper::generateUid(),
'channel' => $info['channel'],
'created_at' => time(),
'updated_at' => time(),
];
$cond = ['channel' => $info['channel']];
$isAdded = Templates::updateOrCreate($cond, $data);
Expected result
I don't want to update uid column if details already there.
Actual result
If details are not there it adds value to uid column and other columns also and if details are available then also it is updating uid column.
You can't do that with the updateOrCreate method. You'll need to be slightly more explicit. You can use the firstOrNew method to retrieve or instantiate a new object. And then you can use the exists property to determine if it is an existing or new object.
$template = Templates::firstOrNew(['channel' => $info['channel']]);
if (!$template->exists) {
$template->uid = Helper::generateUid();
}
$template->save();
I left out the created_at and updated_at fields because they are automatically handled by Laravel.
Laravel 5.5 introduces a new streamlined request validation. The idea being that:
$validData = $request->validate($rules)
will return only those fields that are present in the $rules. This is beneficial so that one can then simply User::create($validData) or User::update($validData).
However, I noticed that when I have additional data, which I do validate, but that doesn't exist in the model's (this case User) table, the create method inserts the record, but that the update method returns this error:
Column not found: 1054 Unknown column 'column_name' in 'field list'
I can of course write the relevant field lists out, or use other workaround, but I wonder why are the two methods are behaving differently?
e.g. passing
array:4 [▼
"first_name" => "Pedro"
"last_name" => "Taco"
"email" => "taco#example.org"
"operators" => array:1 [▼
0 => "1"
]
]
to User::create() inserts the record. Passing the same to User::update() returns an error.
User has $fillable = 'first_name', 'last_name', 'email'
I believe they behave the same but in update method you have some extra fields that are not in table in database, so you should verify what exactly you send and what exactly you validate to make sure there are no additional fields in $validData when you are updating user.
If you think that's not the case, please show us exactly how the validation looks like for creating and updating user.
If you want to update specific data use where
User::where('id',1)->update($validData);
If you want to update all rows try something like this
User::where('id','!=',-1)->update($validData);
OR
User::query()->update($validData);
If you are trying to use validations, you can decouple the code even further using Request validations.
Here you have a full example of applying Request validations and extracting just the necessary data to store (or update) objects:
1. Generation the request:
php artisan make:request CreateUserRequest
2. Custom the validation rules:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CreateUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
// you specify here a previous condition before access to the method
// can be Auth::check() for example
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
// put here your validation rules like:
'first_name' => 'required|string|max:100',
];
}
3. Modify the method in your controller:
public function store(CreateUserRequest $request)
{
// getting all the attributes
$data = $request->only('first_name', 'last_name', 'other_attribute..');
// creating the object
$user = new User;
// adding data
$user->fill($data);
// saving in database
$user->save();
return response()->json([
"message" => "The user has been created.",
"data" => $user,
], 201);
}
* Notice that the $request used as an argument is of type CreateUserRequest, so this indicates to Laravel wath rules to apply.
We have also only pull the data that we want to store (check the $request->only part), that seemed to be the root of your problem.
I have a table where i have user_id and role_id in it. Now if I select user_id =1 from dropdown and role_id = 2 from dropdown and save it ..Next time if I want to set same user another role instead of creating new row in table..How to update it without creating new one? can anyone suggest something?
$roleUser = RoleUser::firstOrNew(
['role_id' => $request->Input(['role_id']),
'user_id' =>$request->Input(['user_id'])] );
$roleUser->save();
I used the firstOrNew method but it creates a new entry instead of updating the old one.
I'm using this source code when Update or Create new record. Worked well with Laravel 5.2
If exist one record have user_id == your user_id => Will update role_id
Else will insert one more record for your user_id
$roleUser = RoleUser::updateOrCreate([
'user_id' => $request['user_id'],
],
[
'role_id' => $request['role_id'],
]);
Here is a code that should work. However, I don't quite understand your database architecture choice. If a user can only have one role, why don't you define a role_id in your users table, and then use a belongsTo relationship?
$role_user = RoleUser::where('role_id',$request->get('role_id'))
->where('user_id',$request->get('user_id'))
->first();
if (is_null($role_user)) {
RoleUser::create([
'user_id' => $request->get('user_id'),
'role_id' => $request->get('role_id')
])
}
so where's the issue here?
you are using firstOrNew method , which is similar to firstOrCreate typically do the following:
Select from the database
and if not exists
insert the given data
in case of using firstOrNew , you will need to ->save() to execute the query .
so it will not update your data if exists .
however, I think that you are looking for updateOrCreate method, which is take two array arguments , the first is the inserted data , and if exists the function takes the two array argument to update your row.
You may also come across situations where you want to update an
existing model or create a new model if none exists. Laravel provides
an updateOrCreate method to do this in one step. Like the
firstOrCreate method, updateOrCreate persists the model, so there's no
need to call save():
$roleUser = RoleUser::updateOrCreate(
// if not exists, insert the following RoleUser data
['role_id' => $request->Input(['role_id']),'user_id' =>$request->Input(['user_id'])],
// otherwise, update RoleUser set role_id = ?
['role_id' => $request->Input(['role_id'])]
);
$roleUser = RoleUser::firstOrNew(array('role_id' => Input::get('role_id')));
$roleUser ->save();
you can add multiple fields..
example..
If there's a flight from Oakland to San Diego, set the price to $99.
If no matching model exists, create one.
$flight = App\Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99]
);
`
Let's say I have an endpoint for user submitted forms. The form input will be stored as a JSON object in a column of a database table, and the user ID will be stored in another. Because I don't want users to be able to somehow set any user ID they want, I've left the user_id column out of the $fillable variable of the Eloquent model.
The create() method accepts an array of key/value pairs to be assigned, but will only assign values to fillable columns. How do I add the user's ID to the guarded user_id column at the same time? Do I have to fetch the last row and update the user ID as a second operation?
Thanks for all help, it's much appreciated.
IF you don't have attribute in $fillable it doesn't mean you cannot fill it.
The $fillable property holds the attributes that could be filled using create() or fill() method but you can still set value for any attributes using property access.
So let's assume you have Model with email, something and else properties. You set $fillable like so:
protected $fillable = ['email', 'something'];
Now let's assume you have data like this:
$data = [
'email' => 'sample#example.com',
'something' => 'foo',
'else' => 'bar',
];
so now when you use:
Model::create($data);
you will have filled only email and something because those are in $fillable and else won't be filled because it's not, but you can always do something like this:
$model = new Model($data);
$model->else = 'bar';
$model->save();
so you can set here else property value even if it's not inside $fillable but you need to access it like normal property.
Is there a way to map field names to a database to a different attribute name in the model? For example, if the database has a field name of customer_id but I wanted to use eloquent in this way Customer::get(['id']) I've tried using the getAttribute method but that is called after eloquent has attempted to get the value.
You can use accessors to work with such attributes, but there's no way to query them this way with core eloquent.
But fear not! Use this package https://github.com/jarektkaczyk/eloquence and you can easily achieve what you want (Mappable in particular):
// Customer model
protected $maps =[
'id' => 'customer_id',
'name' => 'customer_name',
...
];
// then you can do this:
$customer = Customer::where('name', 'whatever')->first();
// calls WHERE customer_name = ? sql
$customer->id; // customer_id column
$customer->name; // customer_name column
$customer->name = 'different name'; // set mutator works as well
It's in heavy development and currently select is not yet supported, but it's matter of day or two. select support has been pushed already.