Yii2: get value of attribute that has a behavior - php

I'm using the TimestampBehaviour like this:
public function behaviors() {
return [
[
'class' => \yii\behaviors\TimestampBehavior::className(),
'createdAtAttribute' => 'usr_date_added',
'updatedAtAttribute' => 'usr_date_modified',
'value' => new \yii\db\Expression('UTC_TIMESTAMP()'),
],
];
}
Then if access it through the authenticated user like this...
Yii::$app->user->identity->usr_date_modified;
...I get the expression instead of the actual value:
object(yii\db\Expression)#38 (2) {
["expression"]=>
string(15) "UTC_TIMESTAMP()"
["params"]=>
array(0) {
}
}
If I do it like this I correctly get the actual value:
$user = app\models\User::findOne(51);
echo $user->usr_date_modified;
Why is that? And how can I get the actual value through the identity property?

The value while not saved in the database holds the information about how this actual value should be created - in your case it uses UTC_TIMESTAMP() MySQL function that will be called at the moment of saving this object into DB.
When you are retrieving object already saved in the database it takes whatever has been saved there (in your case the result of this MySQL function), so it gives you actual timestamp.
Before saving the object there is no point of checking this value.

I realized that I have modified an attribute and then called the save() method. You would think it should then hold the actual value after calling save() but it doesn't - I guess because doing the UPDATE query the database doesn't return the value. You need to call the refresh() method (see documentation) to make another SELECT query to get the new value. So you would need to do it like this:
Yii::$app->user->identity->usr_last_access = gmdate('Y-m-d H:i:s');
Yii::$app->user->identity->save();
Yii::$app->user->identity->refresh();

Related

Laravel get updated request value after merge

I am attempting to modify a Laravel Request object using merge to update the key trial_end.
I am doing this using the following code...
if ($this->request->get('trial_end', '')) {
$this->request->merge(array('trial_end' => 'test'));
}
dd($this->request->all(), $this->request->get('trial_end'));
I expect $this->request->get('trial_end') to be test, but it is not. $this->request->all() returns what I expected.
Result of die dump
array:1 [
"trial_end" => "test"
]
"12/4/2018"
How come it is not returning the updated value?
Figured it out. The solution was to change
$this->request->get('trial_end');
to
$this->request->input('trial_end');
This works because input() adds the data in all() to getInputSource()->all() before doing a data_get on that, whereas get() just performs a data_get on the input parameters (pre-modifications).
New code (with a change suggested by Alex)
if ($this->request->has('trial_end')) {
$this->request->merge(['trial_end' => 'test']);
}
dd($this->request->all(), $this->request->input('trial_end'));
New results
array:1 [
"trial_end" => "test"
]
"test"
Hope this helps any others that come across this issue.
the problem it's not with the assignment, but with the comparison, here's my personally best way to check if a value in the request has been set.
public function test(Request $request){
if (!$request->has('trial_end')) { //this is what you have wrong
$request->merge(array('trial_end' => 'test'));
}
return $request->get('trial_end');
}
greetings

Is there a way to check if a couple of inputs are unique in laravel 5.2?

update
What I have is a table with these columns:
- ID
- production_year
- type
If the type is already present in the table with the value the user wants to pass, check if production_year is already present too, but fail the validation ONLY if these values are present in the same record. Otherwise let the user to store this record.
I'm trying to check the uniqueness of a couple of fields in the same record...
I've seen the documentation about the conditional validation, but I didn't quite find the answer there.
the code
public function rules()
{
return [
// I'd like to check the uniqueness of both of them. In the same record
'production_y' => 'required|unique',
'fk_type' => 'required|unique',
];
}
Any idea? Thanks!
Laravel 5.3 Update:
Now, you can generate the same rule fluently using the Rule (\Illuminate\Validation\Rule) class.
NULL,id part of the string way is no more required. See:
public function rules()
{
$type = $this->get('fk_type');
return [
'production_y' => [
'required',
Rule::unique('your_table', 'production_year')->where(function($query) {
$query->where('type', $type);
}),
],
];
}
Original Answer
Can't test right now, can you try:
public function rules()
{
$type = $this->get('fk_type');
return [
'production_y' => "required|unique:your_table,production_year,NULL,id,type,{$type}",
// ...
];
}
Explaination:
unique:your_table Set the table for the unique check.
,production_year This matches with production_y.
,NULL,id check all the records.
3.1. if you use like {$id},id it will check uniqueness except the record with the {$id},
,type,{$type} and the type should be {$type}
That will produce sth. like (not exact query, just to express the idea):
select count(*) from your_table where production_year = $product_y and where type = $type and where id <> null
if someone cames from laravel 8, i tried this and it worked !!
for me i need to check the uniqueness of (category_id,subcategory_id) which mean you can find (1,2),(1,3),(2,1),(2,3) but you cant find similar couple !!
'category' => "required|unique:tickets,category_id,NULL,id,subcategory_id,{$request->input('subcategory')}"

Update collection erases all information inside

I am new to MongoDB and trying to perform my first updates.
I have my users collection that is populated by an insert statement. Now, I want to add or insert the field authCode with some data into a specific user.
My problem is that when I perform the following function the whole user data becomes replaced by the information in that update statement. My understanding is that by using upsert I would insert or update a users collection. given that the user already exist I expect just the authCode field to be created or updated.
Could anyone point out what am i doing wrong?
public function addAuthCode( array $userId, $code ) {
$user = $this->db()->user;
$user->update(
$userId,
array( 'authCode' => $code ),
array( 'upsert' => true, 'safe' => true )
);
}
You'll want to take a look at the MongoDB documentation for updates found here: http://docs.mongodb.org/manual/reference/method/db.collection.update/#db.collection.update
Specifically:
Add New Fields
db.bios.update(
{ _id: 3 },
{ $set: {
mbranch: "Navy",
"name.aka": "Amazing Grace"
}
}
)
Notice that in order to add a field, you need to use the $set operator
Chris#MongoLab

NULL appended to array passed to function

I'm getting an odd error when attemping to pass an array to a function which updates data in a MySQL table.
My trigger
$input_data = array(
'field0' => 'abc',
'field1' => '123'
);
// var dump #1
var_dump($input_data);
// gives expected result (2 element array)
$this->user->update_user_info($input_data);
User model
function update_user_info($new_data) {
// var dump #2
var_dump($new_data);
// this gives:
// array(2) {
// ["field0"] => string(3) "abc"
// ["field1"]=> string(3) "123"
// }
// NULL
}
Where is that ending NULL coming from?? I am trying to use this with Codeigniter's active Record Update class and it fails because of that NULL.
I've attempted to copy it to a new array by looping through a foreach, but the NULL value follows to the new array, even though it doesn't appear to be in the array.
Any help would be appreciated.
Apologies for the above 'Answer', I'm new to the site and couldn't see the comment button :p
I've since solved this problem in terms of my own circumstances and possibly this may apply to you.
As I said earlier my problem was identical, the cause was not correctly returning both functions - I returned the secondary function i.e the one that my array was passed to like so.
function update_user_info($new_data) {
// var dump #2
var_dump($new_data);
return;
}
but in the first function I was not returning after calling the second function, hope that makes sense and that this helps you too, it was frustrating as hell for me!
The NULL is obviously not in the array; It is printed on a second call to update_user_info() function. You should try to find out why the update_user_info() function is called twice.

does sfWidgetFormSelect provide a string or an int of the selected item?

I'm having an annoying problem. I'm trying to find out what fields of a form were changed, and then insert that into a table. I managed to var_dump in doUpdateObjectas shown in the following
public function doUpdateObject($values)
{
parent::doUpdateObject($values);
var_dump($this->getObject()->getModified(false));
var_dump($this->getObject()->getModified(true));
}
And it seems like $this->getObject()->getModified seems to work in giving me both before and after values by setting it to either true or false.
The problem that I'm facing right now is that, some how, sfWidgetFormSelect seems to be saving one of my fields as a string. before saving, that exact same field was an int. (I got this idea by var_dump both before and after).
Here is what the results on both var dumps showed:
array(1) {["annoying_field"]=> int(3)} array(1) {["annoying_field"]=>string(1)"3"}
This seems to cause doctrine to think that this is a modification and thus gives a false positive.
In my base form, I have
under $this->getWidgets()
'annoying_field' => new sfWidgetFormInputText(),
under $this->setValidators
'annoying_field' => new sfValidatorInteger(array('required' => false)),
and lastly in my configured Form.class.php I have reconfigured the file as such:
$this->widgetSchema['annoying_field'] = new sfWidgetFormSelect(array('choices' => $statuses));
statuses is an array containing values like {""a", "b", "c", "d"}
and I just want the index of the status to be stored in the database.
And also how can I insert the changes into another database table? let's say my Log table?
Any ideas and advice as to why this is happen is appreciated, I've been trying to figure it out and browsing google for various keywords with no avail.
Thanks!
Edit:
ok so I created another field, integer in my schema just for testing.
I created an entry, saved it, and edited it.
this time the same thing happened!
first if you what the status_id to be saved in the database, you should define your status array like this:
{1 => "a", 2 => "b", 3 => "c", 4 => "d"}
So that way he know that 1 should be rendered like "a" and so on. Then, when saving, only the index should be saved.
About saving in another database, my advise is to modify the doSave method defined by the Form class yo match your needs. I only know how Propel deals with it, maybe this could help:
the doSave method dose something like this:
protected function doSave($con = null)
{
if (null === $con)
{
$con = $this->getConnection();
}
$old = $this->getObject()->getModifiedValues($this);//Define this
$new_object = new Log($old);//Create a new log entry
$new_object->save($con));//save it!
$this->updateObject();
$this->getObject()->save($con);
// embedded forms
$this->saveEmbeddedForms($con);
}
Hope this helps!
Edit:
This is an example extracted from a model in one of my applications and its working ok:
Schema:
[...]
funding_source_id:
type: integer
required: true
[...]
Form:
$this->setWidget('funding_source_id', new sfWidgetFormChoice(array(
'choices' => array(1 => 'asdads', 2 => '123123123' , 3 => 'asd23qsdf'),
)));
$this->setValidator('funding_source_id', new sfValidatorChoice(array(
'choices' => array(1 => 'asdads', 2 => '123123123' , 3 => 'asd23qsdf'),
'required' => true
)));
About the log thing, that could be quite more complex, you should read the current implementation of the doSave method in the base form class, currently sfFomrObject on Symfony1.4., and when and how it delegates object dealing with modified values.
Okay,
It turns out I forgot to do a custom validator to use the array key instead.

Categories