Eloquent updateOrCreate hide columns while updating - php

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.

Related

Can I get the primary key inside the facadesdb insert for direct use - Laravel 8

I am learning Laravel 8 and came across this problem. So, I made a controller class with FacadesDB Insert function. This is my code :
public function aksimenulis_laporan(Request $request){
$filefoto = $request->foto;
DB::table('pengaduan')->insert([
'tgl_pengaduan' => date('Y-m-d'),
'nik' => $_POST['nik'],
'isi_laporan' => $_POST['isi_laporan'],
'foto' => $filefoto->getClientOriginalName(),
'status' => '0',
]);
// isi dengan nama folder tempat kemana file diupload
$tujuan_upload = storage_path();
// upload file
$filefoto->move($tujuan_upload,$filefoto->getClientOriginalName());
return redirect('');
}
https://i.stack.imgur.com/VTJyS.png
This is my database table structure.
And I am trying to insert 'foto' with value of 'id_pengaduan' or the primary key, like using this code. Which will be PrimaryKey_OriginalFileName
'foto' => $filefoto-> 'id_pengaduan'.'_'.getClientOriginalName(),
But the problem I didn't have the value yet. Is there a way that I can value 'foto' with the primary key of the table?
you can use the insertGetId method to insert a record and then retrieve the ID:
$pengaduan_id= DB::table('pengaduan')->insertGetId([
'tgl_pengaduan' => date('Y-m-d'),
'nik' => $_POST['nik'],
'isi_laporan' => $_POST['isi_laporan'],
'status' => '0',
]);
DB::table('pengaduan')->where('id',$pengaduan_id)->update(['foto'=>$filefoto->getClientOriginalName()]);
you can not get the id before the insertion operation is done.
you also should do it in transaction, but for now, I will keep it this way.
You cannot (and shouldn't) insert a row and define its primary key. That's kind of the whole purpose of a primary key. You let SQL manage its identifiers, this is good incase of an error, so there are no duplicates in the primary key.
I'll go into eloquent since you're starting new in Laravel, this will make your life easier with DB operations.
First you'd need to make a new model for your table. You can do this using the console command:
php artisan make:model ModelName
Afterwards, navigate to your Models directory (app/Models/) and you'll find the new model ModelName.php
In there, you'd need to specify the table name and the primary key. You can do that with the these two lines:
protected $table = 'pengaduan';
protected $guarded = ['id_pengaduan'];
Your model should now look something like
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ModelName extends Model
{
use HasFactory;
protected $table = 'pengaduan';
protected $guarded = ['id_pengaduan'];
}
Save, and you might need to clear your cache. Do this by running php artisan optimize in the console.
After you are done inserting the data into a new row, you can get the primary key that was assigned to the row like this:
//using eloquent
use App\Models\ModelName;
//insert data
$insertRow = new Pengaduan;
$insertRow->tgl_pengaduan = date('Y-m-d');
$insertRow->nik = $_POST['nik'];
$insertRow->isi_laporan= $_POST['isi_laporan'];
$insertRow->foto = $filefoto->getClientOriginalName();
$insertRow->status = 0;
$insertRow->save();
//get key here
$rowId = $insertRow->pengaduan_id;
If you want to use the DB::table('table')->insert method, see OMR's answer.
If you really want to define the primary key yourself, then you'd have to run this query on the table:
SET IDENTITY_INSERT [Tablename] ON;
You can read more about this on this thread.

Laravel - USING or NOT USING fillable in laravel model?

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

laravel eloquent : How to update data if exist

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]
);
`

Eloquent: How do I assign values to guarded columns while using the create() method?

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.

Mapping field name in model using laravel

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.

Categories