Potrzebuję rady. Statyczna klasa ze zmiennymi, czy coś innego?

0

Czołem!

Potrzebuję szybkiej rady. Jak rozwiązujecie taki konkretny problem, że w dużej aplikacji często odnosicie się w projekcie do jakichś zmiennych?
Nie chcę korzystać z globalnych.

Zacząłem stosować takie proste rozwiązanie, w postaci klasy ze zmiennymi statycznymi. Ma to tę zaletę, że w ten sposób mogę łatwo znaleźć interesującą zmienną, korzystając z podpowiedzi w IDE.

<?php
namespace tmc\mailboo\src\_Controllers;

use tmc\mailboo\src\App;

/**
 * Class Vars.
 * Defines some constant variables for access inside the project.
 */
class Vars {

	public static $Email_PostType_Slug;
	public static $Email_PostType_MetaKey_Type;
	public static $Email_PostType_MetaKey_HeaderFromName;
	public static $Email_PostType_MetaKey_HeaderFromEmail;
	public static $Email_PostType_MetaKey_HeaderReplyToEmail;
	public static $Subscriber_PostType_Slug;
	public static $List_Taxonomy_Slug;
	public static $List_Term_WpUsers_Slug;
	public static $List_Term_WpUsers_MetaKey_Protected;

	/**
	 * Initialization of variables.
	 * Should be called inside App::setUp().
	 */
	public static function init() {

		static::$Email_PostType_Slug                       = App::getPrefix( '_email' );
		static::$Email_PostType_MetaKey_Type               = 'email_type';
        static::$Email_PostType_MetaKey_HeaderFromName     = 'header_from_name';
        static::$Email_PostType_MetaKey_HeaderFromEmail    = 'header_from_email';
        static::$Email_PostType_MetaKey_HeaderReplyToEmail = 'header_reply_to_email';
		static::$Subscriber_PostType_Slug                  = App::getPrefix( '_subscriber' );
		static::$List_Taxonomy_Slug                        = App::getPrefix( '_list' );
		static::$List_Term_WpUsers_Slug                    = 'wordpress_users';
		static::$List_Term_WpUsers_MetaKey_Protected       = 'protected';

	}

}

Najpierw odpalam sobie Vars::init();
a później mam już dostęp do reszty w dowolnym miejscu w projekcie.
np. echo Vars::$Email_PostType_Slug;

Czy istnieje jakiś design pattern, który byłoby lepiej zastosować? Ktoś spotkał się kiedyś z takim "problemem"?
Przypominam, że zależy mi na podpowiedziach w IDE ( Ctrl + space ).

0

Znam jednego seniora, który w kontrolerze klasy, zamiast pól private lub od biedy static pisze const i potem w prosty sposób wywołuje je po nazwie w metodach tej klasy. Taki kontroler zaczyna się od długiej listy const..

1

Jeśli dochodzisz w swoim projekcie do takich problemów to jest on źle zaprojektowany. Nie wiem też co rozumiesz przez duży projekt, bo ja z Twojego kodu widzę, że jest to coś postawionego na WP. Sam nie pracuje przy WP, ale mam styczność z projektami, które mają po kilkaset tysięcy użytkowników i nie istnieje tam żadna przesłanka, aby stosować Twoje rozwiązanie.

Skoro pytasz o wzorzec to może singleton, ale jak wiadomo jest to antypattern. Na serio jeśli potrzebujesz takich rozwiązań to masz coś nie tak z tym projektem.

No i ten kod.... Rozumiem że WP ma jakieś konwencję nazewnictwa, ale to co pokazałeś zawiera totalny mix code style'a

3

Wrzucanie ich do jednego, globalnego wora to code smell i prawdopodobnie pogwałcenie SRP, a jak już gwałcisz SRP, to pewnie inne zasady też.

Nie bardzo rozumiem co robi ten Twój kod, ale spójrzmy na taki przykład:

class Vars
{
    public static $Email_Regex;

    public static function init()
    {
        static::$Email_Regex = '\S+@\S+';
    }
}

Prawdopodobnie gdzieś w kodzie masz coś takiego (i to nie w jednym miejscu):

if(preg_match(Vars::$Email_Regex, $email)) {
    
}

Zamiast tego lepiej może zrobić tak:

class EmailValidator
{
    const EMAIL_REGEX = '\S+@\S+';

    public function validate($email)
    {
        return preg_match(self::EMAIL_REGEX, $email);
    }
}

Sprowadza się to do tego, żeby przenieść te zmienne tam, gdzie ich miejsce.

Nie wiem czy w WP jest koncepcja rekordu/encji, ale slug zawsze można przenieść do klasy WpUsers:

class WpUsers implements Sluggable
{
    use Sluggable;

    protected function getSlugColumn()
    {
        return 'wordpress_users';
    }
}

interface Sluggable {
    public function toSlug();
}

trait Sluggable {
    // jak ktoś uzyje tego traita, to wymusi na nim interpreter impementacje metody
    // uzycie zmiennej tez jest okej, ale jest to mniej jawne
    protected abstract function getSlugColumn();
    
    // tutaj kod, który z jakieś kolumny w bazie generuje slug
   public function toSlug () {
      return str_replace(' ', '-', $this->{$this->getSlugColumn()});
   }
}

Czasami takie zmienne, to zmienne konfiguracyjne jakiegoś modułu. Czy ten moduł ma config? Zawsze możesz wydzielić config do pliku:

// module.config.php

return [

    'List_Term_WpUsers_Slug' => 'wordpress_users'

]

Config zaczytujesz w miejscu, w którym bootstrapujesz moduł, czy coś. Możesz później od biedy do klasy SomeModule dodać metode getConfig.

0
Desu napisał(a):

Czasami takie zmienne, to zmienne konfiguracyjne jakiegoś modułu. Czy ten moduł ma config?

Tak, właśnie chodzi o coś w stylu configu. Pisząc wtyczki do WP trzeba co jakiś czas odwoływać się w zapytaniach do rodzaju postu albo taxonomii. Nie podobało mi się pamiętanie za każdym razem konkretnego klucza, dlatego wolałem te klucze gdzieś przechowywać.

axelbest napisał:

mam styczność z projektami, które mają po kilkaset tysięcy użytkowników i nie istnieje tam żadna przesłanka, aby stosować Twoje rozwiązanie.

No a jednak nastał moment w którym potrzebny mi config, cóż teraz? ;-)

Zgadzam się, że nie jest to jakieś świetne i piękne.
Przecież gdybym tak twierdził, nie pisałbym tematu na forum 4programmers o nazwie "Potrzebuję rady. Statyczna klasa ze zmiennymi, czy coś innego?".
Wklejka w pierwszym poście to tylko pomysł, który napisałem tutaj, aby łatwiej było zobrazować o co mi chodzi. Szukam inspiracji.

A propos jeszcze mixu code style'u, nie rozumiem za bardzo na co konkretnego wskazujesz? "Slug" to ciąg znaków url friendly, czyli bez wielkich liter i znaków specjalnych, więc separatorem jest tutaj podkreślnik. Na co dzień w kodzie piszę w CamelCase.
W tym przypadku $Email_PostType_MetaKey_HeaderFromName wydawało mi się bardziej czytelne od $EmailPostTypeMetaKeyHeaderFromName. Naprawdę jest to aż tak rażące?

Edit:

Tfu, jednak jest rażące. Generalnie samo korzystanie z tak długich nazw zmiennych to problem u podstaw, ale przysięgam, to tylko w jednym miejscu ... :D

0

Skoro ten config Ci tak potrzebny jest (zdaje sobie sprawę że na serio go potrzebujesz) to moze lepiej zainteresuj się dependency injection. Dodatkowo jeszcze dodam że może w zależności od warstwy (model/controller/view) wystarczy zastosować dziedziczenie. Chociaż i tak to co opisał @Desu idealnie rozwiazywaloby Twój problem

1 użytkowników online, w tym zalogowanych: 0, gości: 1