Welcome Guest, Not a member yet? Register   Sign In
How to implement EventSource on Codeignigter app?
#1

(This post was last modified: 02-22-2020, 05:15 PM by SmokeyCharizard.)

I'm trying to send my end user simple updates on the progress of a data conversion in my app. I researched for a while and found EventSource to be the best solution (lightweight and simple). The problem is, I can't seem to get it to listen for events on the correct model/view/controller in codeigniter.
I have a query submission being sent from a form_open_multipart in an index.php in Views.
Code:
<?php echo form_open_multipart('c_controller/classicFirearmByDate'); ?>
<div class="form-group">
     <label>Date From -></label>
     <input type="text" class="form-control" name="date" placeholder="2019-10-15 06:46:30">
</div>
<div class="form-group">
     <label>Date To <-</label>
     <input type="text" class="form-control" name="date-to" placeholder="2019-10-16 06:46:30">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
    <div class="progress progress-striped active">
    <div class="progress-bar" id="progress" style="width:0%"></div>
<div id="message"></div>
<script>
    var element = document.getElementById('message').innerHTML;
    var source = new EventSource("<?php echo site_url('c_controller/classicFirearmByDate');?>");

    source.addEventListener("message", function(e) {
      document.getElementById("progress").innerHTML = "MESSAGE";
      console.log(e);
    }, false);

    source.addEventListener("open", function(e) {
      document.getElementById("progress").innerHTML = "OPENED";
      console.log(e.data);
      element = 'TEst';
    }, false);

    source.addEventListener("error", function(e) {
      document.getElementById("progress").innerHTML = e.readyState;
      if (e.readyState == EventSource.CLOSED) {
        document.getElementById("progress").innerHTML = "CLOSED";
      }
    }, false);

    function showdata(Jdat) {
      var data = JSON.parse(Jdat);
      document.getElementById("result").innerHTML = data.name;
    }
</script>
I use routes.php to route the data to the correct controller (c_controller.php), specifically to a method called classicFirearmByDate().
routes.php $route['c_controller/classicFirearmByDate'] = "c_controller/classicFirearmByDate";
c_controller.php
Code:
<?php
    class C_controller extends CI_Controller{
        public function classicFirearmByDate() {
            $date = trim(htmlspecialchars($this->input->post('date')));
            $dateTo = trim(htmlspecialchars($this->input->post('date-to')));

            $data['body'] = $this->classic_firearms->get_firearm_by_date($date, $dateTo);

            $this->load->view('templates/header');
            $this->load->view('firearms/firearm', $data);
            $this->load->view('templates/footer');
    }
This method validates and then passes the query to the main method of a model (cfa_model.php) called getProductByDate().
Code:
    public function getProductByDate($date, $dateTo) {
         $filter = array($date, $dateTo);
         $data = $this->proxy->catalogProductList($this->sessionId, $filter);
         ...
         //code to process $data
    }
GetProductsByDate() returns the data after being processed and getProduct (in the controller) loads a new "job finished" view with the resulting data.
I want the index.php file (the first one I mentioned) to get the updates of the processing in getProductsByDate().
I tried to set up EventSource listening in index.php to listen to cfa_model.php, but it didn't work. I was able to get it to listen to c_controller.php, but this will not suffice. I need to get consistent updates from the process itself, and the process is only in cfa_model.php.
Is this just a problem with my routes? Could it be my headers? Can I set up cfa_model.php to update another controller and hook a listener to that?
Reply
#2

Hi, found this not sure if it will help but have a look.

HTML5 Server Sent Event in Codeigniter

He's using eventSource.
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply
#3

It's not the route. Actually, you don't need the route. Whenever the key and the value are the same the route is pointless.

One big issue is the attempt to load a new "job finished" view. Any change to the existing page has to happen in the "message" event handler. So sending back the html of a whole page is not appropriate.

Is your intent to show a new page once the data conversion is complete?

If that's the case, then you need to send a "message" that the onmessage event can interpret as "job complete" and then redirect to the new page using javascript.  While the conversion is in progress you should be periodically sending messages that represent the current state of the conversion process. (How long does this process take anyway?) A periodic update like this usually requires a loop with a timer. You might find this example useful. However, that uses sleep() which probably won't work for you as it stops script execution. PHP does have an Event Class which would do what you need, but it requires an external library and the extension isn't bundled with PHP and so requires installation using a PECL.

You probably don't want to create the "EventSource" until the <form> is submitted. So you will need an event listener to catch that.  You can read about the HTMLFormElement: submit event HERE.

One last thing, you do not need a multi-part form. Those are used when you want files to be sent through a POST. You're not doing that.
Reply
#4

(This post was last modified: 02-23-2020, 11:53 AM by SmokeyCharizard.)

Quote:"One big issue is the attempt to load a new "job finished" view. Any change to the existing page has to happen in the "message" event handler. So sending back the html of a whole page is not appropriate.

Is your intent to show a new page once the data conversion is complete?"


Thanks for the reply! The job finished page is not necessary. If that is what I need to remove to get eventsource working, then so be it! SO how would I do this? Just not load the job finished view?
EDIT: I just tried to remove this line:
$this->load->view('templates/header');
$this->load->view('firearms/firearm', $data);
$this->load->view('templates/footer');
But it doesn't change anything. It still tries to return something I think...
Reply
#5

(02-23-2020, 09:45 AM)InsiteFX Wrote: Hi, found this not sure if it will help but have a look.

HTML5 Server Sent Event in Codeigniter

He's using eventSource.

(02-23-2020, 11:33 AM)dave friend Wrote: It's not the route. Actually, you don't need the route. Whenever the key and the value are the same the route is pointless.

One big issue is the attempt to load a new "job finished" view. Any change to the existing page has to happen in the "message" event handler. So sending back the html of a whole page is not appropriate.

Is your intent to show a new page once the data conversion is complete?

If that's the case, then you need to send a "message" that the onmessage event can interpret as "job complete" and then redirect to the new page using javascript.  While the conversion is in progress you should be periodically sending messages that represent the current state of the conversion process. (How long does this process take anyway?) A periodic update like this usually requires a loop with a timer. You might find this example useful. However, that uses sleep() which probably won't work for you as it stops script execution. PHP does have an Event Class which would do what you need, but it requires an external library and the extension isn't bundled with PHP and so requires installation using a PECL.

You probably don't want to create the "EventSource" until the <form> is submitted. So you will need an event listener to catch that.  You can read about the HTMLFormElement: submit event HERE.

One last thing, you do not need a multi-part form. Those are used when you want files to be sent through a POST. You're not doing that.
I actually used that link as a reference to do all this, but thanks for the help!
Reply
#6

(02-23-2020, 11:42 AM)SmokeyCharizard Wrote: SO how would I do this?

First, you have to convince me that EventSource is really the right solution. Smile

Answering the question, "How long does this process take?" would be a good start toward convincing me it is.
Reply
#7

(02-23-2020, 03:11 PM)dave friend Wrote:
(02-23-2020, 11:42 AM)SmokeyCharizard Wrote: SO how would I do this?

First, you have to convince me that EventSource is really the right solution.  Smile

Answering the question, "How long does this process take?" would be a good start toward convincing me it is.
It can take anywhere between 3 minutes to 3 hours, depending on the items being processed. Should I turn to websockets instead? What would you recommend?
Reply
#8

(02-23-2020, 03:27 PM)SmokeyCharizard Wrote: It can take anywhere between 3 minutes to 3 hours, depending on the items being processed. Should I turn to websockets instead? What would you recommend?

Wow! Now that's a very intensive process.

Is the hard part during or after this line?

PHP Code:
$data $this->proxy->catalogProductList($this->sessionId$filter); 

Wherever it is, I'd need to see the code to find the best place(s) to send progress messages.

I don't think WebSockets is necessary. I don't see the two-way capability of them as useful in this case. They are more complicated to implement too.

Unless examining the code indicates otherwise I'd say stick with EventSource.
Reply
#9

(This post was last modified: 02-24-2020, 09:59 AM by SmokeyCharizard.)

(02-23-2020, 11:13 PM)dave friend Wrote:
(02-23-2020, 03:27 PM)SmokeyCharizard Wrote: It can take anywhere between 3 minutes to 3 hours, depending on the items being processed. Should I turn to websockets instead? What would you recommend?

Wow! Now that's a very intensive process.

Is the hard part during or after this line?

PHP Code:
$data $this->proxy->catalogProductList($this->sessionId$filter); 

Wherever it is, I'd need to see the code to find the best place(s) to send progress messages.

I don't think WebSockets is necessary. I don't see the two-way capability of them as useful in this case. They are more complicated to implement too.

Unless examining the code indicates otherwise I'd say stick with EventSource.

Yes and no. The model calls a lot of methods like catalogProductList, and when one is finished, I want it to fire a message. For security purposes, I can't share all the code, but I do know where I should put the messages. The message must be sent from the cfa_model.php, and I can only seem to have the eventsource listen on a controller's function. Would I have eventsource listen to the file itself?
Reply
#10

Because the model is loaded by the controller it should be possible to send the message from the model. The key is sending a proper message. You cannot go to another controller until the processing is done though.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB