I inherited a project that was created with Yii2, ver. 2.0.4, with the task to update said project to a more current version of Yii2 (2.0.15) because of the incompatibility of the older one with PHP 7.2+.
I noticed that there is a lot of use of assigning arrays to a model:
$model->_attributes = $array;
With the new version this results in an exception
'yii\base\UnknownPropertyException' with message 'Setting unknown property: app\models\model::_attributes'
For the time being I created a workaround with the following function:
function customSetAttributes(&$model, $array) {
foreach($model->attributeLabels() as $model_key => $model_label) {
if(!isset($array[$model_key])) continue;
$model->$model_key = $array[$model_key];
}
}
Also, the getter function now has a similar issue.
What I would like to know:
Was this type of assignment never intended in the first place (and I just haven't found the previous developer's code that enables it)? I skimmed over the Yii2 changelog but didn't notice anything related.
Is there a way to "salvage" the previous behaviour so I don't have to replace each occurence with my workaround function?
ActiveRecord::$_attributes was always private and never should be used in this way. I guess that previous developer edited framework core files in vendor directory and make this property protected/public.
You may try to emulate this behavior by creating virtual attribute using getter and setter:
public function get_attributes() {
return $this->getAttributes();
}
public function set_attributes($values) {
$this->setAttributes($values, false);
}
But this will not always work and it is more like an ugly hack to make crappy code work. I strongly suggest to fix code to use setAttributes() instead of _attributes.
Also you should compare yii2 package from vendor directory with source from https://github.com/yiisoft/yii2-framework/releases/tag/2.0.4 - you may find more places where core was edited.
Related
I'm trying to implement a new method in a BoController called "deleteBooking", the method is defined:
public function deleteBooking($id){
$booking = Reservation::find($id);
if($booking && $booking->delete()){
try {
$email = Mail::to($booking->user_email)->send(new Cancel($booking));
} catch(\Exception $e){
Log::error($e->getMessage());
}
return redirect('admin/manager/home')->with('message','Réservation annulée!');
}
return redirect('admin/manager/home')->with('message','Réservation non annulée!');
}
But laravel at the endpoint says:
(1/1) BadMethodCallException
Method [deleteBooking] does not exist.
Other methods from the same class are linked to endpoints too, and work well.
Do you have any ideas please? Thank you.
I got it fixed, I've found another file called BoController, in another folder somehow and it was conflicting with the App\Http\Controllers one.
Thank you.
It's most likely that you have declared that function for some other request type other than the one you're trying to make. For example you put Route::post('some-method', 'BoController#deleteBooking'); but you need to put either Route::get(...) or Route::put(...) or Route::delete(...).
If it isn't that problem, then you probably misspelled it.
I have faced similar issue. Then I have figured out a issue pointed in composer install log, with following instance of log line:
Class App\Http\Controllers\BlogController located in ./app/Http/Controllers/BlogControllerOld.php does not comply with psr-4 autoloading standard. Skipping.
Based on that I have found that one of the file renamed with Old suffix was creating conflict with the main file. So here I have to chhoseone of the following solutions:
To delete the file created for backup.
Or just rename the class in duplicated file to BlogControllerOld.
So its a good idea to check for issues with composer install
It will highlight the conflicts that can be fixed using one of the method above.
Once fixed using specified methods above issue composer install to apply the fix and regenerate autoloader.
My website is with a hosting provider that has the MessageFormatter class available on the server (Linux, PHP 7.0.27) but it is an old ICU version (4.2.1) that doesn't support my message {number,plural,=0{# available} =1{# available} other{# available}} and gives the error:
Message pattern is invalid: Constructor failed
msgfmt_create: message formatter creation failed: U_ILLEGAL_CHARACTER
...because of the =1 and =2 notation.
I'm not able to make changes to the server so how can I force using the fallback method provided by Yii2 which works just fine?
There is this hacky way you can try.
Copy the yii\i18n\MessageFormatter code to a new file. Name it MessageFormatter.php and place somewhere in your application (but not in vendor folder).
In this new file change the format() method to:
public function format($pattern, $params, $language)
{
$this->_errorCode = 0;
$this->_errorMessage = '';
if ($params === []) {
return $pattern;
}
return $this->fallbackFormat($pattern, $params, $language);
}
Don't change anything else (including namespace).
Now let's use Yii mapping.
Find a place in your application when you can put code that will be run every time in bootstrapping phase. Good place for this is common/config/bootstrap.php if you are using "Advanced Template"-like project.
Add there this line:
Yii::$classMap['yii\i18n\MessageFormatter'] = 'path/to/your/MessageFormatter.php';
Obviously change the path to the one you've chosen. Now Yii autoloader will load this class from your file instead of the original Yii vendor folder (as mentioned in Class Autoloading section of the Guide).
In the modified file MessageFormatter method presence of intl library is never checked so fallback is used as default.
The downside of this trick is that you need to update manually your file every time original Yii file is changed (so almost every time you upgrade Yii version).
Another approach is to configure I18N component in your application to use your custom MessageFormatter where you can extend the original file and just override format() method inside without modifying class map.
Since 1.22.0 version of Twig, method Twig_Environment::clearCacheFiles() is deprecated. However, I didn't found anywhere (nor in documentation, nor in repo tickets, nor here on SO) something which can replace this deprecated method.
So what is the idiomatic (and not deprecated) way to clear all cache files now?
Clearing those files via implementing own function seems to be pretty weird.
So there is no new idiomatic way to clear all cache files.
Twig project maintainers leave it for library users on their own. The arguments are:
The argument was that Twig itself will only support filesystem cache (due to opcache). Thus clear() would be the same as removing the cache folder manually. Thus it doesn't need to be in the interface. So you have to clear your cache either manually or write the method yourself.
More details may be read in relevant issue early referred by #alain-tiemblo in comments.
Here is the deprecated method from Twig made into a generalized function if you are interested. It only removes leaf nodes (the php files that Twig generates) but leaves the directories. You will want to make sure you pass in the correct path.
function clearCacheFiles($cacheLocation) {
if (is_string($cacheLocation)) {
foreach (new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($cacheLocation),
\RecursiveIteratorIterator::LEAVES_ONLY) as $file
) {
if ($file->isFile()) {
#unlink($file->getPathname());
}
}
}
}
From Twig/lib/Twig/Environment.php as it appeared when first marked deprecated.
got this error on Yii2. I dont know what exactly the problem is. I just migrate my source code from Windows to Mac OS. I tried cloning my whole project still the error appears.
Declaration of common\models\Product::getAttributes() should be compatible with yii\base\Model::getAttributes($names = NULL, $except = Array)
These are the things i tried:
Clone the whole project to Mac OS. - error above exists.
Clone the whole project to another windows machine.-the project is running well.
I am using yii2 in this project.
As you can see from the error message, you overrided yii\base\Model getAttributes() method. common\models\Product is extended from yii\db\ActiveRecord and ActiveRecord is extended from yii\base\Model.
If you really want to override this method, list all parameters (see here), it's easier to do with help of IDE. And by the way this is PHP feature and has nothing to do with OS or Yii2.
If it is your custom method for another purposes, you need to rename it in order to resolve conflict.
Your method must accept the same parameters ($names = NULL, $except = Array)
I have been recently playing around with HHVM. Went through a lot of trouble getting it to work on my computer. I know that not all PHP functions are available. As a test, I am writing a new website using it instead of using my current code. I ran into a problem when trying to use
filter_var($var,FILTER_SANITIZE_URL);
From the error.log file, it turns out that this function is undefined. Is the filter_var function not available for use in HHVM or am I just doing something wrong here. I like to keep things DRY, this would mean I have to do a lot more validation than I expected.
filter_var is now implemented in hhvm. Open github issues if you have any problems with it.
This function appears to not have been implemented on HHVM See http://comments.gmane.org/gmane.science.linguistics.wikipedia.technical/70038
An option if you want to rely on this functionality with the hopes that it will enter the fold is to polyfill it in (partial implementation to inspire the motivated).
if (!function_exists("filter_var")){
// define the constants used by the function
define("FILTER_VALIDATE_EMAIL", "email");
function filter_var(){
$args = func_get_args();
// $args[1] is the filter type (second parameter)
switch ($args[1]){
case FILTER_VALIDATE_EMAIL:
if (preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/", $args[0])?$args[0]:false;
break;
}
}
}