My entity looks like this:
class Request extends Entity
{
protected $casts = [
'id' => 'integer',
'added_at' => 'datetime',
'deadline' => 'datetime',
'completed' => 'integer'
];
}
When saving, the model generates the date fields in 'Y/m/d' format for the sql query, hovewer my database can not parse this. How can I force it to generate dates in 'Y-m-d' format when calling $myModel->insert($myEntity) ?
Entities has the option of setters. It performs the validation or conversion in your case whenever you perform save an entity. Lets say you want to change the form of deadline in that case you have to set the Setter for your deadline as follow :
public function setDeadline(string $dateString)
{
$this->attributes['deadline'] = $dateString;
return $this;
}
In the following line : $this->attributes['deadline'] = $dateString; You will use some library like Carbon to format the $dateString and then reassign your variable deadline. Reference link :
https://codeigniter4.github.io/userguide/models/entities.html
Related
I have a table with unique column, it consists of 8 characters of random English letters and numbers.
I need to be able to seed the table by adding more data to the existing data.
I am supposed to enter a given amount of rows.
I tried using Factories and Seeders but then realized it's not working as expected:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Code extends Model
{
protected $table = 'codes';
}
protected $fillable = [
'code',
'is_valid'
];
Factory:
public function definition()
{
return [
'code' => $this->faker->regexify('[A-Z0-9]{8}')
];
}
Then I am supposed to add data by running:
$codes = Code::factory()->count(10000)->create();
and after that, if I run it multiple times I might end up with constraint violation:
// add some more data
$codes = Code::factory()->count(10000)->create();
$codes = Code::factory()->count(10000)->create();
What is an efficient way to be able to add given amount of rows and make sure they're unique?
All other questions I've seen here are similar, but not working for my case.
Change in your factory definition this line from this: 'code' => $this->faker->regexify('[A-Z0-9]{8}') to: $faker->unique()->regexify('[A-Z0-9]{8}');.
In your factory you can use the unique() faker modifier : https://fakerphp.github.io/#modifiers
public function definition()
{
return [
'code' => $this->faker->unique()->regexify('[A-Z0-9]{8}')
];
}
Edit: when running the factory with existing data, you can check if the faked data already exists in the database like:
public function definition()
{
do {
$fakeCode = $this->faker->unique()->regexify('[A-Z0-9]{8}');
} while (DB::table('codes')->where('code', $fakeCode)->exists());
return [
'code' => $fakeCode
];
}
I am saving an array in one column of my database using json_encode as follows and it works:
$service->description = $request->service_description;
$service->image = json_encode($url);
$service->duration = $request->service_delivery_time;
When I fetch the data I get a string. I am fetching using $service = Service::findOrFail($id);. I can decode the individual column as done below and pass it to the view.
$service = Service::findOrFail($id);
$images = json_decode($service->image);
return view('services.show',['service'=>$service , 'images'=>$images]);
What I am asking is, can I decode the images in one query?
Well this is a single query, json_decode runs after the SQL query returned your desired result.
What you can do is add a $casts property to your Service model so Laravel encodes/decodes it automatically for you, then you don't need to store these values with json_encode, just do $service->image = $url, and when you run findOrFail, the image property will already be a decoded json.
protected $casts = [
'image' => 'array',
];
Here's the documentation
You can use $cast or Accessor
1: $cast:
protected $casts = [
'image' => 'array'];
2: Accessor:
public function getImageAttribute()
{
return json_decode($this->attributes['image']);
}
How do I can select data to show based on comparation in yii2 Activerecord? My data record from db contain column depTime. So I want to show only data that has depTime less than current time.
Here is my function in my controller.
public function actionSelectedTeam($id) {
$searchModel = new TeamSearch();
$dataProvider= $searchModel->search(Yii::$app->request->queryParams);
$dataProvider->pagination = [
'pageSize' => 5
];
return $this->render('team-info', [
'model' => $this->findModel($id),
'dataProvider' => $dataProvider,
]);
}
Or there is another way to do that? I mean outside this method, maybe from the model.
Thankyou.
You will always have the records displayed that are smaller than the current time, other than they are some kind of reservations and you are providing future date/time manually.
You haven't specified what is the type of the depTime column, I assume that you have a datetime column, you can use the time() and now() function to achieve this.
You can add the following line in your search model's search() method before you return the $dataProvider which is subtracting the depTime from the current time and if the result is positive it will include the record.
$query->andFilterWhere(['>', new Expression('time(now()) - time(depTime)'), 0]);
In my database some fields are set as date, while others are datetime or timestamp formats. However when fetching data, the "date" fields are also shown with the 00:00:00 time string attached at the end. How can I prevent this?
You can use date/datetime casting with an additional format parameter as described in the Eloquent: Mutators documentation.
class User extends Model
{
protected $casts = [
'created_at' => 'datetime:Y-m-d',
];
}
This will apply the given format when serializing the model to an array or json. If you want to use a different format in your blade templates, you can use the format() function on the datetime property you want to change:
{{ $user->created_at->format('Y-m-d') }} or {{ $user->created_at->toDateString() }}
You will have to add the created_at column to the $dates property of your model though:
protected $dates = [
'created_at',
];
This basically adds 'created_at' => 'datetime' to your $casts.
I am storing a model in my session. I am using column maps in my model so that if the column name changes in the database I don't have to make changes throughout my application. So if 'firstName' changed to 'first' in the database i could keep referencing 'firstName' throughout the application. In my testing I have found that unless the column map key and value are equal the property will always be stored as null in the session.
This will work:
/**
* Independent Column Mapping.
*
* Keys reference property in database
* Values reference property application-wide
*/
// db column name = 'firstName'
public static function columnMap()
{
return
[
'firstName' => 'firstName'
];
}
This will work:
// db column name = 'first'
public static function columnMap()
{
return
[
'first' => 'first'
];
}
This will fail:
// db column name = 'first'
public static function columnMap()
{
return
[
'first' => 'firstName'
];
}
I don't foresee changing database column names, nor do I like the inconsistency of referencing a property by a different name in the database and in the application. However, I would like to remain flexible and make sure this works in case I run into a scenario where I need this change.
Does anyone know why the session clobbers the property value when the column map key-value pair differs?
Why are you saving the object in session? This will consume a lot of memory. It's better to save only an array. And it will save the new mapped name.
$user = User::findFirstFromId(1000);
$this->session->set('user') = $user->toArray();