Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP] Jak stosować interfejsy?
eerie
post 3.03.2025, 10:37:49
Post #1





Grupa: Zarejestrowani
Postów: 109
Pomógł: 0
Dołączył: 3.08.2017

Ostrzeżenie: (0%)
-----


Nie czuję do końca stosowania interfejsów w mojej aplikacji... Poniżej podaję, jak to obecnie wygląda. Może tak zostać bądź coś poprawić?

Utworzyłem interfejs Mysqli dla klasy Database:

Kod
<?php

declare(strict_types=1);

namespace App\Core;

interface Mysqli
{
    public function dbConnect(): void;
    public function dbClose(): void;
    public function dbQuery(string $query): mixed;
    public function dbFetchArray(mixed $result): array|null|false;
    public function dbNumberRows(mixed $result): int;
    public function dbAffectedRows(): int;
    public function dbInsertId(): int;
    public function dbStartTransaction(): bool;
    public function dbCommit(): bool;
    public function dbRollback(): bool;
}


Interfejs Mail jest implementowany przez Email:

Kod
<?php

declare(strict_types=1);

namespace App\Core;

interface Mail
{
    public function sendEmail(
        string $serverName,
        string $emailFrom,
        string $emailTo,
        string $subject,
        string $message
    ): bool;
}


Oraz interfejs Validator jest implementowany przez abstrakcyjne klasy Code, Error i Message, które są potem rorszerzane przez podklasy odpowiedziane za validację (np. MainPageValidator) danych z formularzy czy api:

Kod
<?php

declare(strict_types=1);

namespace App\Core;

interface Validator
{
    public function isValid(): bool;
}


Wypadałoby dodać jeszcze inne interfejsy dla moich klas tutaj? Trochę nie czuję, gdzie powinienem stosować interfejsy...
Go to the top of the page
+Quote Post
nospor
post 3.03.2025, 10:55:06
Post #2





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




1) Napisales ktore klasy implementuja ktore interfejsy, ale wchodzac w ich kod, nie widze zadnej implementacji.
2) Po co ten przedrostek "db" ?
3)
public function dbQuery(string $query): mixed
{
return mysqli_query($this->mysqlLink, $query);
}

Ta metoda powinna zwracac bool a nie zasob mysqli. Po to sie robi interfejsy, by klasa byla uniwersalna a nie ty wymuszasz na nas znajmosc faktu iz zwraca jakis zasob mysqli. Mnie, jako uzytkownika tej klasy guzik obchodzic powinno czy to mysqli, czy mysql czy pdo. wykonuje query, a potem chce pobrac rekordy z tego query. wiec np. ten zasob powinien byc trzymany w klasie.
Z drugiej strony, moze byc faktycznie sytuacja, gdzie na raz wykonujesz dwa zapytania, np petla w petli i wtedy ten zasob jest potrzebny. No ale to mozna rozwiazac inaczej, np. klasa nie zwraca zasob ale number zasobu, i zasoby nadal so trzymany w klasie w tablicy, albo jak chcesz zwracac zasob, to moze warto tez zrobic to na interfejscie DBResource
4) interface Mysqli
Nie, masz zrobic interface DB, a potem klase MysqlI ktore go implementuje. Interfacy sluza by mowic o czym ogolnie, a nie robisz interface pod dana klase od razu


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

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
eerie
post 3.03.2025, 17:35:15
Post #3





Grupa: Zarejestrowani
Postów: 109
Pomógł: 0
Dołączył: 3.08.2017

Ostrzeżenie: (0%)
-----


Poprawiłem (szczegóły tutaj):

Kod
<?php

declare(strict_types=1);

namespace App\Core;

interface Database
{
    public function connect(): void;
    public function close(): void;
    public function query(string $query): bool;
    public function result(): mixed;
    public function fetchArray(mixed $result): array|null|false;
    public function numberRows(mixed $result): int;
    public function affectedRows(): int;
    public function insertId(): int;
    public function startTransaction(): bool;
    public function commit(): bool;
    public function rollback(): bool;
}


Kod
<?php

declare(strict_types=1);

namespace App\Core;

class Mysqli implements Database
{
    [...]

    public function query(string $query): bool
    {
        $this->mysqlResult = mysqli_query($this->mysqlLink, $query);

        return (bool) $this->mysqlResult;
    }

    public function result(): mixed
    {
        return $this->mysqlResult;
    }

    [...]
}


Kod
abstract class Controller
{
    [...]

    public function setManager(string $name = 'Mysqli'): void
    {
        if (!isset($this->manager[$name])) {
            $this->database[$name] = new $name($name);
            $this->manager[$name] = new Manager($this->database[$name]);

            $this->database[$name]->connect();
        }
    }

    public function getManager(string $name = 'Mysqli'): Manager
    {
        $this->setManager($name);

        return $this->manager[$name];
    }

    [...]


Ten post edytował eerie 3.03.2025, 17:40:26
Go to the top of the page
+Quote Post
nospor
post 3.03.2025, 18:00:06
Post #4





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Odnosnie tego co zwraca query() to nie poprawione to jest. ok, niby zwracasz bool, ale inne zapytania jak fetch() nadal wymagaja tego resource, wiec nic sie nie zmienilo, wiec nie potrzebnie to trzymasz tez jako wlasciwosc w klasie bo trzymasz tylko jedno, jak masz kilka query to kazde zwroci inne resource.

Idea byla by metody ala fetch, nie musialy juz tego brac jako parametr, tylko by sobie braly z wlasciwosci klasy.

moze ja za bardzo kombinuje, ale ja osobiscie bym zrobil to teraz tak:
query niech zwraca to resource, w type mixed
zapisuj to tez we wlasciwosci klasy jak to robic,

zas metody ala fetch: user moze podac nam ten resource albo nie. Jak nie poda to fetch wezmiej ostatni zapisyny we wlasciowosci klasy.

Wtedy kod moze wyglada tak

$con->query('blabla');
$con->fetch()

Albo
$res - $con->query('blabla');
$con->fetch($res)


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

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
Loguss
post 3.03.2025, 21:51:02
Post #5





Grupa: Zarejestrowani
Postów: 1
Pomógł: 0
Dołączył: 3.03.2025

Ostrzeżenie: (0%)
-----


Cytat(nospor @ 3.03.2025, 18:00:06 ) *
Odnosnie tego co zwraca query() to nie poprawione to jest. ok, niby zwracasz bool, ale inne zapytania jak fetch() nadal wymagaja tego resource, wiec nic sie nie zmienilo, wiec nie potrzebnie to trzymasz tez jako wlasciwosc w klasie bo trzymasz tylko jedno, jak masz kilka query to kazde zwroci inne resource.

Idea byla by metody ala fetch, nie musialy juz tego brac jako parametr, tylko by sobie braly z wlasciwosci klasy.

moze ja za bardzo kombinuje, ale ja osobiscie bym zrobil to teraz tak:
query niech zwraca to resource, w type mixed
zapisuj to tez we wlasciwosci klasy jak to robic,

zas metody ala fetch: user moze podac nam ten resource albo nie. Jak nie poda to fetch wezmiej ostatni zapisyny we wlasciowosci klasy.

Wtedy kod moze wyglada tak

$con->query('blabla');
$con->fetch()

Albo
$res - $con->query('blabla');
$con->fetch($res)

trochę za bardzo kombinujesz, ale pomysł jest sensowny. Jeśli query() będzie zwracać resource i zapisywać go w właściwości klasy, metody jak fetch() będą mogły działać bez konieczności przekazywania parametru. Takie podejście uprości kod i sprawi, że będzie bardziej elastyczny. Można to zrobić na dwa sposoby, jak zaproponowałeś, czyli albo z automatycznym pobieraniem ostatniego zapisanego resource, albo z opcją przekazania własnego.
Go to the top of the page
+Quote Post
eerie
post 3.03.2025, 23:53:05
Post #6





Grupa: Zarejestrowani
Postów: 109
Pomógł: 0
Dołączył: 3.08.2017

Ostrzeżenie: (0%)
-----


Poprawione: https://github.com/EEQSOFT/framework.eeq/tree/main/src

Teraz powinno być dobrze... smile.gif
Go to the top of the page
+Quote Post
nospor
post 4.03.2025, 10:33:46
Post #7





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Cytat
trochę za bardzo kombinujesz, ale pomysł jest sensowny

No niestety czasami tak mam. Raz wychodzi na dobre, raz niekoniecznie wink.gif

Cytat
Teraz powinno być dobrze..

prawie wink.gif

popraw to
public function connect(): void
{
$this->mysqlLink = @mysqli_connect(
$this->mysqlHost,
$this->mysqlUser,
$this->mysqlPassword,
'',
$this->mysqlPort
) or die('Could not connect to MySQL');

mysqli_select_db($this->mysqlLink, $this->mysqlDatabase)
or die('Could not choose the database');

mysqli_set_charset($this->mysqlLink, $this->mysqlNames);
}

wywal te malpe or wywal te die(). zadna klasa nie powinna konczyc w tak drastyczny sposob aplikacji. Zamiast tego rzucaj wyjatkiem i to niech aplikacja sie martwi co dalej a nie klasa


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

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
viking
post 4.03.2025, 10:47:59
Post #8





Grupa: Zarejestrowani
Postów: 6 376
Pomógł: 1116
Dołączył: 30.08.2006

Ostrzeżenie: (0%)
-----


A nie lepiej po prostu przejść na pdo, albo chociaż obiektowe mysqli?


--------------------
Go to the top of the page
+Quote Post
eerie
post 4.03.2025, 16:29:17
Post #9





Grupa: Zarejestrowani
Postów: 109
Pomógł: 0
Dołączył: 3.08.2017

Ostrzeżenie: (0%)
-----


Cytat
A nie lepiej po prostu przejść na pdo, albo chociaż obiektowe mysqli?

Pewnie byłoby lepiej, ale na razie nie chce mi się zmieniać... wink.gif

Cytat
wywal te malpe or wywal te die(). zadna klasa nie powinna konczyc w tak drastyczny sposob aplikacji. Zamiast tego rzucaj wyjatkiem i to niech aplikacja sie martwi co dalej a nie klasa

Po usunięciu małpy wywala ostrzeżenie, więc zostawiłem. Zamiast die() dałem "throw new AppException()" (Mysqli). Wyjątek obsłużyłem w głównym pliku, gdzie tworzę obiekt kontrolera (index.php).
Go to the top of the page
+Quote Post
nospor
post 4.03.2025, 17:01:21
Post #10





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Cytat
Po usunięciu małpy wywala ostrzeżenie, więc zostawiłem.

Jakie ostrzezenie? Ostrzezenia sie naprawia a nie wylacza ich wyswietlanie

Cytat
Wyjątek obsłużyłem w głównym pliku, gdzie tworzę obiekt kontrolera (index.php).

Milion razy duplikujesz tam try catch... zrob jeden a nie w kazdym case osobno.
No i appka powinna przekierowac wowczas na strone z bledem a nie echo "nie dziala"; exit. No tak sie nie robi wink.gif


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

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
eerie
post 4.03.2025, 18:49:06
Post #11





Grupa: Zarejestrowani
Postów: 109
Pomógł: 0
Dołączył: 3.08.2017

Ostrzeżenie: (0%)
-----


Cytat
Jakie ostrzezenie? Ostrzezenia sie naprawia a nie wylacza ich wyswietlanie

Po włączeniu samego php, bez bazy danych, wyświetla mi bez małpy takie coś:

Cytat
Warning: mysqli_connect(): (HY000/2002): Nie można nawiązać połączenia, ponieważ komputer docelowy aktywnie go odmawia in C:\Work\Domain\framework.eeq\src\Core\Mysqli.php on line 38
Could not connect to MySQL

Moim zdaniem nic na to nie poradzę, a info niepotrzebnie się dubluje... smile.gif

Cytat
Milion razy duplikujesz tam try catch... zrob jeden a nie w kazdym case osobno.

Pewnie mi się znowu dostanie, ale zrobiłem to w głównym public dla głównego require() [index.php].

Cytat
No i appka powinna przekierowac wowczas na strone z bledem a nie echo "nie dziala"; exit. No tak sie nie robi wink.gif

Ja tę app'kę traktuję na razie edukacyjnie. Jak będzie sens, to kiedyś to przerobię bardziej profesjonalnie. wink.gif
Go to the top of the page
+Quote Post
nospor
post 6.03.2025, 07:44:13
Post #12





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Odnosnie bledu i malpy. Nie uzywaj malp. Zamiast tego napisz swoj wlasny error handler i zamiast bledy wyswietlac, to zapisuj do np. pliku

https://www.php.net/manual/en/function.set-error-handler.php


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

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
eerie
post 10.03.2025, 17:20:32
Post #13





Grupa: Zarejestrowani
Postów: 109
Pomógł: 0
Dołączył: 3.08.2017

Ostrzeżenie: (0%)
-----


Dzięki za podpowiedź. Miałem dzisiaj trochę wolnego czasu i zastosowałem to rozwiązanie. Usunąłem małpę i zapisuję błędy do pliku. Wyświetlam też komunikat użytkownikowi, że cos poszło nie tak, na oddzielnej stronie, jak sugerowałeś. smile.gif
Go to the top of the page
+Quote Post
nospor
post 10.03.2025, 17:24:53
Post #14





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Nie
print_r($logData, 1);

a
print_r($logData, true);

Drugi argument to BOOL a nie INT. Ja wiem, ze php to mapuje, ale jak kiedys php wkoncu wlaczy super strict mode, to sie zdziwisz wink.gif

No i to co w error.php to tez to powinna byc klasa a nie funkcje. Nie idz na latwizne wink.gif


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

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
eerie
post 10.03.2025, 20:21:55
Post #15





Grupa: Zarejestrowani
Postów: 109
Pomógł: 0
Dołączył: 3.08.2017

Ostrzeżenie: (0%)
-----


Ok. Dzięki za uwagi. Poprawione. smile.gif
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 19.05.2025 - 06:24