Laravel alias column name in Eloquent model - laravel

How can I alias a column name in a model? I would like to show idUser instead of id in API responses. So far I've tried the following.
protected $maps = [
'id' => 'idUser',
];
protected $visible = [
'idUser'
];
protected $appends = [
'idUser'
];
This gives me an error:
'Call to undefined method App\User::getIdUserAttribute()'
Also, I would like to alias created_at and updated_at to createdAt and updatedAt.

you can define accessor method in your model like this :
public function getUserIdAttribute($)
{
return $this->id;
}
and then you have to add the attribute name in the $appends array
protected $appends = ['user_id'];
for more details checkout the docs
https://laravel.com/docs/5.8/eloquent-mutators

As #Namoshek's comment, you should be able to return a custom aliases for each column by renaming it.
First, look for which route you want to edit in folder routes/api.php. You can either use callback function or a Controller to manage the response.
// routes/api.php
Route::middleware('auth:api')->get('auth/retrieve-user', function(Request $request) {
$user = Auth::user();
return response()
->json([
'userId' => $user->id,
'createdAt' => $user->created_at,
'updatedAt' => $user->updated_at,
]);
});

Related

Laravel unique validation if ID isn't in request

I want to do some validation for a field. Right now works for unique values, the problem is that on Update I get the same error. So I want to filter the request, if that post request contain ID field then this field shouldn't be unique.
public function rules()
{
return [
'customer_id' => 'required|unique:customers',
];
}
You can use Rule class' unique method for the update method
public function rules()
{
return [
'customer_id' => [
'required',
Rule::unique('customers')->ignore($customer->customer_id),
];
}
Laravel docs: https://laravel.com/docs/8.x/validation#rule-unique
For common rules() function it can be done as
use Illuminate\Validation\Rule;
class CustomerController extends Controller
{
protected function rules($customer)
{
return [
'customer_id' => [
'required',
Rule::unique('customers')->ignore($customer->exists ? $customer->customer_id : null),
];
}
public function store(Request $request)
{
$customer = new Customer;
$request->validate($this->rules($customer));
}
public function update(Request $request, Customer $customer)
{
$request->validate($this->rules($customer);
}
}
In my case I have a single method for store/update and I check If I have an ID or not. Also I added $customer = request()->all(); and ignore($customer['ID'] , that is for my specific case.
Laravel Docs warns against passing user controller request input to the ignore method
For your specific case you can do
$customer = !empty($request->input('ID') ? Customer::findOrFail($request->input('ID')) : new Customer;
//Then pass the customer to the rules()
$validated = $request->validate($this->rules($customer));

How to create a data associatively? laravel eloquent

I have a Post model:
class Post extends Model
{
protected $fillable = [
'title',
'user_id',
'token',
'body'
];
public function favorites()
{
return $this->hasMany(Favorite::class);
}
public function addFavorite($state = 1)
{
$this->favorites()->create(compact('state'));
}
}
Favorite model:
class Favorite extends Model
{
protected $fillable = ['user_id', 'post_id', 'state'];
}
When I test in tinker:
$post = Post::first();
$post->addFavorite();
It returns me an error below:
Illuminate/Database/QueryException with message 'SQLSTATE[HYOOO]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into favorites...
Why it ask user_id when it is given in the post? Question is do I necessarily need to input the user_id to achieve this?
The question of whether user_id is necessary is up to you. Will it come in handy later on? Does having it on the posts table suffice?
It is asking for user_id because you do not have a default value field on that field in the favorites table. You can either set a default value, remove it from the table (if you decide you don't need it), OR provide it when creating via the relationship:
class Post extends Model
{
protected $fillable = [
'title',
'user_id',
'token',
'body'
];
public function addFavorite($state = 1)
{
$this->favorites()->create([
'state' => $state,
'user_id' => $this->user_id,
]);
}
public function removeFavorite()
{
$this->addFavorite(0);
}
}
Don't forget to include the relationship definition of favorites on the Post model.
Based on the plural name, it seems that a post has many favorites, but then your removeFavorite() method calls the addFavorite method?? This would not actually remove anything - it would create a new record.
Since Favorite model is related to Post model and you create it via relation()->create(), you can skip specifying post_id as Laravel can deduce it. But you do have to specify user_id, because there's no way for your code to know that favourite.user_id and post.user_id is the same. So in short: yes, you have to specify user_id.

Date field must cast to 'date' in Eloquent model

Hi I'm using laravel nova for create an admin panel. And I'm trying to use Date Field.
This is my migration,
$table->date('day')->nullable();
This is my my nova resource,
public function fields(Request $request)
{
return [
ID::make()->sortable(),
Date::make(__('Day'), 'day'),
];
}
This is my model,
class Menu extends Model
{
use HasTranslations;
public $translatable = ['name','description'];
protected $fillable = [
'name','description','typology', 'cost', 'day', 'active', 'buffet'
];
This is my error,
Date field must cast to 'date' in Eloquent model.
Do I need to do anything in resource ?
In your model class you just need to add the following lines which describe to laravel that you must cast the day field into a date object (Carbon):
//Casts of the model dates
protected $casts = [
'day' => 'date'
];
Check here someone has the same issue.
EDIT:
I have seen that your day column is set to nullable i think that your field Nova should be to like in this post :
public function fields(Request $request)
{
return [
ID::make()->sortable(),
Date::make(__('Day'), 'day')->nullable(),
];
}
And we need to change the model like this,
protected $casts = ['day' => 'date'];

Passing data from controller into Model in Laravel

I have this comment controller:
class CommentsController extends Controller
{
public function store(Article $article){
$comment = new Comment();
$comment->user_id = auth()->id();
$comment->comment = request('comment');
$comment->article_id = $article->id;
$comment->save();
return back();
}
}
And it works. I tried to make my code cleaner by putting that logic into my model. So I changed it like this:
class CommentsController extends Controller
{
public function store(Article $article){
$article->addComment(request('comment'));
return back();
}
}
Meanwhile, in my Comment Model I'm doing like this:
class Article extends Model
{
protected $fillable = ['title','content','user_id'];
public function comments(){
return $this->hasMany(Comment::class);
}
public function user(){
return $this->belongsTo(User::class);
}
public function addComment($comment){
Comment::create([
'comment' => $comment,
'article_id' => $this->id,
'user_id' => auth()->id()
]);
}
}
but when I do this, I'm getting this kind of error:
"SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into `comments` (`comment`, `article_id`, `updated_at`, `created_at`) values (Test comment bla bla bla..., 1, 2017-10-16 09:27:27, 2017-10-16 09:27:27)) ◀"
It seems I can't get the user_id in that manner, so how can I pass the user id so i can insert it into my comment tables? Thanks.
You need to add user_id to $fillable array in Comment model, not in Article model to make it work. Your original code works just because you do not use mass assignment there.
Try this:
public function addComment($comment){
Comment::create([
'comment' => $comment,
'article_id' => $this->id,
'user_id' => \Auth::user()->id
]);
}
try
\Auth::id()
instead of
auth()->id()
and go to your database and and make user_id default as NULL
The reason for this kind of error is that laravel protects database fields for mass assignment when you add the following code it makes all fields fillable.
protected $guarded = [];
Another way of doing is to add user_id in comments model. Is this case it will only allow the fields mentioned in the array to be mass assigned.
protected $fillable = [
'user_id'
];

Laravel Model create function returns column with null value

In Laravel, When I run the following query, it returns a row with null values.
//Cards.php
public function __construct(array $attributes = []) {
$this->gateway = StripeGateway;
}
protected $fillable = ['user_id', 'card_id', 'customer_id', 'exp_year', 'exp_month', 'funding', 'brand', 'last4'];
public function createNewCardFromCustomer($user_id, $customer)
{
$result = $this->create([
'user_id' => $user_id,
'customer_id' => $customer->id,
'card_id' => $customer['sources']['data'][0]->id,
'exp_year' => $customer['sources']['data'][0]->exp_year,
'exp_month' => $customer['sources']['data'][0]->exp_month,
'funding' => $customer['sources']['data'][0]->funding,
'brand' => $customer['sources']['data'][0]->brand,
'last4' => $customer['sources']['data'][0]->last4
]);
return $result;
}
Even the Model static create method receives the right parameters. And I've taken care of the mass assignment also.
I posted this on Laracasts too :)
Anyway, you have to change your constructor to this:
public function __construct(array $attributes = []) {
$this->gateway = StripeGateway;
parent::__construct($attributes);
}
You are overriding the Model's base constructor, which changes its default behavior. Laravel uses the constructor for a lot of things (create method, relationships, etc.).
The base model's constructor function does several things, but one very important part of it is that it accepts an array to fill out its attributes as can be seen here:
public function __construct(array $attributes = [])
{
$this->bootIfNotBooted();
$this->syncOriginal();
$this->fill($attributes);
}
So, after you set your gateway property, you should call the parent's constructor function and pass the attributes.

Resources