Skip to content
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

Update structure-widgets.md with more details #9833

Closed
wants to merge 2 commits into from
Closed

Update structure-widgets.md with more details #9833

wants to merge 2 commits into from

Conversation

CyberPunkCodes
Copy link

Added example of creating and passing global default values from main.php

Added example of creating and passing global default values from main.php
Add example for global defaults in components array.

Based off the example widget above, make minor changes to use this default `message` param. If `message` is `null` (because it was not set in the widget directly), it will fetch the value from your config `web.php`.

```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

```php

@samdark
Copy link
Member

samdark commented Oct 5, 2015

It's not intended to use widgets like that.

@samdark samdark closed this Oct 5, 2015
@CyberPunkCodes
Copy link
Author

Sorry but your wrong. Many widgets need global config. The only reasonable place is to set them in config so you dont have to repeat yourself a million times. Besides that, it works just fine.

The docs are lacking in a million places. When you go to the docs page about widgets, it should tell you everything you need to know about them, or link to another page with more info.

I have came across many people who all say the same thing, their biggest issue with Yii is with the docs.

Sent from my iPhone

On Oct 5, 2015, at 5:19 AM, Alexander Makarov notifications@github.com wrote:

It's not intended to use widgets like that.


Reply to this email directly or view it on GitHub.

@samdark
Copy link
Member

samdark commented Oct 5, 2015

I've added a link to DI docs. That's how widgets are supposed to configure their default values.

@CyberPunkCodes
Copy link
Author

To make a reusable extension for the public, you wouldn't use the DI container to set an API key. I have used many extensions, and this is the first time I have ever seen it used!

That DI does the same exact thing as putting the array in your config. It adds the array to the components array.

What we are talking about is the exact same thing, only your way is a non user friendly way to do it programmatically, from within the code routine.

With a recaptcha widget, or google maps widget, our YouTube widget... Social media share button widget.. The end user will need to add their credentials globally. Add them in the config components array so they are used globally through their site.

If you don't see that, then I give up. I won't try to help anyone else or the community.

Sent from my iPhone

On Oct 5, 2015, at 6:03 AM, Alexander Makarov notifications@github.com wrote:

I've added a link to DI docs. That's how widgets are supposed to configure their default values.


Reply to this email directly or view it on GitHub.

@samdark
Copy link
Member

samdark commented Oct 5, 2015

Array in config is for application components, not widgets. DI container isn't doing the same.

@CyberPunkCodes
Copy link
Author

Yii is about making things simpler and easier on the developer. Keeping things as lightweight as possible. It doesn't make sense to make a component for a simple widget. One extra class loaded for no reason.

Sent from my iPhone

On Oct 5, 2015, at 1:46 PM, Alexander Makarov notifications@github.com wrote:

Array in config is for application components, not widgets.


Reply to this email directly or view it on GitHub.

@samdark
Copy link
Member

samdark commented Oct 5, 2015

Well, what you're proposing is exactly that. If widget is registered in components config of the application it becomes a component. And that's why I'm opposing it.

@SilverFire
Copy link
Member

A few words about Google Maps, YouTube, social, etc widgets, when you have 3rd-part widget which does not support some special ways of configuring defaults.
So I had the same question: how to use widget with the same configureation multiple times and found at least 3 approaches:

  • Create a view views/widgets/FacebookButton.php, create an alias @facebookButton and use $this->render('@facebookButton', ['config' => ['override']])

  • Create an option in params.php and call widget FacebookButton::widget(Yii::$app->params['facebookButton'])

  • Create a component FacebookButton, configure it with components configuration array and call it like echo Yii::$app->facebookButton->render($options)

    I think, we can find more good ways of implementing toogether.

    P.S.: I think we must not be afraid of extra class, when it gives a clear understanding of what is going on.

@samdark
Copy link
Member

samdark commented Oct 5, 2015

@SilverFire you're missing officially recommended way to do it: http://www.yiiframework.com/doc-2.0/guide-concept-di-container.html#practical-usage

@SilverFire
Copy link
Member

@samdark Yes, of course, it's the best solution for global changes. I didn't mention it because it would affect all the calls of Widget. I needed to store two different configs of the same widget and have an ability to call it with config A or config B

@CyberPunkCodes
Copy link
Author

@samdark http://www.yiiframework.com/doc-2.0/yii-base-component.html

A subclass of yii/base/component is yii/base/widget. Therefore, a widget is a type of component. So it being used under the components array, should be acceptable usage. class Widget extends Component implements ViewContextInterface... it directly extends Component anyways..

A dog is an animal.. a car is a vehicle.. a widget is a component.

To top it off, even the configurations page of the docs, is vague on how to do this.. It listed some arrays in the components, but nothing talking about how to actually implement it in my own extension. I see examples of db and mail, they pass parameters.. I want to do that too!

So I checked out the components page, since you say they are appropriate to be in the components array passing params as I demonstrated. Nope, still no examples or information on anything like the following:

'components' => [
    'myComponent' => [
        'class' => 'path/to/MyComponent',
        'API_KEY' => 'mykey',
        'API_PASS' => '123456',
    ],
],

I am trying to learn how to set a global param for my extension, that I plan to share with the world..

Then you tell me about the ugly DI option (which I have never seen anyone use).. Docs don't even tell me what to do with it? Do I put it in the index.php of my main script to "inject" it? Maybe I put it in my controller? Maybe Google knows.. SO?.. hours wasted..

This isn't about me, it's about new developers coming to Yii that have no idea. They come to the docs for the answer, and get stuck in maze. I understand you can't fit everything on one page, but a note with a link to it, is expected.

The docs are a maze. If I go to the Components page, I should learn everything I need to know about them, or a link to further details. A note with a link to a link for "how to extend a component", "how to add your component to your components array".

I recently extended the AccessControl and AccessRule to roll out my own modifications. Information on how to extend AccessControl and AccessRule, little to no information. Once you get passed the basics on how to install Yii2 and setup a few things, it's a free for all.

My biggest problem with the docs, is I go to the page I expect the answer to be on. ie: widgets.. and can not find the answer.

To do it like you say it should be done, it should mention on the widgets page that if you need to pass params from your main.php config to your widget, you should create a Component. And have a link with an example on using a Component to handle a widget and using params from the components array in main.php/web.php.. the current docs, just leaves them hanging.

@samdark
Copy link
Member

samdark commented Oct 6, 2015

Anything that's listed under components is:

  1. Is application component.
  2. Created once.
  3. Meant to be accessed as Yii::$app->componentName.

While technically it could be done, widgets weren't meant to be used like that. Their defaults are meant to be configured via DI container in which guide it's saying directly about where to do it:

  • If you are the developer of an application, you can register dependencies in your
    application's entry script or in a script that is included by the entry script.
  • If you are the developer of a redistributable extension, you can register dependencies in the bootstrapping class of the extension.

I've added missing link from a widgets page to DI page. Now it should be much easier to find it. If you have more of such references missing in mind, let me know, I'll add these.

@CyberPunkCodes
Copy link
Author

Thank you for the attention, but this actually is more like it: Structure Applications which then also links to Structure Application Components

It was in there the whole time, exactly what I am talking about. Nobody here mentioned it, and I have been beating this issue with examples, and the reply I got was to use DI...

Wish there was an anchor link to go right to it though. Here is an excerpt from Structure Applications:

"This is the single most important property. It allows you to register a list of named components called application components that you can use in other places.
...
Each application component is specified as a key-value pair in the array. The key represents the component ID, while the value represents the component class name or configuration.

You can register any component with an application, and the component can later be accessed globally using the expression \Yii::$app->componentID.

Please read the Application Components section for details."

This bit of information, is gold for someone trying to make a widget (such as yii2-recaptcha for example) or any type of extension, yet it is barely mentioned and hard to find!

In my commit, I do reference it as Yii::$app->componentName.

if ( $message === null ) {
    $this->message = Yii::$app->componentName->message;
}

As I said, I already know how to do it. What use am I if I just learn for myself and don't try to help anyone else. The community wouldn't go far if everyone had that mentality.

@samdark
Copy link
Member

samdark commented Oct 6, 2015

if ( $message === null ) {
    $this->message = Yii::$app->componentName->message;
}

Doesn't look right to me. It looks like component is used for the config purpose only which is certainly wrong. Either it should be used as a component afterwards i.e. Yii::$app->componentName->something() or parameters could be in Yii::$app->params['something']. The best solution is still using DI.

@CyberPunkCodes
Copy link
Author

It looks like component is used for the config purpose only which is certainly wrong

No, its just an example.

If you are the developer of an application, you can register dependencies in your application's entry script or in a script that is included by the entry script.

I would never start tossing junk in there... nor ask anyone installing my package to do so either.. index.php already loads the config web.php (basic) as illustrated in the entry script page. I will just use it.

If you are the developer of a redistributable extension, you can register dependencies in the bootstrapping class of the extension.

So where exactly do I ask them to enter their Google API Key and Secret so my extension can access it? The whole point is easy.. asking them to modify index.php is crazy.. or to drop a line to DI.. You could use params, but it doesn't have the ability to bind to an instance of an object!

Every single extension, widget, whatever you want to call them, I have used required me to add something for it in my main.php configuration file. So maybe they are all doing it wrong?

As I have stressed, this is about ME making an extension for OTHER PEOPLE! ie: use composer, download my cool extension, enter these in config, presto. Exactly how thousands of other people have already done, all over Github. If it was just for me to use, I would just hard code it in there. It is about other people using my work.

Scenario..

I am creating a widget to help make embedding YouTube videos on your page easier. Simply call YouTuber::widget(['video' => 'http://youtube.com/somevideo']);

Boom, YouTube video embedded for them. However, to take advantage of more features, you need to have API credentials and use their API: https://developers.google.com/youtube/v3/getting-started

Maybe you want to enable autoplay, control the width/height, aspect ration, disable full screen.. I dunno, whatever other options you can take advantage of.

Globally for the entire site, you can force every embedded video to autoplay and be 600x300..

'components' => [
    'youTuber' => [
        'class' => '/path/to/YouTuber',   // this loads the class to use over and over again everywhere
        'API_KEY' => 'mykey',
        'API_SECRET' => '123456',
        'autoplay' => true,
        'width'=> 600,
        'height' => 300
    ],
],

Now every page I embed a youtube video, it will default to those settings. I can still override them manually in my view when calling the widget.. ie:

`<?= YouTuber::widget(['video' => 'http://youtube.com/somevideo', 'width' => 300, 'height' => 200]) ?>`

Params are used for things like holding the admins email address, phone number, things like that. Not default values for your odd and end extensions/widgets/components.. I haven't used an extension that said "now enter this in your params"...

As I said, everything for yii2 I have used, must be doing it wrong. I could probably list 20+ popular and well put together extensions in 10 minutes.. probably could find you 100 in a day.. all using components array that way.

@samdark
Copy link
Member

samdark commented Oct 6, 2015

All these extras should be configurable via widget properties. Defaults could be set via DI. The huge pro #1 of it is that you can override one or more defaults like that (same as in your case):

YouTube::widget([
    'video' => 'http://youtube.com/somevideo',
    'width' => 300,
    'height' => 200
]);

The second huge pro is that you don't have to access application instance or read component config or do anything within your widget code:

class YouTube
{
    public $video;
    public $width;
    public $height;

    public function run()
    {
        if ($width !== null) {
            //  do something
        }
    }
}

@SilverFire
Copy link
Member

Would like DI way more, if you could configure it with configuration array like this:

[
    'di' => [
        'yii\widgets\LinkPager' => [
            'maxButtonCount' => 5
        ]
    ]
]

And then somewhere

foreach ($config['di'] as $class => $value) {
     Yii::$container->set($class, $value);
}

will be executed

@CyberPunkCodes
Copy link
Author

I agree. I am not opposed to DI, however I haven't seen any extension ask me to use it to configure tier extension. I think a config array is the most socially accepted method of passing around reusable and configurable packages. I don't care if the array is named "crap" in main.php , as long as it's easy an clean to setup my global defaults.

Sent from my iPhone

On Oct 6, 2015, at 5:37 AM, Dmitry Naumenko notifications@github.com wrote:

Would like DI way more, if you could configure it with configuration array like this:

[
'di' => [
'yii\widgets\LinkPager' => [
'maxButtonCount' => 5
]
]
]
And then somewhere

foreach ($config['di'] as $class => $value) {
Yii::$container->set($class, $value);
}
will be executed


Reply to this email directly or view it on GitHub.

@SilverFire
Copy link
Member

@samdark What do you think, is it necessary to implement DI config loading from the config?

As for me, this will be a good option. The only minus is that we will support one additional piece of code for some kind of syntax sugar.

@samdark
Copy link
Member

samdark commented Oct 8, 2015

I don't think it's necessary. It would be exactly the same thing.

@SilverFire
Copy link
Member

@samdark
We already have components config section, which is equal to Yii::$app->container->set($key, $value) and nobody complains about.

P.S.: And I'm not sure, whether I really want to get this feature. I'm sharing my thoughts and will be thankful to hear other members' opinion.

@samdark
Copy link
Member

samdark commented Oct 8, 2015

It's not equal.

@SilverFire
Copy link
Member

Sorry, that was a typo. Yii::$app->set($key, $value)

@dynasource
Copy link
Member

@WadeShuler:

Firstly, I agree with you that Widgets should be configured centrally from a reuse perspective.
Secondly: if you want to benefit from one central place for Widget configuration, I'd advise you to use DI (Yii::$container->set), like @samdark states.
Thirdly, @samdark also advises you no to put 'configs' for widgets inside $app->components. This choice is up to you, as everything basically is a component. But if you also value an application from a architectural perspective, there are alternatives which are better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants