2017-07-18 53 views
5

Więc staram się wykorzystywać Server Sent Events w moim laravel aplikacji, ale problemem jest to, że w SSE, można określić tylko jeden adres URL w:Jak uniknąć pojedynczej trasy w laravel na serwer wysłał Wydarzenia

var evtSource = new EventSource("sse.php"); 

The Problem polega na tym, że chcę wysyłać zdarzenia z różnych części/kontrolerów całej aplikacji, nie tylko pojedynczego pliku sse.php. Przykład:

// AuthController.php 
public function postLogin(Request $request) { 
    // login logic 

    // SEND SSE EVENT ABOUT NEW USER LOGIN 
} 

// FooController.php 
public function sendMessage() { 
    // SEND SSE EVENT ABOUT NEW MESSAGE 
} 

Jedyny pomysł, który przychodzi mi do głowy to, że z tych sterowników, tworzenie plików tymczasowych z tekstem zdarzeń, a następnie odczytać te pliki tekstowe w sse.php pliku, wysyłania zdarzeń, a następnie usunąć pliki. Jednak nie wygląda to na idealne rozwiązanie. A może jakiś plik hakowy sse.php z mechanizmem zdarzeń Laravel, ale to wydaje się nieco zaawansowane.

Nie mam również nic przeciwko tworzeniu wielu obiektów źródłowych zdarzeń z różnymi plikami php, takimi jak sse.php, ale problem polega na tym, że te metody kontrolerów niekoniecznie wysyłają same zdarzenia, ale także wykonują inną pracę. Na przykład nie mogę użyć akcji postLogin bezpośrednio w obiekcie SSE, ponieważ wykonuje ona również logikę logowania, nie tylko wysyłając wydarzenie.

Czy ktoś miał podobny problem i jak sobie z nim radzić?

+0

Zamieszczam to jako komentarz, ponieważ nie jest (i nie jestem pewien, czy jest) idealnym rozwiązaniem. Stworzyłem 1 punkt końcowy API w laravel, który pobiera pewien parametr (treść POST lub ciąg zapytania), który określa, jakie "części/kontrolery" chce się wyświetlać. Obudowa przełącznika w twoim "głównym" kontrolerze, jeśli chcesz. –

+0

@ThomasMoors: Jak byś powiedział z obiektu źródła zdarzenia, który metoda kontrolera ma wywoływać, ponieważ nie ma dodatkowych parametrów argumentu? Var evtSource = new EventSource ("sse.php"); '. Obawiam się też, że to nie zadziała w przypadku akcji 'postLogin', która również wykonuje logikę logowania, nie tylko wysyłając wydarzenie. – dev02

+0

Mój zły: nie obsługuje [POST tylko GET] (https://stackoverflow.com/questions/34261928/server-sent-events-pass-parameter-by-post-method) Więc jesteś w dół, aby zapytać o żądanie GET parametry: 'var evtSource = new EventSource (" sse.php? whatIwant = theSpecialController ");' –

Odpowiedz

2

SSE nigdy nie używane, ale w zależności od ich docs, dwa rozwiązania przychodzą do mojego umysłu:

1.Define stwardnienie EventSource obiekty i obsługiwać je w różny sposób w swoim JS:

var loginSource = new EventSource("{!! url("/loginsse") !!}"); 
var messageSource = new EventSource("{!! url("/messagesse") !!}"); 

2. Wewnątrz pliku sse.php, sprawdzać aktualizacje z kontrolera innymi:

//sse.php called function 
while(1) { 
    $login = AuthController::postLogin($request); 
    if ($login) return $login; 

    $msg = FooController::sendMessage(); 
    if ($msg) return $msg; 
    // ... 
} 

Trzeba będzie dokonać sendMessage() i postLogin(Request $request) metody statyczne.

Zastanów się także nad przyjęciem niektórych bibliotek do używania SSE z laravel: szybkie wyszukiwanie google dało mi kilka możliwości.

2

Można użyć zdarzeń Laravel i utworzyć detektor, który połączy wszystkie zdarzenia z twojej aplikacji w jeden strumień, a następnie będziesz mieć jeden kontroler, który będzie emitował ten strumień zdarzeń do klienta. Możesz wygenerować zdarzenie w dowolnym miejscu w kodzie i będzie ono przesyłane strumieniowo do klienta. Potrzebujesz jakiegoś współdzielonego bufora FIFO, aby umożliwić komunikację między słuchaczem a kontrolerem, słuchacz zapisałby do niego, a kontroler odczytałby go i wysłał SSE. Najprostszym rozwiązaniem byłoby użycie do tego zwykłego pliku dziennika.

Również Laravel ma wbudowaną funkcję nadawania przy użyciu Laravel Echo, więc może to mogłoby pomóc? Nie jestem pewien, czy Echo używa SSE (zero doświadczenia z obu), ale robi prawie to samo ...

Aktualizacja: Pozwól mi spróbować dodać przykład:

1) Najpierw musimy utworzyć wydarzenie i słuchacza, np

php artisan make:event SendSSE 
php artisan make:listener SendSSEListener --event=SendSSE 

2) Twoja klasa zdarzenie jest po prostu otoki wokół danych, które chcesz przekazać do słuchacza. Dodaj do klasowych SendSSE jak wiele właściwości, jak trzeba, ale pozwala przechodzić tylko wiadomość ciąg dla tego przykładu:

public function __construct($msg) 
    { 
     $this->message = $msg; 
    } 

    public function getMessage() 
    { 
     return $this->message; 
    } 

3) Teraz można odpalić to wydarzenie tak:

event(new \App\Events\SendSSE('Hello there')); 

4) Twój Metoda obsługi handle() odbierze go, a następnie musisz przekazać go do bufora FIFO, którego użyjesz do komunikacji ze sterownikiem SSE. Może to być tak proste, jak zapisanie do pliku, a następnie odczytanie go w kontrolerze, lub możesz użyć rury DB lub linux fifo lub współużytkowanej pamięci lub cokolwiek chcesz.Zostawię tę część ciebie i zakładają, że masz dla niego usługę:

public function handle(\App\Events\SendSSE $event) 
{ 
    // let's presume you have a helper method that will pass 
    // the message to the SSE Controller 
    FifoBufferService::write($event->getMessage()); 
} 

5) Wreszcie, w SSE kontrolera należy odczytać bufor FIFO, a kiedy przychodzi nowa wiadomość przekazać go do klienta :

while(1) { 
    // if this read doesn't block, than you'll probably need to sleep() 
    if ($new_msg = FifoBufferService::read()) {  
     $this->sendSSE($new_msg); 
    } 
} 
+0

Tak, mam powody, by sądzić, że wydarzenia i słuchacze mogą być w jakiś sposób wykorzystane, ale teraz pewna, jak prosty przykład byłby przydatny. Dzięki – dev02

+0

@ dev02 dodano kilka przykładów. Zauważ, że pisałem to z mojej głowy, nie testowałem żadnego kodu. To jest po prostu ilustracja tego pomysłu. Aby uzyskać szczegółowe informacje na temat zdarzeń/słuchaczy, sprawdź https://laravel.com/docs/5.4/events#defining-events – ivanhoe