Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] 1 linijka zamiast 3
Forum PHP.pl > Forum > Przedszkole
KR2615
Hej
Zmieniłem bibliotekę do komunikacji mojego skryptu PHP z Mikrotikiem z https://github.com/EvilFreelancer/routeros-api-php na https://github.com/BenMenking/routeros-api
Wcześniej posługiwałem się takim kodem do odczytu:
  1. $identity = $client->query('/system/identity/print')->read();

Teraz w przykładzie znalazłem:
  1. $client -> write('/system/identity/print');
  2. $read = $client -> read(false);
  3. $identity = $client -> parseResponse($read);

Jak ten drugi kod przerobić żeby też mieścił się w jednej linijce?
Salvation
Nie przerobisz tego na jednolinijkowca, bo metoda `write` nie zwraca obieku, a jedynie typ prosty: bool.
Z resztą, ja osobiście nie widzę potrzeby. Tak jak jest, jest czytelniej, a dla interpretera i tak ta różnica jest niezauważalna.

Max co można zrobić, to tak:
  1. $client->write('/system/identity/print');
  2.  
  3. $parsedResponse = $client->parseResponse($client->read(false));

Z kodu klasy wynika jeszcze, że możesz po prostu zrobić takie coś:
  1. $client->write('/system/identity/print');
  2.  
  3. $parsedResponse = $client->read();

I też będzie działać jak powyżej.
gino
$client jest u Ciebie instancją klasy, która odwołuje się do różnych metod: $client->write($patch), $client->read itd. Po co chcesz to łączyć w jedna linijkę?
Nie da się podmienić obiektu $client na write($patch) bo to już nie będzie instancja i dostaniesz masę błędów.
Ewentualnie jak napisał @Salvation
KR2615
Cytat(Salvation @ 18.10.2022, 10:45:15 ) *
Z resztą, ja osobiście nie widzę potrzeby.

A ja mam to w 26 miejscach w kodzie i wolałbym poprawić to jednym regexpem zamiast ręcznie. Ale skoro nie ma możliwości to ok:)
Salvation
Cytat(KR2615 @ 18.10.2022, 10:56:53 ) *
A ja mam to w 26 miejscach w kodzie (...)

To zamknij ten kod w metodę i utwórz Traita. Wtedy tylko raz zmienisz to w 26 miejsach, a później już tylko w jednym.
nospor
Jak ci ta jedna linijka jest potrzebna do regexpa to

$client->write('/system/identity/print'); $parsedResponse = $client->read();

I masz jedna linijke
KR2615
Tylko, że ja tak za bardzo nie umiem w programwanie obiektowe sad.gif Czytałem poradniki, robiłem kursy ale nic. Może jakiś gotowiec na tym przykładzie by mnie oświecił?

Cytat(nospor @ 18.10.2022, 11:07:38 ) *
Jak ci ta jedna linijka jest potrzebna do regexpa to

$client->write('/system/identity/print'); $parsedResponse = $client->read();

I masz jedna linijke

Zamieniłem ale wyszło coś takiego:
  1. $users = $client->write('/user/print'); $parsedResponse = $client->read();
  2. $dns = $client->write('/ip/dns/print'); $parsedResponse = $client->read();
  3. $ntp_serv = $client->write('/system/ntp/client/print'); $parsedResponse = $client->read();

a chodziło by mi o to, żeby pod zmiennymi $users, $dns i $ntp_serv pojawiła się już sparsowana odpowiedź. Dlatego tak zależy mi na "jednej linijce".
gino
Najprościej dopisz w klasie RouterosAPI metodę np. clientConnect(string $patch) i wrzuć w nią kod, który masz w pierwszym poście, coś takiego:

Kod
public function connectClient(string $patch)
{
  $this->write($patch);
  return $this->parseResponse($this->read(false));
}

i będziesz miał jedną linijkę w stylu:

Kod
$identity = $client->connectClient('/system/identity/print');


zmieniając sobie ścieżkę jak Ci się podoba.
KR2615
Fajnie, dzięki, o to właśnie mi chodziło!
Salvation
Nie nalezy edytować plików źródłowych. Teraz wyobraź sobie, że robisz update biblioteki i wszystkie Twoje zmiany idą się paść na zieloną łączkę...
Dlatego napisałem, byś obudował bibliotekę własną abstrakcją.

Korzystasz z composera może?
gino
dlatego napisałem najprościej a nie najlepiej i to chyba jest logiczne. Ucięło mi też z jakiegoś powodu resztę posta, bo pisałem, żeby zrobił jak radzisz, albo napisał własne rozszerzenie klasy i podałem tam też przykład.
KR2615
Cytat(Salvation @ 18.10.2022, 14:01:32 ) *
Korzystasz z composera może?

W tym rozwiązaniu nie. Poprzednią bibliotekę  ładowałem composerem:
  1. //include("vendor/autoload.php");
  2. //use \RouterOS\Client;
  3. //use \RouterOS\Query;
Salvation
To pamiętaj o zmianach jakie wykonałeś przy update'cie biblioteki.
KR2615
Nie dotykałem biblioteki bo już kiedyś brutalnie się przekonałem, co to znaczy updatować biblioteki, zmieniać strukturę danych itp na przykładzie LMSa (Lan Management System), że wyszła mi z niego kompletnie osobna gałąź i nie mogłem w łatwy sposób korzystać z feature'ów wprowadzanych przez Twórców. Wszystko zrobiłem w "mojej" części kodu.
Działa dokładnie tak, jakbym chciał.
Dzięki wszystkim za pomoc!

----------------


Jeszcze jedno pytanie w tym samym temacie. Dostaję od urządzenia taką odpowiedź:
  1. array(2) {
  2. [0]=>
  3. array(8) {
  4. [".id"]=>
  5. string(2) "*1"
  6. ["address"]=>
  7. string(13) "10.9.4.109/24"
  8. ["network"]=>
  9. string(8) "10.9.4.0"
  10. ["interface"]=>
  11. string(7) "ether1"
  12. ["actual-interface"]=>
  13. string(7) "ether1"
  14. ["invalid"]=>
  15. string(5) "false"
  16. ["dynamic"]=>
  17. string(5) "false"
  18. ["disabled"]=>
  19. string(5) "false"
  20. }
  21. [1]=>
  22. array(8) {
  23. [".id"]=>
  24. string(2) "*2"
  25. ["address"]=>
  26. string(13) "10.9.4.209/24"
  27. ["network"]=>
  28. string(8) "10.9.4.0"
  29. ["interface"]=>
  30. string(7) "ether2"
  31. ["actual-interface"]=>
  32. string(7) "ether2"
  33. ["invalid"]=>
  34. string(5) "false"
  35. ["dynamic"]=>
  36. string(5) "false"
  37. ["disabled"]=>
  38. string(5) "false"
  39. }
  40. }

Jak za pomocą kodu php znaleść nazwę interfejsu (ether2) na którym jest IP 10.9.4.209 ?
KR2615
Przeczytałem dokumentację, przejżałem przykłady ale nadal nie przychodzi mi do głowy pomysł, jak rozwiązać to zadanie.
Salvation
  1. <?php
  2.  
  3. declare(strict_types=1);
  4.  
  5. function findNetworkWithIPAddress(array $payload, string $ipAddress): array
  6. {
  7. $network = array_values(array_filter($payload, function (array $networkInfo) use ($ipAddress) {
  8. $address = $networkInfo['address'] ?? '';
  9.  
  10. /** for PHP < 8.0 */
  11. // return substr($address, 0, strlen($ipAddress)) === $ipAddress;
  12.  
  13. /** for PHP >= 8.0 */
  14. return str_starts_with($address, $ipAddress);
  15. }));
  16.  
  17. return reset($network) ?: [];
  18. }
  19.  
  20.  
  21. $payload = [
  22. [
  23. ".id" => "*1",
  24. "address" => "10.9.4.109/24",
  25. "network" => "10.9.4.0",
  26. "interface" => "ether1",
  27. "actual-interface" => "ether1",
  28. "invalid" => false,
  29. "dynamic" => false,
  30. "disabled" => false,
  31. ],
  32. [
  33. ".id" => "*2",
  34. "address" => "10.9.4.209/24",
  35. "network" => "10.9.4.0",
  36. "interface" => "ether2",
  37. "actual-interface" => "ether2",
  38. "invalid" => false,
  39. "dynamic" => false,
  40. "disabled" => false,
  41. ],
  42. ];
  43.  
  44. $network = findNetworkWithIPAddress($payload, '10.9.4.209');
  45. $interfaceName = $network['interface'] ?? '';
  46.  
  47. var_dump($interfaceName);


Demo: https://3v4l.org/EYugm
KR2615
Dzięki, działa! Sam bym tego lepiej nie wykonał ani nawet lepiej nie nazwał : )

Edit: Po dodaniu
  1. declare(strict_types=1);

taki fragment kodu:
  1. if(strpos($values[1],$node['ip']) !== false) {
  2. $badnodes = true;
  3. $no_contain .= $node['ip'].'/32,';
  4. }

wyrzuca:
Cytat
ncaught TypeError: strpos() expects parameter 1 to be string, null given in....

nospor
N $values[1] jest NULLem a nie tekstem. Pomysl co z tym fantem teraz zrobic
KR2615
Już wczoraj pomyślałem i stworzyłem warunek
  1. if(empty($node['ip'])) { $node['ip'] = ''; }

ale chyba ze zmęczenia nie zauważyłem, że chodzi o parametr pierwszy a nie drugi (albo coś mi się pomyliło i sobie ubzdurałem, ze parametry funkcji w PHP też są numerowane od 0 : )

W każdym razie prawidłowe rozwiazanie brzmi:
  1. if(empty($values[1])) { $values[1] = ''; }

Dzięki za nakierowanie!
Pozdrawiam
trueblue
  1. $values[1] ?? ''
gino

Tak nie całkiem offtopic. Czy po dwóch linijkach kodu które napisałeś mam podstawy wnioskować, że nie będziesz rozumiał co napisał @trueblue, czy może się mylę? To tak a propos kopiuj/wklej do swojego kodu.
KR2615
Widziałem już gdzieś taki przykład @gino. To uproszczenie tego ifa które z powodzeniem udało mi się zastosować:
  1. if(strpos($values[1] ?? '',$node['ip']) !== false) {
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.