Upgrading to 3.2 (from 3.0.x)

Hello everyone,

we want to upgrade our Phalcon version from 3.0.2 to 3.2.

We are checking the Changelog: https://github.com/phalcon/cphalcon/blob/master/CHANGELOG.md

Changed fields evaluation

With the new version, getChangedFields() and hasChanged() perform the control by comparison of the type and value of the variable, unlike before, when control was performed only by value.

With 3.2, we are experiencing errors on these evaluations. The errors are detected for the evaluation of boolean fields (which, in the database, are TINYINT fields with a value of 0 or 1) and numeric fields (INT, DECIMAL, etc.).

We tried two alternative ways to adapt our applications in order to properly handle this new behaviour. The two alternatives are based on the use of these two PDO connection options:

$config['options'] = [
    \Pdo::ATTR_EMULATE_PREPARES     => false,
    \Pdo::ATTR_STRINGIFY_FETCHES    => false,
];
  1. Without using the options

    • getSnapshotData() always returns all values cast as string (or NULL, of course). So, if we force all Models to always return all string values, we do not have any problem

    • However this would not be the best solution

  2. Using the options

    • Doing so, we should intervene on all of our Models by modifying the getters and the setters so they always return and set the data casting to the correct type based on the field in the database

    • We also realized that using these options causes some unexpected behaviour with PDO prepared statements. It appears that using the same named parameter as a multiple placeholder in the same query causes an error; we also found this StackOverflow thread: https://stackoverflow.com/questions/7603896/php-pdo-prepare-repetitive-variables

    • Are there other implications that we should take into account and which we have not yet noticed, using these two new options?

What should we do to upgrade our application? Do you have any suggestion? Is there anything else we should try to do?

Snapshots and refresh

In order to have some snapshot data on creates, we used to invoke setSnapshotData().

Reading the Changelog it seems that with 3.2 all Models will always have a Snapshot ready to be used after any save() (on both updates and creates): is that right? So we should delete all setSnapshotData() used before (when we used it to have snapshots on create)?

Another issue that we experienced before 3.2 was the need to make a refresh() in order to clean the snapshot. However from 3.2 it appears to be an automatic action always performed by the save().

Is that right? Should we delete all our refresh() invocations (when we invoke the method after a save() to refresh the snapshot)?

Model assign() method

We are using assign() on various occasions to speed up new Model instances creation. With 3.2 we noticed that if a Model doesn't have a setter for one or more of its properties, assign() throws an Exception. However, we need some of our models to not make some setters available.

On the Changelog we noticed that there's a new method setup() that appears to have exactly the same behaviour of the previous assign() where no exceptions were thrown if a setter was missing, thus only using properties names.

Is that right? Should we use setup() instead of assign() when we're working with a Model in which some setter methods are missing?

Thank you very much for your attention and precious help.

Have a nice day!

That's interesting with this exception on assign. Change was only supposed to make it possible to speed up assign method because it was always using setters even it wasn't needed. About snapshot and refresh - yea you can remove it, though keep in mind that fields which are having default value in database will not get updated - I created issue beacause this'll need some discussion what to do with those.



3.8k

That's interesting with this exception on assign. Change was only supposed to make it possible to speed up assign method because it was always using setters even it wasn't needed. About snapshot and refresh - yea you can remove it, though keep in mind that fields which are having default value in database will not get updated - I created issue beacause this'll need some discussion what to do with those.

Thank you very much. We will test which method is the best one, to remove or not to remove the refresh(). Can you provide the link to the issue you opened, please?

What about the getChangedFields() "issue"? Do you have any suggestion?

Thank you

edited Jul '17

Which issue? It was always using type and value i think, don't know about this change.

https://github.com/phalcon/cphalcon/issues/12745 here is issue, if you have any idea how to solve it then great



3.8k
edited Jul '17

Which issue? It was always using type and value i think, don't know about this change.

Wrong. We are using Phalcon 3.0.3 now. Let me explain with an example.

A Model which is keeping Snapshot has a field called Active of type TINYINT(1). Other fields inside the Model are all VARCHAR.

At the moment, record with id = 100 has Active = 1. The user doesn't change any field and saves the record, also leaving Active = 1.

Inside beforeUpdate() we have a procedure that checks if some fields have changed their value using getChangedFields().

With 3.0.3 getChangedFields() returns an empty array.

With 3.2.0 getChangedFields() returns [ Active ] (because the Model retreives the value as int but when we instantiate the Model we set the values as string.

This is the problem.

Any idea why?

edited Jul '17

Just send/set it as a int then? It was a bug that it wasn't checking type, now it's fixed.



3.8k

Just send/set it as a int then? It was a bug that it wasn't checking type, now it's fixed.

Ok. So we can take all our 234 Models and cast all values inside all setters and getters. At least on numeric type fields.

Do you think that this will solve the problem definitively?

Thank you