-
-
Notifications
You must be signed in to change notification settings - Fork 20
Add magic methods in Registry.php #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add magic methods in Registry.php #58
Conversation
|
in class Registry is property |
|
You are right, the magic method __invocable has questionable behavior. I will remove this method.
Let's analyze it.
And instead of disliking, you could explain what exactly you liked and what exactly you didn't like. |
|
@mbabker |
On the contrary, that's exactly why tests need to be added. You've added new methods to the
At that point, does that really read any better than
I just don't like it. It's not that this PR is fundamentally flawed or incorrect in any way. That's just my personal taste of how I write PHP these days, I prefer code that reads clearly over code that relies on magic behaviors. In any of my own projects, I'd personally reject a patch that would try to use the |
|
Writing functions with curly braces can really cause cognitive problems. |
|
@mbabker |
|
In fact, it is not clear what to write in the tests. |
No, you don't. Or, rather to rephrase things, why do you need to understand the internals of the
The existing automated tests in this package give 0 coverage to using the object-oriented syntax. Therefore, tests are needed to ensure that this feature is covered and is not accidentally broken in the future. The entire point of automated testing is to help give developers confidence in the code by having their API features tested and that every feature does not need to be tested by a human with every change (unlike in Joomla world where it seems development is driven by humans validating things in a web browser, I constantly work in applications where I very rarely open my web browser when working on things; these applications have literally thousands of test scenarios covering an overwhelming majority of the code which allows us to make changes safely and lets us know pretty quickly if something is potentially broken). The tests here aren't necessarily to explicitly check values, they're to make sure that feature of the API does not break. final class RegistryTest extends PHPUnit\Framework\TestCase
{
/**
* Test based on existing `testGetOffsetAsAnArray` test case
*/
public function testGetValueThroughMagicGetter(): void
{
$instance = new Registry(['foo' => ['bar' => 'value']]);
$this->assertSame('value', $instance->{'foo.bar'}, 'An assigned key should be retrieved with object access.');
$this->assertNull($instance->{'goo.car'}, 'An unknown key should return null with object access.');
}
}That is all that is needed to test the new |
|
@mbabker
You look like a developer who makes applications that are able to work on his expensive smartphone. And in the calculation of pensioners, schoolchildren, housewives do not take into account at all who have a very cheap smartphone. |
|
Hello @mbabker . Could you run this test?
|
|
I checked the opcode needed to access the object with ->xyz and ->get('xyz') syntax, not much different except the function call is hidden in the magic method. If you like to use fast_concat you can also do this with the On the other side we have already 2 ways to access the values of the registry and normally an object get accessed with arrow functions. So I personally see no real benefit (except my personal preference to use objects with the arrow syntax) but I also see no negative consequences by adding it. To summaries this, if you add the tests correctly, I'm not against this. I think Michael mean you should duplicate https://github.com/joomla-framework/registry/blob/2.0-dev/Tests/RegistryTest.php#L458-L497 and adapt it for the arrow syntax. Maybe I missed a test. |
src/Registry.php
Outdated
| * | ||
| * @return mixed The value of the that has been set. | ||
| * | ||
| * @since 1.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cannot be correct.
src/Registry.php
Outdated
| * | ||
| * @since 1.0 | ||
| */ | ||
| public function __set(string $path = '', $value = null): void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having a default string will allow this to be called without a path which kinda defeats the object of the method right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. Only without default value for path attribute.
src/Registry.php
Outdated
| * | ||
| * @return mixed The value of the removed node or null if not set | ||
| * | ||
| * @since 1.6.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1.6.0?
src/Registry.php
Outdated
| * | ||
| * @return boolean | ||
| * | ||
| * @since 1.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1.0?
src/Registry.php
Outdated
| * | ||
| * @return mixed Value of entry or null | ||
| * | ||
| * @since 1.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1.0?
|
@HLeithner @PhilETaylor |
|
Excuse me. The question is off topic. |
|
in the cms the release script changes the magic string to the version it's building. in the framework jenkins does this on tagging |
|
As charming as this approach may be at first glance, it is unfortunately also unsuitable. What should happen for $reg = new Registry(['data' => ['key' => 'value']]);
$data = $reg->data;? For this reason I have to close this PR, but I would like to thank you for your effort and dedication. |
@nibra Let's bet. |
|
@nibra Leaders who have already watched this PR understand that |
$reg = new Registry(['data' => ['key' => 'value']]);
$data = $reg->data;There are no contradictions $data == ['key' => 'value']To take into account the property |
|
Even if it works with If you absolutely want to call the properties using the arrow, use |
I did not propose to exclude the separator now. I suggested deleting the separator in the future version of Joomla 5. $module = new JRegistry('{"id"=123, "content"="Content","title"="New Module"}');
echo"
<label>$module->title</label>
<div>$module->content $module->user</div>";The code is very easy to read. We can write a lot of examples with very simple and readable code. |
|
We discussed this feature at the last Production Department meeting. The unanimous opinion is that another access method is not desired as it would cause more confusion than solve problems. |
|
I was waiting for such an answer from you, and you sent this answer. Quote:
@mbabker @HLeithner @PhilETaylor Funny, are you seriously saying this? or are you kidding? Dear participants - Joomla executives. I reported this to "nibra", I thought that he either did not understand the code and closed it by mistake PR, or "nibra" has little experience. General reasoning : In open respositories there are always a small part of managers who are interested in slowing development. I understand that complaining about Joomla executives is bad with experience for more than 10 years, but the reason for blocking PR is wrong. "nibra" says magic methods can create confusion. It is not true. And also I can say with confidence that magical methods, on the contrary, remove confusion. Since when developing extensions we turn to different objects : Maybe it has to do with politics? |
|
Absolutely nothing to do with me!
… On 3 Jul 2022, at 20:19, Сергей ***@***.***> wrote:
I was waiting for such an answer from you, and you sent this answer.
Quote:
We discussed this feature at the last Production Department meeting. The unanimous opinion is that another access method is not desired as it would cause more confusion than solve problems.
@mbabker <https://github.com/mbabker> @HLeithner <https://github.com/HLeithner> @PhilETaylor <https://github.com/PhilETaylor>
Funny, are you seriously saying this? or are you kidding?
Dear colleagues, if you get acquainted with this PR, then the current answer "nibra" complements the previous answers, after which it becomes very funny.
Dear participants - Joomla executives.
I want to complain about "nibra".
It's been 2 weeks since he blocked this PR.
He explained this by the fact that there are 2 members in the JREGISTRY class that will conflict.
But this is not the case at all. This class has an important member, but it is private.
Thus, the reason for closing the PR is completely wrong. Since the second member that can cause closure is not important.
Referring to the reason for closing the PR due to the DATA member is completely wrong.
The JREGISTRY class has 2 members, but each member does not have a weight of 50%. The DATA member has an importance of 99.5%. and the SEPARATOR member has a weight of 0.5%.
I reported this to "nibra", I thought that he either did not understand the code and closed it by mistake PR, or "nibra" has little experience.
I asked him to open the PR back.
After which it became clear that "nibra" has a very large experience in the development, and also "nibra" has a good idea of how this class works. As it turned out, he has experience with Mambo 4.6
Until now, PR is still closed.
PR is fully backward compatible.
Before, I was guided by the rule that if this PR improves the lives of 99% of developers, it will be good for everyone.
But now I am in a different situation.
I am in a situation that if there is at least one developer in the world who will be against this PR, then this is an occasion to reject it.
It is obvious that in the world there will always be 1 person who will be against everything.
I tried to explain "nibra" the reasons for the use of this PR, completely retelling the arguments that I wrote at the very beginning of this PR .
Perhaps there are problems (this is only 1 problem) this PR, how to manage a member of the separator.
This problem is completely solvable by the conditions in the code. But this must be discussed. "nibra" does not want to discuss.
I can’t make corrections to the blocked PR that we can make.
General reasoning :
This situation resembles a situation where Microsoft deliberately slowed down the development of OS Linux. Very much.
As an example, we know that OS Linux has Office Libre (Open Office). This is a very complicated program. While Libre Office is an open program.
We can ask ourselves: Were there and wanted people in the world who could modify the user interface to the mind so that it was not as nasty and bad as the Windows 95 interface.
Despite the fact that there were people who developed the complex LibreOffice. Of course there were such people, since making the OSLinux glamorous interface is a much simple task than creating LibreOffice.
OSLinux needed to add shadows to the windows, and make rounded windows, make the windows wider frame so that it was easier to stretch the windows. You just had to add fixes to the current interface.
The Linux interface looked as if people specifically made it very bad and nasty from the age of 95. I think that Microsoft executives know that if you can’t forbid, then you need to lead a group of people.
Of course, there were any developers who wanted it, this did not happen for obvious reasons, then OS Linux would become a competitor to Windows on home PCs.
Today in 2022, OSLinux began to have a modern interface, but this has happened over the past 2-3 years.
This happened after China began to develop its closed DeepinOS (based on Linux). After which Microsoft is no longer able to slow development Linux. After that, you can notice all Linux`s began to actively develop interfaces in a modern look. Literally at 1-2 years, all Linux became impeccably beautiful. As you might guess, the reason for this was the impetus: the fact that Microsoft cannot slow down the development of DeepinOS .
In open respositories there are always a small part of managers who are interested in slowing development.
I am sure that "nibra" is a very professional developer, and "nibra" is a very attentive leader.
Then why did he block this PR for no reason?
"nibra" refers to very dubious reasons. More precisely, it simply selects the most possible reasons that may be the reason for canceling PR. Even if PR will benefit an order of magnitude more.
And then "nibra" didn't want to open it back.
I understand that complaining about Joomla executives is bad with experience for more than 10 years, but the reason for blocking PR is wrong.
Despite the fact that "nibra" had to block PR, but for no reason it was impossible to block. "nibra" indicated a reason that could only be like truthful. And this is a good reason.
I ask the help community to resolve the conflict. Is it possible to do this?
"nibra" says magic methods can create confusion. It is not true. And also I can say with confidence that magical methods, on the contrary, remove confusion. Since when developing extensions we turn to different objects :
JTable, $module, $params, $plugin. Each of these objects creates confusion. Since the JTable object needs to be accessed by the name of the property, the objects $module and $plugin have the type stdClass also need to be contacted by the name of the property.
But at the same time, the configuration object with the type JRegistry does not allow you to handle the property name. It turns out so that half of the extension code uses property names, and half calls the function ->get('prop'). While the default values of 99% are required blank. Since magical methods can create confusion?if the transition to magic methods will completely facilitate the writing of code, readability of code, layouting of code.
—
Reply to this email directly, view it on GitHub <#58 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AADBVXBBTCVTNBJYBGIZ4L3VSHRVNANCNFSM5G2HZF2Q>.
You are receiving this because you were mentioned.
|
Your comment is on top. |
|
I'm sorry that this is hitting you so hard. As I had feared a reaction of this kind, I put the issue up for discussion in the Production Department - not a single advocate was found. Nevertheless, I will try to give you my reasons for rejecting this PR. Joomla is a system with a long history, and although the architecture has already been cleaned up to a great extent with Joomla 4, the process is far from over. Some legacy issues such as the use of magic methods or stdClass make it difficult to make the software less error-prone. Magic methods that respond to arbitrary keys cannot be provided with type hints. This undermines an important instance in quality checking, static code analysis. If an explicit get() method is used, at least this fact is not obfuscated and the developer is not lulled into a false sense of safety. I would also like to remove the array access from the registry, but it has been in there too long for that to be realistic. Even if such constructs are still present in the current code base, we need to eliminate them one by one. In any case, we should not introduce any new ones with today's knowledge. This will only cause pain in the long run in the development of the overall system. I hope this makes it clear that a) this is not a solo decision on my part and b) there are indeed factual reasons. |
|
I realized that there are objective reasons. Based on the stated reasons. I can make a conclusion. That you are trying to get away from the ambiguity of types. |
|
You can't have typed properties in a Registry, which by design is a bag of arbitrary values of any type. When enforcing usage of |
|
@nibra Which IDE editor do you use? |
|
PHPStorm, but that does not really matter. All major IDEs support IntelliSense (although it might have a different name). |
|
@korenevskiy you can be sure it wasn't @nibra decision alone to not except this pr as he already stated that it is a production decision. Beside test if you look at your use case where you want to use
One of the common tasks in a layout is to change the case of a string or do other things before echoing the text. You would need to catch the null variable and convert it to a string, doing this in the template looks ugly and counter intuitive and leads to errors. <?php
class Registry {
public $data = [];
public function __get($var) {
return $this->data[$var] ?? null;
}
public function get($var, $default) {
if (!array_key_exists($var, $this->data)) {
return $default;
}
}
}
$reg = new Registry;
var_dump($reg->empty); // null
var_dump(strtoupper($reg->empty)); // deprecation warning
var_dump($reg->get('empty', 'empty')); // uses the default
var_dump(strtoupper($reg->get('empty', 'empty'))); // uses the default |
|
@nibra @HLeithner var_dump(strtoupper($reg->empty ?? 'empty')); // NOT deprecation warning
var_dump(strtoupper($reg->get('empty', 'empty'))); // uses the defaultIn 99% of cases, it is enough for the code to have a default value of NULL. In 1% of cases, a default value is required. Your example is not proof. Since the use of magical methods in it is either equivalent or also make it more convenient. And now I'll tell you another fact. You are right, text output in layout requires text to be converted into functions. But then it is necessary to specify which text needs to be converted. In the layout, we insert variables: classes, identifiers, attributes to read, labels, Tags eventually. The code above is from the number 1% |
No, the decision was made on the basis of architectural considerations, not technical feasibility. |
|
The extension for PhpStorm that I specified above allows. At any point in the code, set PHPDoc for any variable, as well as set properties and keys in PHPDoc for the same variables. This will allow you to use IntelliSense deep into the variable. /**
* @var array $arr = [
* 'fields' => [ // Defines the feilds to be shown by scaffolding
* $anyKey => [
* 'name' => 'sale', // Overrides the field name (default is the array key)
* 'model' => string, // (optional) Overrides the model if the field is a belongsTo associated value.
* 'width' => '100px', // Defines the width of the field for paginate views. Examples are "100px" or "auto"
* 'align' => 'center', // Alignment types for paginate views (left, right, center)
* 'format' => 'nice', // Formatting options for paginate fields. Options include ('currency','nice','niceShort','timeAgoInWords' or a valid Date() format)
* 'title' => 'Sale', // Changes the field name shown in views.
* 'desc' => 'A deal another person that results in money', // The description shown in edit/create views.
* 'readonly' => false, // True prevents users from changing the value in edit/create forms.
* 'type' => 'password', // Defines the input type used by the Form helper
* 'options' => ['option1', 'option2'], // Defines a list of string options for drop down lists.
* 'editor' => false, // If set to True will show a WYSIWYG editor for this field.
* 'default' => '', // The default value for create forms.
* ],
* ],
* ]
*/
$arr=[
'fields' => [
'0' => [
'model' => 2
]
]
];for VSCode /**
* @var array $arr $arr
* @var array $arr['fields']
* @var array $arr['fields']['fieldName']
* @var array $arr['fields']['fieldName']['name']
* @var array $arr['fields']['fieldName']['model']
* @var array $arr['fields'][fieldName]['width']
* @var array $arr['fields'][fieldName]['align']
* @var array $arr['fields'][fieldName]['format']
* @var array $arr['fields'][fieldName]['title']
* @var array $arr['fields'][fieldName]['desc']
* @var array $arr['fields'][fieldName]['readonly']
* @var array $arr['fields'][fieldName]['type']
* @var array $arr['fields'][fieldName]['options']
* @var array $arr['fields'][fieldName]['editor']
* @var array $arr['fields'][fieldName]['default']
**/
$arr = [
'fields' => [
'fieldName' => []
]
];For JRegistry, a mixed type should not be expected, but a string type should be expected first. Even using the ->get() function, you also need to expect a string value first. Since JRegistry is a serialization and deserialization object. If a person expects a mixed type from JRegistry, then it seems to me that he chose the wrong object. JRegistry has no code to cast one type to another type. You are right, syntactically restrictions are used in different companies. But each company has its own limitations, they are united by only one common limitation of PSR. @nibra Can you tell us about the architectural limitation? |
You don't need any extension to annotate properties. But you can't set an annotation for a property defined at runtime, as is the case with Registry. If you know the properties beforehand, you should use a value object with proper typing instead.
Nope. You should always be aware that you know NOTHING about the returned type. That's why magic property access is bad in this case - properties should always have a proper type (different from
Yes, Registry supports serialisation, but the result will not be what you expect, if objects stored in it do not support serialisation.
The most obvious thing: We would never be able to add public properties to the Registry. Although there are no plans to do so, good architecture does not create such obstacles. I really appreciate your effort and I hope that the rejection of this PR does not demotivate you. |
Add magic methods.
The Registry class is used to get data of different configurations and settings.
In the case when we want to get configuration data with a non-existent setting, we want to use the default value.
But when we use regular objects, we get a PHP error about missing a property.
And when using the Get(), Set() methods, we have to write a lot of code, the text becomes NOT susceptible to reading.
The old syntax.
echo "<button id='" . $params->get('id') . "'>" . $params->get('name') . "</button>";New syntax.
echo "<button id='$params->id'>$params->name</button>";This ability can be used in templates of modules, plugins, components.
You can see how much easier it is to write?
And much more important that such code is easier for programmers to read again.
In the description of this class we see:
This is a similar approach.
But now we can write: