Using Respect/Validation in another language - php

I want to use the Respect/Validation library in PHP. I know how to use it but currently I'm using it in a project in German language and of course, I also want the error messages in German.
For language translation, there is a section in the documentation but I don't really get it and I did not found any answer yet.
They're talking about a translator that should handle the translation of the messages. As a second parameter they're giving "gettext" but I don't know what this should be and how this should handle the translation.
Can anybody explain me how this works?

Respect/Validation won't do the translation for you, you should use a different project, library or function to do that. It won't leave you empty handed though, as the documentation states.
First, you should try to understand how translation libraries work (such as gettext()) and then read PHP documentation on Callables. Then it is a matter of choosing a library, creating the translations and calling setParam('translator', 'callable') method on the exception instance.
A quick introduction to your problem:
Translations are done based on a source: it can be a file, a database or something else, depending on which library you use.
Respect/Validation exception messages use the same pattern: {{name}} is invalid.. Where {{name}} will be replaced by the input given or the name if setName() was called on that rule.
You can see all messages you need to translate under the Respect\Validation\Exceptions namespace.
Usually, every library provide a single function/method to translate a given string. This is the method/function you want to set on the $exception->setParam() call.
If you ever translate all exception messages, we would love to make them available to everyone else.
PS: You could also make this question on the repository page, more people would help and we could also improve the way translations are handled by the library in the future.

I just changed all Exception defaultTemplates property, it works for me.
class Localization
{
public function init()
{
$this->validation();
}
public function validation()
{
$prefix = '\\Respect\\Validation\\Exceptions\\';
$localize = [
'EmailException' => 'local message',
'NotEmptyException' => 'local message'
];
foreach($localize as $class => $message) {
($prefix.$class)::$defaultTemplates[
ValidationException::MODE_DEFAULT][ValidationException::STANDARD] = $message;
}
}
}
$localization = new Localization();
$localization->init();

Related

Yii2 $model->_attributes assignment does not work in new version

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.

PHP 7 "declaration..should be compatible" for argument types

I'm using a framework which has method defined something like
class Abc {
public function doThis($what) {
...
}
}
Since I'm using PHP 7 and also fan of PHP codesniffer, it tells me to define function argument types, that said I have wrote class in my code:-
class Pqr extends Abc {
public function doThis(string $what) {
...
}
}
This code gives me warning Declaration of Pqr::doThis(string $what) should be compatible with Abc::doThis($what)
It seems PHP is treating $what in Abc class differently (not as string). Since Abc is part of framework and I cannot do anything about it. I do not want to remove argument types in my code and want to keep cngode more strict. Disabling all warnings would be bad idea.
Anything better we have to fix this issue ?
Code Sniffer may well be telling you to do something, and you may want to follow its advice, but if your framework isn't doing it then you may not be able to do it either. You can't dicatate the code rules to the framework; you have to live with what it imposes on you, even if that goes against Code Sniffer's rules.
My advice is to simply ignore this issue. Code Sniffer is a great tool, and its advice is worth following, but there are times when you simply can't do so.
If your goal is to get your system to show zero Code Sniffer warnings, then you can do so by explicitly adding markers to your code telling Code Sniffer to ignore specific rules at various points in your code. Code Sniffer has the ability to ignore sections of code; this is described in it's Advanced Usage documentation page.

JS Lexer to detect function calls

In order to localize strings used within my javascript, I want scan all my js files for such strings.
I am using a t() function to request string translations as follows:
t("Hello world");
or with dynamic portions:
t("Hello #user", {"#user": "d_inevitable"});
I want to detect all calls to the t() function and thus gather the strings contained in the first argument in a php "build" script, but skipping the following:
function foo(t) {
t("This is not the real t, do not localize this!");
}
function bar() {
var t = function(){}; //not the real t either...
}
function zoo() {
function t() {
//This also isn't the real t() function.
}
}
t("Translate this string, because this is the real t() in its global scope");
So the simple rule here is that the t function being invokes must be in global scope in order for the first argument to qualify as a translation string.
As a rule, dynamic runtime data as first argument is not allowed. The first argument to t() must always be a "constant" literal string.
I think php codesniffer will help me do it, however all the documentation I could find on it is about enforcing code standard (or detecting violations of it). I need lower level access to its js lexer.
My question is:
Would the php codesniffer's js lexer be able to help me solve my problem?
If so how do I access that lexer?
Are there any other php libs that could help me find the calls to t()?
Please do not suggest stand-alone regular expressions as they cannot possibly solve my problem in full.
Thank you in advance.
What you are describing is basically a coding standard. Certainly, ensuring strings are localised correctly is part of many project standards. So I think PHPCS is the right tool for you, but you will need to write a custom sniff for it because nothing exists to do exactly what you are after.
The best thing to do is probably clone the PHPCS Git repo from Github and then create a new directory under CodeSniffer/Standards to contain your custom sniff. Let's say you call it MyStandard. Make sure you create a Sniffs directory under it and then a subdirectory to house your new sniff. Take a look at the other standards in there to see how they work. You'll also find it easier to copy an existing ruleset.xml file from another standard and just change the cotent to suit you. if you don't want to include any other sniffs from anywhere (you just want to run this one check over your code) then you can just specify a name and description and leave the rest blank.
There is a basic tutorial that covers that.
Inside your sniff, you'll obviously want it to check JS files only, so make sure you specify that in the supportedTokenizers member var (also in the docs). This will ensure PHP and CSS files are always ignored.
When you get down to the actual checking, you'll have full low-level access to the parsed and tokenised content of your file. There are a lot of helper functions to check things like if the code inside other scopes, or to help you move backwards and forwards through the stack looking for bits of code you need.
TIP: run PHPCS using the -v option to see the token output on your file. It should help you see the structure more easily.
If you want to really do things properly, you can even create a nice unit test for your sniff to make sure it keeps running over time.
After all this, you'd check your code like this:
phpcs --standard=MyStandard /path/to/code
And you can use a lot of integrations that exist for PHPCS inside code editors.
You might decide to add a new more sniffs to the standard to check other things, which you can then do easily using your ruleset.xml file or by writing more custom sniff classes.
I hope that helps a bit. If you do decide to write your own sniff and need help, just let me know.

How do you define Exception?

I'm used to Zend Framework, when you write your own component, you make it's own Exception file, but on per file basis, then you have such structure:
Zend/View/Exception.php
Zend/View/Helper/Exception.php
Zend/View/Renderer/Exception.php
etc.
I'm ok with, I also use Doctrine2 and Exception are "stored" in a different way
something like (in a Zend way)
and in Zend/View/Exception.php
class Exception {
public static function invalidArguement() {
return new self('Invalid arguement was given, etc..');
}
I understand that the second approach is less flexible but more accurate because it throws exception according the error.
The first approach is just a way to be able to throw a Zend_View_Exception with a custom messagE.
Also, what about one Exception file per, Exception.
Like the following structure :
Exception/InvalidArguement.php
Exception/AuthentificationFailed.php
Exception/QuantityLimit.php
Is there any best practices? Any pros/cons?
For me the best practice is to group exceptions related to their issue.
For example if you have a number of Auth exceptions, like InvalidDetails, UserNotFound put them here
Library/Auth/Exceptions/InvalidDetails.php
Library/Auth/Exceptions/UserNotFound.php
Each exception should be an extension of Zend_Exception ( unless you've extended it yourself )
this way you can do:
throw new Library_Auth_Exception_InvalidDetails("Invalid details when trying to login");
the benefit of using this method is you DONT need to have a message, the Exception name can cover it enough.
My assumptions here is you setup a namespace for Library called Library and everything is within there.
I tend to group everything, so a typical Auth library could be:
Auth/Forms/Login.php
Auth/Exception/InvalidUser.php
Auth/Orm/Abstract.php
Auth/Orm/Doctrine.php
HTH
I've never worked with Zend framework but if this at all helps, I would at least make a common Exception class and all those other ones extend that rather than just make one for each.

How to design error reporting in PHP

How should I write error reporting modules in PHP?
Say, I want to write a function in PHP: 'bool isDuplicateEmail($email)'.
In that function, I want to check if the $email is already present in the database.
It will return 'true', if exists. Else 'false'.
Now, the query execution can also fail, In that time I want to report 'Internal Error' to the user.
The function should not die with typical mysql error: die(mysql_error(). My web app has two interfaces: browser and email(You can perform certain actions by sending an email).
In both cases it should report error in good aesthetic.
Do I really have to use exception handling for this?
Can anyone point me to some good PHP project where I can learn how to design robust PHP web-app?
In my PHP projects, I have tried several different tacts. I've come to the following solution which seems to work well for me:
First, any major PHP application I write has some sort of central singleton that manages application-level data and behaviors. The "Application" object. I mention that here because I use this object to collect generated feedback from every other module. The rendering module can query the application object for the feedback it deems should be displayed to the user.
On a lower-level, every class is derived from some base class that contains error management methods. For example an "AddError(code,string,global)" and "GetErrors()" and "ClearErrors". The "AddError" method does two things: stores a local copy of that error in an instance-specific array for that object and (optionally) notifies the application object of this error ("global" is a boolean) which then stores that error for future use in rendering.
So now here's how it works in practice:
Note that 'Object' defines the following methods: AddError ClearErrors GetErrorCodes GetErrorsAsStrings GetErrorCount and maybe HasError for convenience
// $GLOBALS['app'] = new Application();
class MyObject extends Object
{
/**
* #return bool Returns false if failed
*/
public function DoThing()
{
$this->ClearErrors();
if ([something succeeded])
{
return true;
}
else
{
$this->AddError(ERR_OP_FAILED,"Thing could not be done");
return false;
}
}
}
$ob = new MyObject();
if ($ob->DoThing())
{
echo 'Success.';
}
else
{
// Right now, i may not really care *why* it didn't work (the user
// may want to know about the problem, though (see below).
$ob->TrySomethingElse();
}
// ...LATER ON IN THE RENDERING MODULE
echo implode('<br/>',$GLOBALS['app']->GetErrorsAsStrings());
The reason I like this is because:
I hate exceptions because I personally believe they make code more convoluted that it needs to be
Sometimes you just need to know that a function succeeded or failed and not exactly what went wrong
A lot of times you don't need a specific error code but you need a specific error string and you don't want to create an error code for every single possible error condition. Sometimes you really just want to use an "opfailed" code but go into some detail for the user's sake in the string itself. This allows for that flexibility
Having two error collection locations (the local level for use by the calling algorithm and global level for use by rendering modules for telling the user about them) has really worked for me to give each functional area exactly what it needs to get things done.
Using MVC, i always use some sort of default error/exception handler, where actions with exceptions (and no own error-/exceptionhandling) will be caught.
There you could decide to answer via email or browser-response, and it will always have the same look :)
I'd use a framework like Zend Framework that has a thorough exception handling mechanism built all through it.
Look into exception handling and error handling in the php manual. Also read the comments at the bottom, very useful.
There's aslo a method explained in those page how to convert PHP errors into exceptions, so you only deal with exceptions (for the most part).

Categories