[ALG] Hoe ver gaan met modulariteit?

Pagina: 1
Acties:
  • 1.109 views sinds 30-01-2008
  • Reageer

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Mijn CMS'je is gedeeltelijk modulair van opzet: elke functionaliteit (forum, userbeheer, templating, etc) zit in een aparte module (= php bestand). Ook heeft elke module zijn eigen database tabel of tabellen, geprefixed met de modulenaam.

Nu is het zo, dat modules ook vaak eigen, specifieke javascripts gebruiken. Ook gebruiken een aantal modules plaatjes (icoontjes) die andere modules niet gebruiken. Tot nu toe heb ik alle javascript functies in 1 bestand gedumpt, genaamd 'common.js'. Alle plaatjes zijn in de map /images gezet.

Nu bedacht ik mij vannacht dat het eigenlijk logischer zou zijn om elke module in een eigen map te zetten, met daarin het php bestand en module specieke javascript, language file, css en plaatjes.

Het nadeel daarvan is echter, dat je op 1 pageload meerdere javascript bestandjes moet inladen, meerdere stylesheets en dat de tekststrings niet in 1 bestand staan, maar in meerdere language files verspreid. Het betekent dat de client meer verschillende bestanden moet downloaden, en dat de server realtime meerdere language files moet aanspreken ipv 1. Bovendien staan tot nu toe alle modules in dezelfde map '/modules', waardoor het includen redelijk snel gaat. Maar ook dat zal trager gaan als elke module in een eigen /modules submap staat.

Kortom: hoe ver gaan jullie met het opdelen van je code? Ik heb het idee dat ik het door op te delen beter onderhoudbaar maak, maar er staan zoals gezegd een aantal nadelen tegenover...

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • JHS
  • Registratie: Augustus 2003
  • Laatst online: 05-11 09:42

JHS

Splitting the thaum.

Ik zou plaatjes, javascripts en dergelijk wel degelijk bij de module houden, omdat het anders niet echt een modulaire opzet te noemen is. Het is niet alsof je dan simpelweg een module in kan pluggen :) . De problemen die je schetst met betrekking tot het aanspreken van meerdere bestanden zou ik oplossen met behulp van caching.

DM!


  • eamelink
  • Registratie: Juni 2001
  • Niet online

eamelink

Droptikkels

De extra tijd die het je server kost om php files van her en der te includen is verwaarloosbaar.

Het extra downloaden van javascripts door de client kan je voorkomen door een javascript.php en een stylesheet.php te nemen, die alle benodigde javascripts en stylesheets inleest, bij elkaar zet en weer uitspuugt :)

  • Johnny
  • Registratie: December 2001
  • Laatst online: 10:09

Johnny

ondergewaardeerde internetguru

gewoon losse javascripts gebruiken, ze worden toch gecached. In plaats van in een keer enkele honderden kilobytes te laden hoeft er dan maar per pagina enkele kilobytes extra te worden geladen en het is nog makkelijker te schalen en te onderhouden ook wanneer je steeds meer modules krijgt.

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Nou, da's dus duidelijk :) Maar ik loop nu wel tegen een praktisch probleem op. Ik heb een map /modules en in deze map heeft elke module een subdir, bijvoorbeeld /modules/user. In deze map zit onder andere een language file: /module/user/user.nl.lang. Deze language file is op het moment een PHP array:
PHP:
1
2
3
4
5
$lang[] = array (
  'USER_FIRSTNAME' => 'Voornaam',
  'USER_LASTNAME'  => 'Achternaam',
  'USER_PASSWORD'  => 'Wachtwoord'
);

Op deze manier heb ik straks een language file voor elke module, bijvoorbeeld ook voor het forum: /modules/forum/forum.nl.lang:
PHP:
1
2
3
4
$lang[] = array (
  'FORUM_VIEW_POST' => 'Bekijk bericht',
  'FORUM_SEND_POST' => 'Verstuur bericht'
);

Nu wil ik dus op het moment dat er een request naar de server gaat, al deze language files includen, ze doorlezen en er 1 array van maken die ik in een static var of zoiets stop. Pseudo:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
function language_load($language = 'nl') {
  static $language;

  foreach (module_list() as $module) {
    $filename = "modules/$module/$module.$language.lang";
    if (file_exists($filename)) {
      include_once($filename);
      $language = array_merge($language, $lang) // ??? wat hier te doen ???
    }
  }
  return $language;
}

Vraag: hoe kan ik nu die language files uitlezen en mergen tot 1 array? Moet ik trouwens wel elke language file in de vorm van een PHP array stoppen hiervoor? Tips, graag!

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 09:27

mulder

ik spuug op het trottoir

Waarom zou je een andere aanpak kiezen dan als met de javascripts en images, je zorgt dat je module de juiste language files include met daar in constants met de juiste taal. Ik zie geen toegevoegde waarde van een array.

oogjes open, snaveltjes dicht


  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
eamelink schreef op maandag 26 februari 2007 @ 16:32:
Het extra downloaden van javascripts door de client kan je voorkomen door een javascript.php en een stylesheet.php te nemen, die alle benodigde javascripts en stylesheets inleest, bij elkaar zet en weer uitspuugt :)
Moet je wel zorgen dat je het zo aanpakt dat ze wel gecached kunnen worden. Maar goed, als er niet echt veel veranderd per module kun je net zo goed een gewone file neerzetten per js/css file, hoef je het niet te parsen, scheelt ook weer. :P

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

Reveller schreef op maandag 26 februari 2007 @ 17:26:
Vraag: hoe kan ik nu die language files uitlezen en mergen tot 1 array? Moet ik trouwens wel elke language file in de vorm van een PHP array stoppen hiervoor? Tips, graag!
Alle language files in één map zetten, waar je met de filesystem functies doorheen loopt, om vervolgens elk bestand dat je daar tegenkomt te includen? Daarna array_merge gebruiken voor het samenvoegen van arrays. Lijkt me niet zo'n probleem eigenlijk? :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • frickY
  • Registratie: Juli 2001
  • Laatst online: 08:59
Kijk ook eens naar gettext() voor je vertalingen.

  • Annie
  • Registratie: Juni 1999
  • Laatst online: 25-11-2021

Annie

amateur megalomaan

Ik snap niet waarom je alles in 1 array zou willen zetten. Als de language file module specifiek is, dan gebruik je 'm dus ook alleen binnen die module, toch?
Waarom dan alle files in 1 array stoppen?

Today's subliminal thought is:


  • MisterData
  • Registratie: September 2001
  • Laatst online: 27-11 20:42
Zet javascripts per module in een map, maak een PHP script (javascripts.php) die al die *.js bestanden samenvoegt en uitspuugt (eventueel newlines enzo eruit slopen voor kleiner bestand). Dat script cached dan naar een bestand en roep je aan als je een script veranderd hebt :) Eventueel laat je het script ook nog zelf de bestands-tijden checken van de javascripts :)

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Annie schreef op maandag 26 februari 2007 @ 21:21:
Ik snap niet waarom je alles in 1 array zou willen zetten. Als de language file module specifiek is, dan gebruik je 'm dus ook alleen binnen die module, toch?
Waarom dan alle files in 1 array stoppen?
Modules kunnen aangeroepen worden op pagina's buiten die modules. Het simpelste voorbeeld hierbij is een [laatste 10 reakties uit het forum] - box op de homepage. In die box gebruik ik dus strings uit de forum module, terwijl ik in werkelijkheid in de page (want: op een door de user aangemaakte webpagina) module zit.
MisterData schreef op maandag 26 februari 2007 @ 21:55:
Zet javascripts per module in een map, maak een PHP script (javascripts.php) die al die *.js bestanden samenvoegt en uitspuugt (eventueel newlines enzo eruit slopen voor kleiner bestand). Dat script cached dan naar een bestand en roep je aan als je een script veranderd hebt :) Eventueel laat je het script ook nog zelf de bestands-tijden checken van de javascripts :)
Een dergelijk idee is al eerder geopperd en het klinkt reuze handig :) Daar ga ik eens werk van maken...
frickY schreef op maandag 26 februari 2007 @ 19:42:
Kijk ook eens naar gettext() voor je vertalingen.
gettext is geen optie omdat niet alle (Windows-) servers dit ondersteunen en ik zoek een platform onafhankelijke oplossing. Ik weet dat er op SourceForge een win32 port van gettext staat, maar ik heb niet altijd iets te zeggen over de configuratie van de server, lijkt me :)

[ Voor 47% gewijzigd door Reveller op 26-02-2007 22:04 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 09:27

mulder

ik spuug op het trottoir

Reveller schreef op maandag 26 februari 2007 @ 22:01:
[...]

Modules kunnen aangeroepen worden op pagina's buiten die modules. Het simpelste voorbeeld hierbij is een [laatste 10 reakties uit het forum] - box op de homepage. In die box gebruik ik dus strings uit de forum module, terwijl ik in werkelijkheid in de page (want: op een door de user aangemaakte webpagina) module zit.

[...]
En als het in een array zit dan heb je toch hetzelfde probleem? Je zult toch de taalwaarden van die module er bij moeten pakken, of je nou de waarden uit een bestand inleest in een array of simpelweg de file include.

oogjes open, snaveltjes dicht


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Don Facundo schreef op dinsdag 27 februari 2007 @ 08:42:
[...]
En als het in een array zit dan heb je toch hetzelfde probleem? Je zult toch de taalwaarden van die module er bij moeten pakken, of je nou de waarden uit een bestand inleest in een array of simpelweg de file include.
Het idee is om op elke pagerequest alle language files te includen, door te nemen en onder elkaar te plakken in 1 array die voor elke functie beschikbaar is. Dit bestand, met daarin alle strings van alle modules, kan ik dan cachen. Van tijd tot tijd controleer ik of de language files van de modules veranderd / geupdate zijn. Als dat zo is, stel het systeem een nieuwe language-array samen die weer gecached wordt. Volgens mij werkt zo'n systeem het beste.

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • soulrider
  • Registratie: April 2005
  • Laatst online: 27-11-2017
je kan ook spieken bij een voorbeeld zoals php-nuke
(ook in verre mate modulair)
en hoe daar het probleem van language fiels worden opgelost (daar ik me herinner vind je per module een verdere map 'language' die in de module-php-script ge-include wordt)

oke moet je per module vertalingen gaan voorzien, maar dat kan je ook oplossen met een algemene:
if not found include 'default-language-file'
en dat dan in 't engels voorzien.

  • mithras
  • Registratie: Maart 2003
  • Niet online
Reveller schreef op maandag 26 februari 2007 @ 22:01:
[...]

Modules kunnen aangeroepen worden op pagina's buiten die modules. Het simpelste voorbeeld hierbij is een [laatste 10 reakties uit het forum] - box op de homepage. In die box gebruik ik dus strings uit de forum module, terwijl ik in werkelijkheid in de page (want: op een door de user aangemaakte webpagina) module zit.
Dat is natuurlijk niet modulair meer ;)

Wat je beter kan doen is bijvoorbeeld je frontpage zo maken dat de onderdelen die je wil tonen ophaalt van de andere modules. In php kan je dan een functie van de module aanroepen. De module regelt alles zelf, en retourneert bijvoorbeeld een html string. Dan heeft je frontpage niets te zeggen over de zaken die spelen in je forum module.
Bij een wijziging van je forum module wijzigt dan je frontpage automatisch mee, als je het op jouw manier doet kan je problemen krijgen :)

Maar ik snap het nut ook niet van een grote array voor alle vertalingen: als je modulair wil zijn moet je juist _ook_ dat modulair maken. Gewoon een language file per module. De module regelt gewoon haar eigen vertaling.

In mijn cms is het nu als volgt geregeld:
code:
1
2
3
4
5
6
7
8
9
10
./
./index.php
./init.php   //initialiseert objecten uit /includes
./config.php  //config file
./includes/plugin.php  //php object met daarin de plugins
./includes/functions/php   //php object met veel gebruikte functies
./plugins/main/main.class.php   //plugin "main"
./plugins/user/user.class.php   //plugin voor user managment
./plugins/user/admin.class.php   //admin gedeelte voor plugin
./plugins/user/language   //language file
De language file werkt nu nog niet, die wordt binnenkort toegevoegd. Maar zo behoud je de hoogste mate van modulariteit :)

Als ik bijvoorbeeld in mijn blog de user wil ophalen die het artikel heeft geschreven, moet dat via de user plugin. In het blog gedeelte staat namelijk alleen een user-id. Ik roep een functie aan binnen $user die een array met gebruikersinfo retourneert. Daar kan je dan weer je username uit halen. Als ik dus de usertabel wijzig, verandert er niets voor mijn blog: dit handel ik toch allemaal af binnen het user gedeelte :)

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Voor elke module van mijn cms heb ik een submap in /modules. In elke submap zit een language file die hoort bij die module. Hieronder staan 2 voorbeelden. In de code daaronder probeer ik deze twee language files te mergen tot 1 array:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// user/user.nl.lang
$lang[] = array (
  'USER_FIRSTNAME' => 'Voornaam',
  'USER_LASTNAME'  => 'Achternaam',
  'USER_PASSWORD'  => 'Wachtwoord'
);

// page/page.nl.lang
$lang[] = array (
  'PAGE_DELETE' => 'Verwijder pagina',
  'PAGE_UPDATE' => 'Update pagina',
);

function language_load($language = 'nl') {
  foreach (module_list() as $module) {
    $filename = "modules/$module/$module.$language.lang";
    if (file_exists($filename)) {
      include_once($filename);
      $array = array_merge($array, $lang);
    }
  }

  return $array;
}

PHP loopt keihard vast door regel 20. Als ik die regel weg laat, werkt het bijna. Met een print_r($lang) krijg ik de volgende array terug:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
Array
(
  [0] = Array (
    [USER_FIRSTNAME] => 'Voornaam',
    [USER_LASTNAME]  => 'Achternaam',
    [USER_PASSWORD]  => 'Wachtwoord'
  )

  [1] = Array (
    [PAGE_DELETE] => 'Verwijder pagina',
    [PAGE_UPDATE] => 'Update pagina',
  )
)

Maar ik wil als output:
code:
1
2
3
4
5
6
7
8
Array
(
  [USER_FIRSTNAME] => 'Voornaam',
  [USER_LASTNAME]  => 'Achternaam',
  [USER_PASSWORD]  => 'Wachtwoord'
  [PAGE_DELETE]    => 'Verwijder pagina',
  [PAGE_UPDATE]    => 'Update pagina',
)

Vraag: hoe kan ik nu die language files uitlezen en mergen tot 1 array?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • Wim Leers
  • Registratie: Januari 2004
  • Laatst online: 01-12 23:49
Wat is de exacte foutmelding?

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 30-11 15:10

Creepy

Tactical Espionage Splatterer

Met $lang[] = new array(...) voeg je steeds een nieuwe element aan de $lang array toe waarin weer een nieuwe array staat omdat je met array() weer een nieuwe array aanmaakt. Probeerd $lang = new array(...) eens zodat $lang steeds opnieuw wordt overschreven.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
@Creepy - nu werkt het perfect, dank je!

Nu ik erover nadenkt, kan ik ws. net zo makkelijk de array's appenden ipv mergen, maar dat dan nog blijft de oplossing hetzelfde :)

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Verwijderd

Waarom doe je niet iets als
PHP:
1
2
3
4
5
6
7
8
// user/user.nl.lang
$lang['USER_FIRSTNAME'] = 'Voornaam';
$lang['USER_LASTNAME']  = 'Achternaam';
$lang['USER_PASSWORD']  = 'Wachtwoord';

// page/page.nl.lang
$lang['PAGE_DELETE'] = 'Verwijder pagina';
$lang['PAGE_UPDATE'] = 'Update pagina';

\Je hoeft nu alleen de juiste files te includen, en niets te mergen.

  • Blaise
  • Registratie: Juni 2001
  • Niet online
Ik zat laatst ook met deze kwestie en heb gekeken hoe anderen het doen. PHPBB3 (beta) doet het zo:

Aan het begin van elk taalbestand:
PHP:
1
2
3
4
if (empty($lang) || !is_array($lang))
{
    $lang = array();
}


vervolgens:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$lang = array_merge($lang, array(
    'YEAR'              => 'Year',
    'YES'               => 'Yes',
    'YOU_LAST_VISIT'    => 'Last visit was: %s',
    'YOU_NEW_PM'        => 'A new private message is waiting for you in your Inbox',
    'YOU_NEW_PMS'       => 'New private messages are waiting for you in your Inbox',
    'YOU_NO_NEW_PM'     => 'No new private messages are waiting for you',

    'datetime'          => array(
        'TODAY'         => 'Today, ',
        'YESTERDAY'     => 'Yesterday, ',
        'Sunday'        => 'Sunday',
        'Monday'        => 'Monday',
        // etc
    )
));


Ik heb de methode gebruikt zoals beschreven in de post hierboven, maar die vind ik minder overzichtelijk door de brackets.

[ Voor 6% gewijzigd door Blaise op 18-03-2007 20:19 ]

Pagina: 1