Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [php] Stałe w programowaniu obiektowym
Forum PHP.pl > Forum > Przedszkole
eerie
Witam

Czy używanie stałych w programowaniu obiektowym pod php7 to dobra praktyka? Pytam, bo gdy programowaliśmy w języku Java na strudiach, to nie pamiętam, abyśmy używali stałych. Poniżej podaję kod przykładowej klasy konfiguracyjnej mojej aplikacji. Prosiłbym o sugestie, czy może mieć taki kształt? Czy zamiast zmiennych nie powinienem wprowadzić stałych? Dopiero uczę się php7 i nie mam pewności, czy stałe w klasie konfiguracyjnej to dobry pomysł...

https://github.com/eerie79/framework2_svn/b...Core/Config.php

Pozdrawiam
Robert
nospor
Generalnie uzywa sie stalych w OOP jak najbardziej.
Nie zmienia to faktu, ze tak jak ty to zrobiles, to jest zrobione zle. Przeciez teraz udostepniasz nam swoja konfiguracje w repo. A co gdy ja bede chcial skorzystac z twojej klasy i zmienic konfiguracje na swoja? Przeciez nadpisze twoje dane.

Konfiguracja powinna lezec w oddzielnym pliku. W symfony jest to np. plik .yml. Ale rownei dobrze moze to byc .ini, czy nawet plik php, ktory zwroci dane. Wazne jednak jest, by ten plik nie byl w repozytorium. Z reguly to sie robi tak, ze tworzysz plik .dist, ktory sluzy jako przyklad konfiguracji, a kazdy lokalnie robi swoja kopie tego pliku i tam ustawia swoj config. Rzecz jasna ten lokalny plik jest w .gitignore i pozamiatane.

Klasa config moze sobie istniec jak najbardziej. Klasa ta bedzie zczytywac dane z tego pliku z konfiguracja
darko
To, co nazywasz stałymi, to w rzeczywistości chronione pola statyczne klasy, do definiowania stałych używamy słowa kluczowego CONST:

  1. class Config
  2. {
  3. CONST MYSQL_HOST = 'localhost';
krzywy5830
Cytat(darko @ 12.01.2018, 11:15:10 ) *
To, co nazywasz stałymi, to w rzeczywistości chronione pola statyczne klasy, do definiowania stałych używamy słowa kluczowego CONST:

  1. class Config
  2. {
  3. CONST MYSQL_HOST = 'localhost';


Dodam, że jeśli chcesz żeby stała była protected to możesz to zrobić jeśli masz wersję PHP 7.1:

  1. class Config
  2. {
  3. protected CONST MYSQL_HOST = 'localhost';


No i nospor ma rację, taka konfiguracja powinna być w oddzielnym pliku. Ja zwykle tworzę plik o nazwie np. database.php z taką zawartością:

  1. <?php
  2. return
  3. [
  4. 'host' => 'localhost',
  5. 'port' => '3306'
  6. 'db_name' => 'nazwa bazy',
  7. 'db_user' => 'użytkownik',
  8. 'db_password' => 'hasło'
  9. ];


Potem w tej klasie Config możesz zrobić:

  1. class Config
  2. {
  3. public function __construct()
  4. {
  5. $database = require('database.php');
  6. echo($database['db_user']); //wyświetli "użytkownik", oczywiście nie dawaj tego echo, to tylko przykład żeby ci pokazać jak to działa
  7. }
  8. }


No i jeszcze to:

  1. public static function getServerDomain(): string
  2. {
  3. return str_replace('www.', '', $_SERVER['SERVER_NAME']);
  4. }
  5.  
  6. public static function getServerEmail(): string
  7. {
  8. return 'kontakt@' . str_replace('www.', '', $_SERVER['SERVER_NAME']);
  9. }


Po co stworzyłeś metodę getServerDomain() skoro potem jej nie używasz? Możesz to zamienić na:

  1. public static function getServerDomain(): string
  2. {
  3. return str_replace('www.', '', $_SERVER['SERVER_NAME']);
  4. }
  5.  
  6. public static function getServerEmail(): string
  7. {
  8. return 'kontakt@' . self::getServerDomain();
  9. }


Poza tym $administratorEmail czy $moderatorEmail przecież mogą się zmieniać. Warto to umieścić np. w bazie danych i cachować.
eerie
Dziekuję za pomoc. Tak to teraz wygląda po przerobieniu. Ma ktoś może uwagi, co jeszcze poprawić?

https://github.com/eerie79/framework2_svn/b...Core/Config.php

A tu jest autoloader, który wywołuje metodę init(). Dokładniej robi to ostatni jego warunek.

https://github.com/eerie79/framework2_svn/b...re/autoload.php

Może tak być? A czy nie powinno być, jak podałem poniżej, dla wszystkich autoloaderów w mojej aplikacji?

Kod
    ...

    if (file_exists($file)) {
        require_once($file);

        if (method_exists($class, 'init')) {
            $class::init();
        }
    }

    ...


Bo jeśli nie załaduje mi pliku z klasą, to chyba nie będzie widać, że taka metoda istnieje.

PS Mam takie przemyślenie... Teoretycznie require_once('nazwa_pliku.php'); może zostać użyte niezależnie od autoloadera wcześniej, więc chyba warunek na istnienie metody init() powinien być wykonany również niezaleźnie od sprawdzenia istnienia pliku $file. Czyli jest dobrze tak, jak podałem w repozytorium.
markuz
Korzystaj z autoloadera composera, a takie dane jak dostęp do MYSQL powinien być w zmiennych środowiskowych. Poczytaj o plikach .env.dist .env.
com
dodatkowo poczytaj wgl o PSR, w 2018 rok to jest wszędzie już wymagane. Własny autoloader nie ma sensu, tak jak wspomina kolega markuz, wykorzystaj composer.
Ale tak jak napisał krzywy5830
  1. $database = require('database.php');

co użył w konstruktorze tak również nie rób wink.gif to tylko dla demo było
krzywy5830
Cytat(com @ 14.01.2018, 15:53:27 ) *
Ale tak jak napisał krzywy5830
  1. $database = require('database.php');

co użył w konstruktorze tak również nie rób wink.gif to tylko dla demo było


Właściwie to co z tym jest nie tak? Nie do końca rozumiem dlaczego takie rzeczy jak dane do MySQL powinny być w zmiennych środowiskowych. Załóżmy, że korzystam z biblioteki vlucas/phpdotenv, w pliku .env oprócz danych do bazy są również inne rzeczy (np. microframework lumen zapisuje tam też domyślną strefę czasową oraz informację o tym czy aplikacja jest w trybie debugowania). Co w przypadku kiedy chciałbym zrobić instalator taki jak ma Wordpress czy fora phpBB? W instalatorze podaje dane do bazy, wszystko fajnie ale trzeba by kombinować z zapisaniem tych danych do pliku .env. A gdy stworzę sobie taki plik jak mówiłem (database.php) to wystarczy zrobić:

  1. file_put_contents('database.php', '<?php'.PHP_EOL.'return '.var_export(TABLICA Z DANYMI DO BAZY, true).';', LOCK_EX);
eerie
Przez pół roku uczyłem się programować we framework'u Symfony, potem i tak nikt nie chciał mnie zatrudnić. Dlatego na własne potrzeby napisałem bardzo prosty szkielet aplikacji, który wzorowałem na Symfony.

https://github.com/eerie79/framework2_svn

Dla mnie frameworki typu Symfony są jak strzelanie z armaty do mówki. Ile to ma klas... Ile to ma plików... A da się programować w PHP dużo prościej... Niby frameworki mają upraszczać, a tylko wszystko gmatwają.

Czytałem o PSR. Mój autoloader pochodzi z przykładu dla PSR-4.

https://github.com/php-fig/fig-standards/bl...der-examples.md

Instalowanie composera i używanie go jest dla mnie analogiczne do korzystania z frameworków. Można to zapisać w zmiennych środowiskowych, ale czy tak, jak pokazał kolega krzywy5830, nie jest prościej?
krzywy5830
Cytat(eerie @ 14.01.2018, 22:42:21 ) *
Przez pół roku uczyłem się programować we framework'u Symfony, potem i tak nikt nie chciał mnie zatrudnić. Dlatego na własne potrzeby napisałem bardzo prosty szkielet aplikacji, który wzorowałem na Symfony.

https://github.com/eerie79/framework2_svn

Dla mnie frameworki typu Symfony są jak strzelanie z armaty do mówki. Ile to ma klas... Ile to ma plików... A da się programować w PHP dużo prościej... Niby frameworki mają upraszczać, a tylko wszystko gmatwają.

Czytałem o PSR. Mój autoloader pochodzi z przykładu dla PSR-4.

https://github.com/php-fig/fig-standards/bl...der-examples.md

Instalowanie composera i używanie go jest dla mnie analogiczne do korzystania z frameworków. Można to zapisać w zmiennych środowiskowych, ale czy tak, jak pokazał kolega krzywy5830, nie jest prościej?


Też nie przepadam za takimi dużymi frameworkami jak Symfony, jednak uznałem, że pisanie własnego nie ma sensu. Za dużo czasu to pochłania. Myślę, że powinieneś zainteresować się microframeworkami jak Lumen, Slim czy Zend Expressive (chociaż ten nie do końca mi się podoba). Zawierają tylko podstawowe rzeczy, których się najczęściej używa (routing, obsługa requestów HTTP, kontener IoC), zachowują standardy PSR-7 i te inne, no i są szybkie i lekkie. A korzystanie z Composera to nie to samo co korzystanie z frameworków. A jeśli chodzi o moją metodę przechowywania danych do bazy to sam nie wiem czy jest to do końca prawidłowe. Sam jeszcze muszę się wiele nauczyć jeśli chodzi o dobre praktyki, dlatego proszę żeby ktoś wyjaśnił mi dlaczego to powinno być w zmiennych środowiskowych.
eerie
Mój przykład to w zasadzie nie jest własny framework. Raczej to szkielet przykładowej aplikacji. Stworzyłem go jako wzorzec, na którym opieram się programojąc w PHP.

PS Też dopiero uczę się programować... Sądzę jednak, że frameworki typu Symfony tylko gmatwają to, co jest bardzo proste, gdy się dobrze pozna temat od podstaw...
Pyton_000
@eerie nie chciałbym mieć przyjemności poprawiania projektów po Tobie. Zwłaszcza jeśli oparłbyś cokolwiek o ten swój "szablon".

Nie każdy framework nadaje się do wszystkiego. Owszem w większości da się zrobić wszystko. Używanie frameworka z dużą ilością domyślnie włączonych rzeczy do uzbrojenia API z 2 wndpointami mija się z celem.
Dla tego Trzeba umieć dostosować technologię do potrzeby, wiedzieć co jest na rynku, jak szybko coś działa. Lubisz Laravela? To użyjesz albo Laravela do projektu albo Lumen do czegoś szybkiego i małego.

Symfony tak samo. Lubisz? To bierz Symfony albo Silex (Silex btw kończy żywot bo na jego miejsce wskoczył Symfony Flex (4))

Trochę myślenia. Poza tym jak chcesz robić sobie szablon to zrób to jak człowiek. Użyj Composer, użyj małych paczek np. oddzielny routing, DI, Service Container, jakiś ORM/whatever, jakiś twig.... i masz gotowy szkielet na komponentach które wszyscy znają i używają. Nie masz problemu z błędami, lukami bezpieczeństwa. Era "jeste programmistom - muszem mieć swój frejmłork" się dawno skończyła.
darko
Cytat
armaty do mówki. Ile to ma klas... Ile to ma plików... A da się programować w PHP dużo prościej... Niby frameworki mają upraszczać, a tylko wszystko gmatwają.

Jest jeszcze coś takiego jak bezpieczeństwo i koszty utrzymania aplikacji. Nie zawsze pisanie od zera to dobry pomysł. Pomyśl kto będzie się później zagłębiał w Twój totalnie customowy tok myślenia i ile to Cię będzie kosztowało.
com
krzywy5830 odpowiedź dlaczego env masz w zasadzie w tej paczce co podlinkowałeś. Ale ja nie mówiłem o env. Odpowiadając na Twoje pytanie odnośnie tego co napisałem, to chodzi o to, że na sztywno wrzucasz zależności do pliku, który nigdy nie powinien się znaleźć w repo, a skoro tak to jak pobieram te paczkę to pierwsze co się stanie jak go nie utworze to rzuci mi błędem. Poza tym to niczym się nie różni jakbym wklepał na sztywno to w tej klasie. Jak już to powinieneś te database.php a w zasadzie jego zawartość do config wstrzyknąć po to mamy przecież DI.
krzywy5830
Cytat(com @ 16.01.2018, 19:43:41 ) *
Odpowiadając na Twoje pytanie odnośnie tego co napisałem, to chodzi o to, że na sztywno wrzucasz zależności do pliku, który nigdy nie powinien się znaleźć w repo


Pliku database.php przecież nie muszę umieszczać w repo.

Cytat(com @ 16.01.2018, 19:43:41 ) *
a skoro tak to jak pobieram te paczkę to pierwsze co się stanie jak go nie utworze to rzuci mi błędem.


Jak nie utworzysz pliku .env z odpowiednimi wpisami to też rzuci ci błędem.

Cytat(com @ 16.01.2018, 19:43:41 ) *
Poza tym to niczym się nie różni jakbym wklepał na sztywno to w tej klasie.


Różni się tym, że mogę tego pliku nie umieszczać w repo, a klasę muszę.
com
Cytat
Pliku database.php przecież nie muszę umieszczać w repo.

No nie musisz ale nie może tak być ze w środku kodu nagle coś brakuje bo nikt nie spodziewa się braku plików w jakimś core tak jak tutaj..
Cytat
Jak nie utworzysz pliku .env z odpowiednimi wpisami to też rzuci ci błędem.

Owszem ale brak env i błąd jeśli by się pojawił to zamierzony efekt. Brak pliku który nie jest bezpośrednio wstrzykiwany to błąd.

Cytat
Różni się tym, że mogę tego pliku nie umieszczać w repo, a klasę muszę.

To tez musisz bo jest to nieoderwalna cześć klasy wink.gif
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.