• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Własny framework

Object Storage Arubacloud
+1 głos
805 wizyt
pytanie zadane 29 stycznia 2020 w PHP przez michal_php Stary wyjadacz (13,700 p.)
Cześć.

Otóż zamierza stworzyć własny framework dla php do api. I mam pytanie czy znacie jakieś dobre poradniki gdzie można mnie więcej jak inni budują swoje własne frameworki aby móc się wzorować na dobrych praktykach. Z góry dziękuje za podpowiedź. Oraz i temat jest otwarty dla każdego kto chce dodać jakiś inne podobne uwagi i spostrzeżenia.

2 odpowiedzi

+2 głosów
odpowiedź 30 stycznia 2020 przez Ehlert Ekspert (212,670 p.)
wybrane 30 stycznia 2020 przez michal_php
 
Najlepsza
Ten pomysł nie ma większego sensu, ale zobaczysz to dopiero gdy sam spróbujesz napisać własny framework.

Ogólnie tworząc framework trzeba myśleć o tym jaką architekturę może on dostarczyć oraz jak wygodny będzie w użyciu. Wszystko to powinno być realizowane poza problemami domenowymi. Jeżeli tworząc fw piszesz w nim jednocześnie własną aplikację, to zakopiesz się szybciej niż myślisz.

Istnieje wiele fw dostosowanych rozmiarowo i architektonicznie do różnych potrzeb. Symfony, Laravel, Lumen. To, że któregoś z nich nie ogarniasz to nie powód żeby tworzyć swój. Trzeba je potraktować jako narzędzie i tyle. Ludzie którzy tworzyli te paczki kodu mają bardzo dużo doświadczenia. Na ich rozwiązaniach powstawały dziesiątki tysięcy projektów i platform. Rozwiązali oni bardzo dużo problemów, otestowali swój kod oraz co najważniejsze łatali i wciąż łatają luki bezpieczeństwa.
komentarz 30 stycznia 2020 przez michal_php Stary wyjadacz (13,700 p.)
powiem tak jeśli chodzi o framework np.: Symfony - to to jest mój ulubiony framework w ,którym mi się bardzo dobrze pracuje. Natomiast Laravel - coś mi nie wchodzi. A z kolei Lumen - jeszcze nie próbowałem.   

I mam takie pytanie jak jesteśmy przy frameworkach. Jak według Ciebie lepiej jest zbudować platformę api. W symofny wykorzystując platformę api czy Symfony , ale budować własną platformę api (chodzi mi obundle api). Czy lepiej jest wykorzystać Lumen ?

A pytanie powstało ponieważ poczułem potrzeba stworzenia coś własnego od zera.
komentarz 30 stycznia 2020 przez Ehlert Ekspert (212,670 p.)
Lumen do mniejszych rzeczy.

Z Symfony Api Platform szczerze mówiąc nie korzystałem, ale widziałem że całkiem dużo można tam zdziałać.

Wszystkie komercyjne projekty jakie dotąd robiłem były oparte na FosRestBundle.

Jak będziesz marnować czas na review pomiędzy jednym a drugim rozwiązaniem to w końcu znowu jesień przyjdzie. Wybierz pierwsze lepsze z tych dwóch i zacznij pisać.
komentarz 30 stycznia 2020 przez michal_php Stary wyjadacz (13,700 p.)
FosRestBundle -  to jest bundl dla symfony do budowy własne platformy api ?
komentarz 30 stycznia 2020 przez Ehlert Ekspert (212,670 p.)

platformy api 

Nie wiem co to znaczy. Api to api. Api Platform to framework automatyzujący budowę REST API. FosRestBundle to bundle Symfony ułatwiający budowanie api.

komentarz 31 stycznia 2020 przez antyprogramista Bywalec (2,120 p.)
mysle, ze warto patrzec na takie narzedzie jak przykladowo robi to Swagger (openapi), gdzie genereujemy sobie SDK przy okazji.

To co mi sie nie podoba, to potrzeba tworzenia dokumentacji w formacie narzuconym przez standard openapi,

Lepiej od strony progrmaisty wykorzytsac fakt typowania i wiele spraw zautomatyzowac.

Przykladowo FastApi dla pythona bardzo ladnie to robi, przy polaczeniu z baza danych w kilkanascie linijek budujesz aplikacje, ktora ma dokumentacji API i baze danych, nawet kupilem w tym celu domene. Bo kiedys chce miec taka zabawke, ktora mi wygeneruje API, by podpiac 2 fragmenty kodu roznych aplikacji i sie komunikowac na bazie modeli danych, bez potrzeby myslenia o innych warstwach.

Dla mnie to dane sa kluczem a nie framework czy biblioteka, dlatego wolabym nie myslec przez pryzmat narzedzi o tym a przez pryzmat danych jakie chce wymieniac a to jest niezalezne w kazdej aplikacji, kwestia wygenerowania kodu SDK.

Tak wyobrazam sobie podejscie do budowy rozwiazania dla API.
+1 głos
odpowiedź 30 stycznia 2020 przez antyprogramista Bywalec (2,120 p.)
edycja 30 stycznia 2020 przez antyprogramista

Super, chetnie pomoge.

Tworze biblioteki dla PHP opensource, wiec jesli dzialasz na github/bitbucket daj znac na PW

 

Tak jak kolega @Ehlert wspomnial moze to wiazac sie z wieloma przeszkodami w implementacji w roznych projektach, ale to juz samemu mozna przepracowac.

Mam odnosnie takiego frameworka kilka pomyslow, bo sam sie wczesniej przymierzalem.

Na co dzien jestem daleki od tworzenia frameworkow, wystarczy nam ich a brakuje nam bibliotek do szybkiego klejenia roznych rozwiazan.

Moje propozycje na dzis to:

+ uproszeczenie walidacji i komunikacji poprzez wyrzucenie routingu do poziomu klas

+ Exception wyrzuci za kazdym razem, jak bedzie blad, i framework bedzie bazowal na obsludze nie routingu a mapowaniu requestow przez Exceptions

+ Bo kazda operacja, zle obsluzona powinna byc automatycznie logowana

Dodatkowo sam sposob osblugi danych wejsciowych i wyjsciowych z parametrow mozna by od razu ladowac do objektow, w czym moze pomoc jedna z moich otwartych  bibliotek do obslugi kolekcji (tworzenie, dodawanie, usuwanie, filtrowanie, konwertowanie)

 

// Struktura 

Transaction: Client/Server
.Request
..Url /Resource
...Method /Command
....Data Params/Blob
.....Exception

// Client side
// Request, przyklad wysylania:

try{
  new Request(
    new Url(),
    new Method()
    new Data()
  );
} catch() {
  echo 'Problem';
}

// Server side
// Response, przyklad odbierania:
// inicjuje obiekty z zapytania przychodzacego do serwera

// GET /user/login

use /Server/Response;

class UserLogin{

   public function __construct(/Server/Method $method, /Server/Data $data)
     // Co to za metoda?
    $method->getName();

     // jak pobrac nazwe usera do logowania?
     $data->getPost()->getUsername()   
   }

  ...
}


// autoload laduje pliki
function __autoload($classname) {
    $filename = "./". $classname .".php";
    include_once($filename);
}



Reasumujac, dzialajmy!

w koncu na bledach sie uczymy kazdego dnia,

Co do kodu mysle ze mozna stworzyc wersje jednoplikowa dla klienta, bo kod jest prosty a kazdy kto potrzebuje prostego rozwiazania nie bedzie musial nawet bawic sie w ladowanie paczek, aby tylko zrobic jakiegos Requesta.

Server powinien juz byc wersja composer-owa

komentarz 30 stycznia 2020 przez Comandeer Guru (600,810 p.)

A dlaczego klient ma nie być composerowy? To, że jest w jednym pliku, nic nie zmienia (chociaż brzmi to trochę, jakby mógł łamać S z SOLID). Dodatkowo nie do końca wiem, po co frameworkowi klient – brzmi jakby to miał być framework do tworzenia typowych HTTP/RESTful APIs.

Exception wyrzuci za kazdym razem, jak bedzie blad, i framework bedzie bazowal na obsludze nie routingu a mapowaniu requestow przez Exceptions

Nie bardzo rozumiem – mógłbyś rozwinąć?

Nie wiem też, czy jest sens rozbijać request na osobne parametry ($method i $data). No i metoda HTTP jako osobna klasa? Brzmi jak przeinżynierowanie.

Dodatkowo __autoload od dawna nie jest już zalecany → https://www.php.net/manual/en/function.spl-autoload-register.php 

komentarz 30 stycznia 2020 przez antyprogramista Bywalec (2,120 p.)

Dziekuje za uwagi, na co dzien nie tworze frameworkow, dlatego nawet nie zagladam do autoloada, masz racje, spl_autoload_register.

Co do rozbijania Request'a chodzi o dostep do kazdego obiektu, aby zyskac Single Responsibility oraz DI, by nie tworzyc duplikatatow potem w dalszej czesci projektu w zaleznosci od uzycia.

 

Dodatkowo nie do końca wiem, po co frameworkowi klient – brzmi jakby to miał być framework do tworzenia typowych HTTP/RESTful APIs.

Klient moze byc uzyty w wielu roznych projektach, gdzie potrzebny jest dostep do jakiegos API.

Server moze byc czyms dzialajacym w oparciu o modele z Client'a

 

framework do tworzenia typowych HTTP/RESTful APIs.

Racja, nie myslalem o czyms innym, na poczatek to wystarczy

 

A dlaczego klient ma nie być composerowy

Moze byc w wersji podstawowej a zebrany do piku w wersji minimalnej, zeby po prostu skopiowac sam plik i uzyc, bo inaczej nie widze sensu robienia frameworka.

 

Moja filozofia dzialania jest taka, aby tworzyc male uzyteczne narzedzia typu kombinerki, male wjednofunkcyjne, ale dzialajace w roznych warunkach, inni wola wielofunkcyjne maszyny, ale wtedy potrzeba troche czasu na skonfiugorwania, wiec w przypadku zdefiniowanego uzycia latwiej zachowac spojnosc i nie ponosic kosztow czegos czego sie nie przewidzialo.

komentarz 30 stycznia 2020 przez Comandeer Guru (600,810 p.)

Moze byc w wersji podstawowej a zebrany do piku w wersji minimalnej, zeby po prostu skopiowac sam plik i uzyc

Ale po co ktoś miałby kopiować plik, skoro to np. uniemożliwia następnie łatwe zaktualizowanie tej zależności? Zresztą w takim podejściu starczy mieć wersję composerową na GH i ktoś sobie skopiuje bezpośrednio stamtąd.

Co do rozbijania Request'a chodzi o dostep do kazdego obiektu, aby zyskac Single Responsibility oraz DI, by nie tworzyc duplikatatow potem w dalszej czesci projektu w zaleznosci od uzycia. 

SRP nie polega na dzieleniu wszystkiego na najmniejsze niepodzielne części. To tak jakby wyciągnąć silnik z samochodu i twierdzić, że przedstawia jakaś wartość sam w sobie. No nie, on działa dopiero po włożeniu do całego samochodu. Tak samo jest z żądaniem – wyjęcie metody z niego nie ma sensu, bo sama metoda jest całkowicie bezwartościowa. Request jako całość spełnia SRP, bo zajmuje się tylko jedną rzeczą – żądaniem HTTP.

Zresztą w przypadku DI też sensowniej mieć cały obiekt Request, żeby niepotrzebnie nie tworzyć miliarda parametrów. 

komentarz 30 stycznia 2020 przez antyprogramista Bywalec (2,120 p.)
edycja 30 stycznia 2020 przez antyprogramista

Dziekuje za uwagi, 

W zasadzie mozna rozroznic 2 sprawy:

Client dla obslugi API, to po prostu Bilbioteka, wiec biblioteka moze miec postac paczki do aktualizacji bazujaca na composer-rze.

Client moze byc tez w skrajnosci jednym plikiem do wlaczenia np dla wysylania e-maili z landing page, albo robienia requestu do platnosci.

 

Po stronie serwera mozna pokusic sie o cos w formie frameworka, z u wagi na potrzebe obslugi Requestow, ale to moze tez robic slimframework.

http://www.slimframework.com/

 

To na razie szkic, ale:

class Url jest niezalezna, podobnie Data/Params,

 

 

SRP nie polega na dzieleniu wszystkiego na najmniejsze niepodzielne części.

Silnik moze byc uzyty do napedzania roznych srodkow transportu w skrajnosci nawet do zasilania agregatu pradotworczego.

Dlatego silnik jest autonomiczna czescia i nie nalezy go kojarzyc z karoseria jako calosc.

Auto to aplikacja, definiowalan, ktora potrzebuje dedykowanych rozwiazan, po to sa biblioteki i frameworki, aby pomoc osiagnac cel.

Gdy klasy sa dzielone na male czesci, latwiej o reuzycie.

To co mnie czesto drazni to podrecznikowe adaptowanie swiata do sztucznych ram.

Patterns, maja nam pomagac, a nie zamykac oczy na rzeczywistosc.

Program ma odzwierciedlac model rzeczywistosci a nie modelowac rzeczywistosc, zamykajac w laboratorium.

 

Odnosnie tworzenia prostych stron demo, dla testow, doszedlem do wniosku, ze bede uzywal kazdej funkcji w osobnym pliku js., mam srodowisko lokalne do uruchamiania prototypow, gdzie uzywam mojego autorskiego rozwiazania do tego i tylko laduje liste plikow, zamiast tworzyc zlozone klasy.

To dziala lepiej, moge lepiej wykorzystac juz napisany kod.

 

view-source:http://js.apiunit.com/

 loader.cacheOff().js([
        "//js.apiunit.com/e.js",
        "//js.apiunit.com/formToObject.min.js",
        "//js.apiunit.com/response.js",
        "//js.apiunit.com/rest.js",
        "//js.apiunit.com/include.js",
        "//js.apiunit.com/listener.js",
        "//js.apiunit.com/router.js",
        "//js.apiunit.com/apiunit.js",
        "//js.apiunit.com/message.js",
        "//js.apiunit.com/rest-form.js"
    ]);

 

Nie boje sie eksperymentow, dlatego pisze o tym otwarcie.

Dziekuje, ze sie nie zgadasz, bo tez ciagle sie ucze i jestem otwarty na krytyke.

Moze czasem za duzo chce na raz zrobic, ale tez nie chce czegos robic, zeby czekalo na lepsze czasy i jeszcze wszytskim to wciskac jak najlepsze rozwiazanie, dlatego male proste do zrozumienia rozwiazania sa zawsze mile widziane.

Ktos uzywa laravela, symfony juz nie musi szukac, ale z drugiej czasem potrzeba czegos zeby potestowac i wtedy pojawiam sie ja z moja skrzynka narzedziowa i daje szanse na szybkie stworzenie rozwiazania, by w ogole upewnic sie czy o to chodzilo a nie budowac aplikacji w oparciu o znany framework, bo 'tak trzeba'

Czas to pieniadz, zwalszcza przy prototypowaniu, ale na co dzien uzywam laravel'a.

 

Zresztą w przypadku DI też sensowniej mieć cały obiekt Request, żeby niepotrzebnie nie tworzyć miliarda parametrów. 

Zastanawialem sie nad tym i modelujac swiat zewnetrzny kazda wartosc przynalezy do jednostki.

Pokusilem sie nawet o zrobienie takiej biblioteki, tylk oproblem polega na tym, ze PHP nie obsluguje natywnie kolekcji obiektow i do tego tez musialem zrobic biblioteke.

Wiec finalnie mam na to rozwiazanie:

Tworze obiekt klasy Collection lub jego implementacje, np UnitCollection

Wrzucam atrybuty do Kolkecji, ktore musza spelniac warunek typu klasy: w tym wypadku Unit

dodaje atrybuty Unit do kolekcji i nimi zarzadzam.

 

Jednak to nie zastepuje atrybutow klasy a jedynie pozwala na zarzadzanie obiektami np w tabeli, dla filtrowanie, etc

Dlatego poszedlem o krok dalej i postanowilem tworzyc male klasy, aby ilosc atrybutow byla minimalna a najlepiej ustandaryzowana, tworzac srodowisko gdzie ma sie ustandaryzwoane typy/jednostki i sie tylko ich uzywa. lepiej po prostu stworzyc strukture, malych obiektow niz jeden duzy, ktorego sie nigdy nie reuzyje.

 

1
komentarz 30 stycznia 2020 przez Comandeer Guru (600,810 p.)

Z całym szacunkiem, ale to brzmi bez sensu. Czemu rozdzielasz coś, co stanowi zwartą całość (żądanie to metoda, URL, nagłówki i ciało – żadna z tych części autonomicznie nie ma sensu), ale i tak następnie robisz z tego kolekcję? Taka kolekcja rzeczy związanych z konkretnym obiektem jest de facto zaprzeczeniem idei OOP. Bo tak naprawdę robisz tablicę opatuloną w obiekt tylko po to, by nie zrobić jednego obiektu z sensownymi metodami i własnościami.

Co więcej, Request można używać w obrębie całego systemu, a nawet między systemami. Ba, jest nawet standardowy format dla żądań i odpowiedzi HTTP – co oznacza, że jest spora szansa, że jeśli Twój framework używa tego formatu, jesteś w stanie używać tych klas nie tylko w swoim projekcie, ale także każdym innym przestrzegającym zasad PSR.

Gdy klasy sa dzielone na male czesci, latwiej o reuzycie.

Tak, ale metody HTTP nie użyjesz ponownie bez reszty żądania. A jeśli użyjesz, to czym ta klasa się różni od stringa?

[…] bede uzywal kazdej funkcji w osobnym pliku js., mam srodowisko lokalne do uruchamiania prototypow, gdzie uzywam mojego autorskiego rozwiazania do tego i tylko laduje liste plikow, zamiast tworzyc zlozone klasy

Ale to nie ma nic wspólnego z OOP. Poza tym funkcje dzieli się inaczej niż klasy z prostej przyczyny: każda funkcja jest niezależnym bytem, wykonującym jedną, konkretną rzecz. W przypadku klas klasa może mieć więcej niż jedną metodę i więcej niż jedną własność, jeśli ma to sens (w sensie: nie da się wydzielić tego w taki sposób, by podział nie był sztuczny). Zresztą fajnie to widać na przykładzie lodasha: tam też jest taki podział na funkcje – ale właśnie dlatego, że każda funkcja robi co innego.

[…] PHP nie obsluguje natywnie kolekcji obiektow […]

Co rozumiesz pod "kolekcja"? Bo np. jest ArrayObject

komentarz 30 stycznia 2020 przez antyprogramista Bywalec (2,120 p.)
edycja 30 stycznia 2020 przez antyprogramista

Czemu rozdzielasz coś, co stanowi zwartą całość (żądanie to metoda, URL, nagłówki i ciało – żadna z tych części autonomicznie nie ma sensu), ale i tak następnie robisz z tego kolekcję? Taka kolekcja rzeczy związanych z konkretnym obiektem jest de facto zaprzeczeniem idei OOP. Bo tak naprawdę robisz tablicę opatuloną w obiekt tylko po to, by nie zrobić jednego obiektu z sensownymi metodami i własnościami.

Masz racje co do ogolu, jednak nie szukam alternatywy dla tworzenia obiektow a do metody ich organizacji w kodzie i bazie danych.

Dla mnie kod jest tylko celem do realizacji uslugi, wiec hardkodowanie odpada, stad moja droga do tworzenia malych autonomicznych uslug w kodzie, ktory jest otwarty na customizacje poprzez dane z bazy danych.

"Jeśli Twój framework używa tego formatu, jesteś w stanie używać tych klas nie tylko w swoim projekcie, ale także każdym innym przestrzegającym zasad PSR."

Zgadzam sie, po prostu czasem warto zrobic cos co czegos nauczy, bibliotek jest masa, tylko tutaj chodzi o maszynke do komunikacji, ktora by bylo ostro typowana i dlatego mam chec na zrobienie malej biblioteczki.

Ale to nie ma nic wspólnego z OOP. Poza tym funkcje dzieli się inaczej niż klasy z prostej przyczyny: każda funkcja jest niezależnym bytem, wykonującym jedną, konkretną rzecz.

To prawda, tylko pokazuje jak mozna podejsc do rozwiazania nuzacych problemow dnia codziennego przy prototypowaniu.

Co rozumiesz pod "kolekcja"? Bo np. jest ArrayObject

Rozumiem mozliwosc uzywania obiektu, ktory bedzie mi dawal dostep do okreslonych obiektow okreslonego typu a nie zbieraniny elementow tablicy, czyli z ograniczeniem typu.

Wiem, ze latwo sie bierze z polki kolejny pomysl tworcow PHP, ale tez trzeba brac pod uwage ograniczenia i problemy wynikajace z tego.

 

 

Dzieki za uwagi, ponizej link do projektu:

https://github.com/phunc-org/Phunc/blob/master/src/Collection.php

 

Przyklad deklaracji

class MinutesCollection extends \Phunc\Collection implements \Phunc\FillFromArrayInterface
{
    /** @var \App\WorkingTime\Minutes */
    protected $instance;

    /**
     * Default Value
     */
    public function __construct()
    {
        $this->setInstance(new Minutes());
    }

    /**
     * @param $key
     * @return \App\WorkingTime\Minutes
     */
    public function getByKey($key)
    {
        return $this->getCollection()[$key];
    }

    /**
     * @param \Phunc\CollectionInstanceInterface $instance
     * @param null $key
     * @return $this
     */
    public function add(\Phunc\CollectionInstanceInterface $instance, $key = null)
    {
        if (empty($key)) {
            $key = $instance->getDateRange()->getName();
        }
        parent::add($instance, $key);
        return $this;
    }

 

Chodzi o mozliwosc filtrowania jak tablicy ale z zachowaniem Strong Typing

$workingMonth = new Minutes();

$workingMonth->setName($monthKey->getLocalMonth());
$workingMonth->setDateRange($dateRange);

$monthCollection = new \App\WorkingTime\MinutesCollection(); 
$monthCollection->add($workingMonth, $monthKey->getKey());

Podobne pytania

+1 głos
1 odpowiedź 462 wizyt
+3 głosów
4 odpowiedzi 468 wizyt
pytanie zadane 20 kwietnia 2016 w Nasze projekty przez jpacanowski VIP (101,940 p.)
0 głosów
1 odpowiedź 428 wizyt
pytanie zadane 15 września 2018 w PHP przez Maikel11 Początkujący (470 p.)

92,555 zapytań

141,403 odpowiedzi

319,560 komentarzy

61,940 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...