Yii Framework Forum: Events in 2.0 - Yii Framework Forum

Jump to content

  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

Events in 2.0

#21 User is offline   phpnode 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 141
  • Joined: 18-April 11

Posted 28 March 2012 - 02:33 PM

trigger() should be public, there are definitely scenarios where you'd need this
1

#22 User is offline   Ben 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 266
  • Joined: 15-March 09

Posted 28 March 2012 - 03:17 PM

Well, I wouldn't mind. Just a minor difference. :)

But could you provide some use cases? The only one that came to my mind after posting were behaviors. There was a feature request, that they should have the possibility to extend the component they are attached to with new events. With the new event system, they could do this easily by calling:

  $this->owner->trigger();



If trigger was protected, they had to raise their own event:

  $this->trigger();



Now, if you want to hide the fact, that the event comes from an behavior instead of from the host component, the base Behavior class could easily override Component's trigger() implementation:

class Behavior extends Component
{
  protected function trigger( $eventName, $event=null )
  {
    if ($event instanceof Event)
    {
      $event->sender = $this->owner;
      $event->name = $eventName;
    }
  }
}

Don't like ads in my sig...
0

#23 User is offline   phpnode 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 141
  • Joined: 18-April 11

Posted 28 March 2012 - 04:27 PM

ben - behaviors are the main use case, keep in mind that behaviors cannot override methods that exist in the attached class so I don't think your example would work, i also posted another specific use case earlier in the thread: http://www.yiiframew...post__p__142981
0

#24 User is offline   Ben 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 266
  • Joined: 15-March 09

Posted 28 March 2012 - 06:58 PM

Well, you can't change what happens when the behavior's host calls trigger(), but you can override Behavior's trigger() method which it inherited from Component. This way, the event dispatching logic could be modified for all events originating from Behaviors (setting sender to $this->owner instead of to $this).

I needed a second look to understand your example, so just for reference:

- You have an article class
- You attach different behaviors to the article (your states)
- One of the states defines a read-event
- You're trying to register to this event
- Because of the current event system, you need to ensure the article is currently in the correct state before registering
- Ideally, you don't want to bother with article's state, you just want to configure "if it gets read, call this method". You shouldn't have to deal with the fact that it can only be read once it is published.

Now, I don't know how qiang implemented the new event system. Let's assume that there's no way to check if a certain event has been declared. Instead,

$article->on( 'read', function(Event $event) {
  echo $event->sender->title . ' has been read!';
});


simply creates a new event for article. Let's also assume that only your attached state triggers the event (can I make this assumption? If yes, trigger() can be protected). The trigger() implementation could look like this:

class Behavior extends Component
{
  protected function trigger( $eventName, $event=null )
  {
    // we should take into account, that Behavior is a Component, and that maybe
    // someone attached event handlers to the Behavior itself instead of to the
    // host...
    parent::trigger( $eventName, $event );

    // now, handle the events which this Behavior triggers as extensions in scope
    // of its host...
    if ($event === null)
    {
      $event = new Event();
    }
    else if (is_array($event))
    {
      $params = $event;
      $event = new Event();
      $event->params = $params;
    }

    if ($event instanceof Event)
    {
      // that's the important part... We're working in scope of our host.
      $event->sender = $this->owner;
      $event->name = $eventName;
    }
    else
    {
      throw new Exception( "Invalid param" );
    }

    foreach ($this->owner->getEventHandlers($eventName) as $eventHandler)
    {
      call_user_func( $eventHandler, $event );
    }

  }
}


So still no reason why trigger() must be public.

But as I've said: no big deal if it was. ;)
Don't like ads in my sig...
0

#25 User is offline   Jaggi 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 90
  • Joined: 05-September 11

Posted 29 March 2012 - 04:27 AM

View Postphpnode, on 28 March 2012 - 04:15 AM, said:

That won't work if you have properties with the same name as the event, i think qiang's implementation is absolutely fine. One thing though, the second parameter to trigger() should be optional, it should just raise a new default event with the object as the sender if it isn't specified


Shouldn't really have those circumstances off the top of my head, another option tho is:

$this->widget('Button', array(
    'name' => 'submit',
    'events' => array(
          'click' => function($event) {...}
    )
));


a little more complicated but easier to remember than "on click", can lots of people doing: 'onClick', 'onclick', 'click' etc.

See my development site @ www.CodeTheInter.net (BETA)

Posted Image Posted Image

Quote

If you make it idiot proof, they'll build a better idiot
0

#26 User is offline   Rodrigo Coelho 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 664
  • Joined: 05-August 10
  • Location:Rio de Janeiro, Brazil

Posted 29 March 2012 - 04:11 PM

@Jaggi,

I like this, but if the "on" has a function? There could be, for example, an "off click" command to remove a default event.
0

#27 User is offline   Jaggi 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 90
  • Joined: 05-September 11

Posted 30 March 2012 - 05:53 PM

View Postmentel, on 29 March 2012 - 04:11 PM, said:

@Jaggi,

I like this, but if the "on" has a function? There could be, for example, an "off click" command to remove a default event.


that would be bound at the trigger not an event, as in qiang example before:

// attach an anonymous function to the 'click' event
$button->on('click', function($event) { ... });
// trigger the 'click' event
$button->trigger('click', new Event($this));
// detaches $callback from 'click'
$button->off('click', $callback);

See my development site @ www.CodeTheInter.net (BETA)

Posted Image Posted Image

Quote

If you make it idiot proof, they'll build a better idiot
0

#28 User is offline   jacmoe 

  • Elite Member
  • Yii
  • Group: Moderators
  • Posts: 2,601
  • Joined: 10-October 10
  • Location:Denmark

Posted 30 March 2012 - 07:57 PM

I would probably use 'connect' and 'disconnect' :)
"Less noise - more signal"
0

#29 User is offline   Onman 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 175
  • Joined: 26-December 09
  • Location:The Netherlands

Posted 22 April 2012 - 04:02 PM

View Postqiang, on 27 March 2012 - 10:47 PM, said:

It is also possible to attach an event handler in a configuration array:
$this->widget('Button', array(
    'name' => 'submit',
    'on click' => function($event) {...}
));


Other proposals are not implemented until we see enough evidence they are useful.


A slightly different proposal for the configuration array: use an array of form 'eventName' => function
$this->widget('Button', array(
    'name' => 'submit',
    'on' => array(
        'click' => function($event) {...},
        'otherEvent' => function($event) {...} 
    )
));

0

Share this topic:


  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users