custom `id` name using `insertGetId` fluent method of Laravel - laravel

According to Laravel's documentation:Inserts
Note: When using PostgreSQL the insertGetId method expects the auto-incrementing column to be named "id".
So, is there a workaround for a custom id name while using inserGetId. i.e.
$id = DB::table('users')->insertGetId(
['email' => 'john#example.com', 'votes' => 0]
);

You can use the Eloquent method Model::create() to return the object inserted, and obtain the object id, whatever his name is.
Try this:
$user = User::create(['email'=>'john#ecample.com','votes'=>0]);
$id = $user->custom_id;
This works if your User model is like:
class User extends Eloquent {
//This custom_id column needs to be of type serial in your table
protected $primaryKey = 'custom_id';
protected $fillable = ['email','votes'];
//...more code ...
}
I hope this works for you

Related

Why eloquent doesn't return error on diffrent primarykey?

I was working on an old database which primarykey is 'Id'. Eloquent set up the primary key to default 'id', so it is little change, but still can be confusing. Of course I didnt notice that, and I wanted to save updated models to database. There was no error, and $model->save() return was good but database didn't update. Furthermore I have other functions that get models from the database, and they work as they should without overriding $primarykey.
So here is my question: Why isn't eloquent returning any warnings or errors ? Of course I found in the documentation that I should override $primarykey in the model, and then everything worked perfectly.
I was using MySql 10.1.16-MariaDB.
Here is Laravel controller
public function update(Request $request, Order $order)
{
$order->fill($request->get('data'));
$order->save();
$order->products;
return $order;
}
Vue.js function
editOrder () {
this.fullscreenLoading = true
axios.put('/web/' + this.url + '/' + this.rowId, {'data': this.row})
.then(({data}) => {
this.row = data;
this.fullscreenLoading = false
});
},
Laravel Model was standard, of course my model is now properly updated, when i got this problem there was no $primarykey, I didnt mention $fillable and relationship to products but in my project they are defined and working.
class Order extends Model
{
use LogsActivity;
protected $table = 'orders';
protected $primaryKey = 'Id';
protected $fillable = []
}
If you execute the query with get(), create() or similar method, it will work as before because Eloquent doesn't use PK in this case. But some methods like find() will not work for you until you setup $primaryKey property in the model.
You didn't get an error because there was no error.
When you ran $order->save(), the query generated would have been something like:
update `orders` set `field1` = ?, `fieldN` = ?, `updated_at` = ? where `id` is null
This is a perfectly valid SQL statement, and when it runs, it would produce no errors. However, it will also not update any records (unless you do have a record where the id is null).
The reason why the update query is using null is because your Order model does not have an id attribute, it has an Id attribute, and PHP array keys are case-sensitive. So, when Laravel attempts to get the value for the id attribute, it returns null, and uses that in the query.

Laravel insert into database request()->all() and addition

In laravel if i want to insert all the form input and i want to add text in one of the column why cant i use this code?
Example
$B2 = new B2;
$B2::create([
request()->all(),
$B2->column9 = "aaaa",
]);
The inserted database only insert column9, the other column is Null.
Because create() accepts an array as the only parameter:
public static function create(array $attributes = [])
You can do this:
$data = request()->all();
$data['column9'] = 'aaaa';
B2::create($data);
When ever you use request all you must first make sure that you have either fillable fields in your model or guarded = to an empty array so for example:
class B2 extends Model
{
protected $table = 'db_table';
protected $fillable = [
'email',
'name',
];
}
or you can use
protected $guarded = [];
// PLEASE BE CAREFUL WHEN USING GUARDED AS A POSE TO FILLABLE AS IT OPENS YOU TO SECURITY ISSUES AND SHOULD ONLY REALLY BE USED IN TEST ENVIRONMENTS UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!
As for your create method you should make sure its an associative array like this:
$B2::create([
$B2->column9 => "aaaa",
]);
Or you could do something like:
$data = $request->except('_token');
$B2::create($data);
You'll have to merge the array.
$B2::create(array_merge(request()->all(), ['column9' => 'text']));
When you are adding to a database in that was it is called mass assignment. Laravel Automatically protects against this so you need to add the firld names to a fillable attribute in your model
protected $fillable = ['field1', 'column9'] //etc
https://laravel.com/docs/5.4/eloquent#mass-assignment
You also need to make sure you pass an array to the create method
$my_array = $request->all()
$my_array['column9'] = 'aaaa';
$B2::create(
$my_array
);

Laravel, how cast object to new Eloquent Model?

I get via Request a Json Object.
I clearly parse this object in order to check if it may fit the destination model.
Instead of assigning property by property. Is there a quick way to populate the model with the incoming object?
If you have an array of arrays, then you can use the hydrate() method to cast it to a collection of the specified model:
$records = json_decode($apiResult, true);
SomeModel::hydrate($records);
If you just have a single record, then you can just pass that array to the model’s constructor:
$model = new SomeModel($record);
Just pass your object casted to array as Model constructor argument
$model = new Model((array) $object);
Internally this uses fill() method, so you may first need to add incoming attributes to $fillable property or first create model and then use forceFill().
You should convert that object to array and use fill($attributes) method.
As method name says, it will fill object with provided values. Keep in mind that it will not persist to database, You have to fire save() method after that.
Or if You want to fill and persist in one method - there is create($attributes) which runs fill($attributes) and save() under the hood.
You can use Mass Assignment feature of Laravel,
You model would look like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'phone'];
}
And the process of populating the Model would be like this:
// This would be your received json data converted to array
// use 'json_decode($json, true)' to convert json data to array
$json_arr = [
'name' => 'User Name',
'email' => 'email#example.com',
'phone' => '9999999999'
];
$user = new \App\User($json_arr);
Hope this helps!
Castings may fail due to several reasons. A safe way is to add a static function to the model to generate from both array or object. feels like an extension to the model.
public static function generateFromObject($object)
{
$myModel = new MyModel();
foreach($object as $k => $v)
$myModel->{$k} = $v; //for arrays $myModel[$k] = $v;
return $myModel;
}
and you can use anywhere like,
$myModel = MyModel::generateFromObject($myObjectOrArray)->save();

laravel 5 model method not working

I have a table with rows with column contain string "this\dIs\dA\dString"
$callPlans = CustomerCallPlan::where('customer_id', $customer->id)->get();
I get the values like above and expected string 'thisXIsXAXString'
as you guess I replace '\d' with 'X'. to do this I use method below inside model class.
class CustomerCallPlan extends Model
{
protected $table = 'customer_callplan';
protected $fillable = [
'template',
'priority',
'customer_id',
'strip',
'add_number',
'actiontype',
'data'
];
public function getNumbertemplateAttribute() {
return str_replace('\d', 'X', $this->attributes['template']);
}
}
But somehow data comes to model without replaced.. what might be cause this ??
This is called an accessor and it'll automatically be called by Eloquent when attempting to retrieve the value. The method name should be the camel cased name of the column you wish to access, prepended by get and followed by Attribute, for example getColumnNameAttribute() will take the column colum_name.

Return Eloquent model with different name from database tables

I want to return a JSON of an Eloquent model, but I'd like to change the array keys. By default they are set as the table field names, but I want to change them.
For example if I have a users table with two fields : id and user_name
When I return User::all(); I'll have a JSON with "[{"id" => 1, "user_name" => "bob}] etc.
I'd like to be able to change user_name to username. I haven't found the way to do it without an ugly foreach loop on the model.
I'm not sure why you would want to do this in the first place and would warn you first about the structure if your app/would it be better to make things uniform throughout.. but if you really want to do it.. you could do:
$user = User::find($id);
return Response::json(array('id' => $user->id, 'username' => $user->user_name));
That will return a JSON object with what you want.
You can also change the name of the key with:
$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);
Just have a look at robclancy's presenter package, this ServiceProvider handles those things you want to achieve.
GITHUB LINK
Just set the $hidden static for you model to the keys you want to hide:
class User extends Eloquent
{
public static $hidden = 'id';
}
and name them the way you like with get and set functons.

Resources