Jak załadować parent_theme functions.php przed child_theme?

12

Mam problem z załadowaniem functions.phppliku motywu nadrzędnego przed załadowaniem pliku motywu podrzędnego functions.php. Jest to potrzebne do procedury konfiguracji i inicjowania. Spojrzałem na haki w katalogu /wp_core_root/wp-settings.php (o nazwie:) do_action('setup_theme');.

Problem polega na tym, że nie wiem, jak się tam podłączyć, ponieważ pierwszy plik, który otrzymuję, to motyw podrzędny functions.php, więc żadne nie add_action( 'setup_theme', 'my_init_function' );będzie działać.

Edycja:
a) Wiem, że wtyczki ładują się wcześniej niż motyw i dlatego mogą uzyskać dostęp nawet do początkowego zapytania, ale nie chcę polegać na wtyczce.
b) Oto kod (skrócony) z pliku wp-settings.php

// happens a lot earlier:  
do_action( 'plugins_loaded' );

// localize stuff happening here
    do_action( 'setup_theme' );

        // Load the functions for the active theme, for both parent and child theme if applicable.
        if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH . '/functions.php' ) )
            include( STYLESHEETPATH . '/functions.php' );
        if ( file_exists( TEMPLATEPATH . '/functions.php' ) )
            include( TEMPLATEPATH . '/functions.php' );
    // first available hook, *after* functions.php was loaded
    do_action( 'after_setup_theme' );

Chcę uniknąć dwóch rzeczy: Najpierw wiele wyjaśnień dla użytkowników. Po drugie szansa, że ​​ktoś coś zepsuje, jeśli przecina linę, przypadkowo usuwając procedurę inicjacyjną rodziców. Ludzie powinni po prostu bawić się funkcjami.php, nie ryzykując, że coś zepsują, nie wiedząc o tym.

Innymi słowy: w jaki sposób mogę utrzymać czystość mojego pliku motywów potomnych functions.php, ale wykonać bootstrap motywów nadrzędnych?

Jakieś pomysły? Wielkie dzięki!

kajzer
źródło
Nie możesz tego po prostu włączyć?
wyrfel
Moje pytanie brzmi: skąd? Pierwszy plik, który zostanie załadowany w kontekście motywu, to motyw potomny functions.php. Spójrz na wp-settings.phpplik „molto loko” w jądrze (linia: 275-279 @wp 3.1 rc) ... wygląda tak: if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH . '/functions.php' ) ) include( STYLESHEETPATH . '/functions.php' ); if ( file_exists( TEMPLATEPATH . '/functions.php' ) ) include( TEMPLATEPATH . '/functions.php' );więc nie widzę szansy ... I nie chcę używać wtyczka do ładowania mojego motywu.
kaiser
Być może czegoś tu brakuje, ale jeśli wstawisz include(/path/to/parent/themes/functions.php)na górze swoich motywów potomnych functions.php, wtedy wszystko tam jest ładowane wcześniej. Nie?
wyrfel
@wyrfel: zaktualizowałem Q, aby było bardziej jasne
kaiser
Widzę, dzięki, teraz jest o wiele jaśniej. Dodatkowo założyłem, że robisz to tylko dla jednej instalacji.
wyrfel

Odpowiedzi:

11

Justin Tadlock napisał ostatnio świetny post na temat tworzenia lepszego pliku functions.php
którym (o ile dobrze pamiętam) zajmuje się dokładnie tym problemem.

Niestety jego strona jest obecnie niedostępna, więc na razie muszę polegać na mojej pamięci.

Jesteś na dobrej drodze z after_setup_themehakiem.

  1. O ile pamiętam, sztuczka polega na zawinięciu filtrów i akcji w jej funkcję.
    Zobacz przykład poniżej.
  2. Robisz to zarówno w functions.phpplikach nadrzędnych, jak i podrzędnych .
  3. Następnie możesz grać z priorytetem tych dwóch haczyków.

Trochę kodu wartego tysiąca słów - Twój motyw nadrzędny function.phppowinien wyglądać tak:

add_action( 'after_setup_theme', 'your_parent_theme_setup', 9 );
function your_parent_theme_setup() {    
    add_action(admin_init, your_admin_init);
    add_filter(the_content, your_content_filter);
}

function your_admin_init () {
...
}

function your_content_filter() {
...
}
Michał Mau
źródło
Ehm, dziękuję za napisanie (+1). Masz imponujący mózg;). Problem w tym, że after_setup_themejest już za późno, ponieważ pliki functions.php zostały już załadowane.
kaiser
EDYCJA: Po przemyśleniu kodu i przeczytaniu „zrób to zarówno w funkcjach nadrzędnych, jak i podrzędnych. Php” i „graj ​​z priorytetem” zaczyna mieć sens. Wciąż szukam lepszego rozwiązania, którego użytkownik nie może złamać tak łatwo, ale ma to sens! Dzięki!
kaiser
Nie ma tutaj żadnego realnego rozwiązania, więc zaznaczam to, ponieważ jako pierwszy zaproponowałeś to.
kaiser
9

Po pierwsze nie możesz. Funkcje motywu podrzędnego. Php zawsze ładuje się najpierw, kropka.

Po drugie, motywy nie mogą podpiąć się do setup_theme. Wtyczki mogą, ale pierwszą rzeczą, do której może się przyczepić motyw, jest after_setup_theme.

Jeśli rodzic jest poprawnie zaprojektowany, dziecko może nadpisywać funkcje i elementy w rodzicu, ale tylko wtedy, gdy zostanie załadowane jako pierwsze.

Mówiąc ogólnie, jeśli uważasz, że musisz najpierw załadować plik funkcji rodzica, prawdopodobnie robisz to źle. Musisz wyjaśnić większy problem.

Otto
źródło
Dziękuję za odpowiedź. Rozumiem potrzebę ładowania wtyczek przed motywami i już zdałem sobie z tego sprawę (czytaj wyżej: „I nie chcę używać wtyczki do ładowania mojego motywu.”). Aby rozwinąć moją sprawę: dostałem plik ini, który dba o ładowanie wszystkich części frameworka, który zaczyna się w funkcjach nadrzędnych php z wymaganiem pliku i ładowaniem klasy init. InitClass dba o ładowanie a) i tablicy danych z plików .ini motywów potomnych, a następnie wypycha je do różnych klas w celu dalszego przetwarzania np. meta boxy, niestandardowe typy postów itp.
kaiser
Mój problem polega na tym, że muszę to wszystko zainicjować z pliku funkcji rodziców funkcji.php, więc normalny użytkownik nie może tego zepsuć podczas zabawy wewnątrz motywu podrzędnego. Mój drugi problem polega na tym, że wszystkie te klasy nie są dostępne w pliku functions.php motywu podrzędnego, więc są bezużyteczne ... ale może mam tutaj duży błąd myślenia . Wszelkie pomysły lub sugestie dotyczące ulepszenia?
kaiser
3
.... Myślę, że będziesz musiał zaakceptować fakt, że jeśli użytkownik psuje rzeczy, to naprawdę ich problem. Konkluzja: Nie ma sposobu, aby najpierw załadować funkcje motywu nadrzędnego. Php i pozostawić motyw potomny „czysty”. Jeśli potrzebujesz czegoś w motywie potomnym, aby działało po załadowaniu pliku functions.php motywu nadrzędnego, umieść go w funkcji dołączonej do parametru after_setup_theme. Działa to po załadowaniu obu plików functions.php.
Otto
Ok. To nie jest taki duży problem. Interesuje mnie tylko taka możliwość. Pytanie: Po co „frameworki warte swojej soli” mają haczyk po procedurze init i nie używają after_setup_themehaka? Żeby nie „spamować” haka, czy dlatego, że jest bardziej „enterprisy” lub „kool”, er? Mam na myśli: Czy idea „najlepszych praktyk” kryjąca się za hakami równoległymi dla poszczególnych tematów „pozostawia haki rdzenia dla wtyczek”? (Tak sobie obecnie
radzę
„Jeśli masz zamiar to zrobić, nie zawracaj sobie głowy dodatkową akcją. Po prostu skorzystaj z After_setup_theme.” Ok. Dzięki. +1
kaiser
4

Próbujesz więc wykonać kod z funkcji potomnych.php, ale po załadowaniu motywu nadrzędnego. Proste, wystarczy użyć niestandardowej akcji:

Na końcu parent/functions.php:

do_action('parent_loaded');

W child/functions.php:

function parent_loaded() {
    // do init stuff
}
add_action('parent_loaded', 'parent_loaded');

Wszystkie motywy nadrzędne warte swojej soli robią to w ten sposób. Co więcej, mają kilka innych akcji i filtrów rozsianych wokół motywu potomnego.

scribu
źródło
Staram się unikać jak największej liczby instrukcji. To jeden z powodów, dla których przełączyłem się z pliku config.php w folderze motywu podrzędnego i teraz zamiast tego używam plików ini. W jednym zdaniu: staram się uciec od mojego starego / twojego rozwiązania i zbliżyć się jak najbliżej rdzenia i kodeksu. Mój problem polega na tym, że nie mogę dostarczyć pojedynczej funkcji z motywu potomnego, ponieważ żadna klasa ani inna z mojego bootstrapu nie jest dostępna w pliku functions.php motywów potomnych (nie mówiąc o znacznikach szablonów niestandardowych / ramowych).
kaiser
Zobacz zaktualizowaną odpowiedź.
scribu
Zaktualizowałem też Q. Po przeczytaniu tych 2/3 odpowiedzi wskazują mi na to samo źródło (tematyczne, przed edycją), mam wrażenie, że istnieje tylko metoda „justin tadlock”, ale chcę się upewnić.
kaiser
2
Jeśli masz zamiar to zrobić, nie zawracaj sobie głowy dodatkową akcją. Po prostu podłącz do after_setup_theme.
Otto
0

Dlaczego nie dołączasz functions.phppliku motywu nadrzędnego do pliku motywu podrzędnego functions.php, tak jak to:

W functions.phppliku motywu podrzędnego :

if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( TEMPLATEPATH . '/functions.php' ) )
            include( TEMPLATEPATH . '/functions.php' );

// code of child theme's functions.php file continues here

W ten sposób functions.phpplik motywu nadrzędnego nie jest zmieniany (czasami jest to ważne).

Anh Tran
źródło
jak wspomniano w pytaniu: „Innymi słowy: jak utrzymywać w czystości mój plik motywów podrzędnych functions.php, ale czy bootstrap nadrzędny jest gotowy?” Jeszcze lepiej: jak uniknąć połączenia z dowolnego pliku functions.php? Dlaczego: Ludzie są przyzwyczajeni do niszczenia każdego badziewia, którego nie chcą mieć w plikach szablonów. Istnieje więc duża szansa, że ​​ktoś przypadkowo usunie niektóre wiersze. Moje doświadczenie: nikt tak naprawdę nie czyta komentarzy, plików Readme ani dokumentacji.
kaiser
0

Miałem wcześniej podobny problem i naprawiłem go, tworząc dodatkowy pusty „child-functions.php” w rodzicu i włączając do „functions.php” (także rodzic) zaraz po plikach / funkcjach, których chcę używać w potomku, następnie w motywie potomnym tworzę plik „child-functions.php” i tam mogę rozpocząć symulację funkcji potomnych. php uruchamiany po rodzicu nie jest eleganckim rozwiązaniem, ale zadziałał.

Softmixt
źródło