TomPich Posted September 14 Share Posted September 14 Hi guys, I know this has been asked already a few times here, but I couldn’t find a working solution for me... Working on a quite big project and I feel it can get messy quite easily. I need to tidy my code a little but. So here is the situation: I have quite a lot of data handling to do in the front side of my website. This involves querying on an external DB and processing the data. I started to write some methods in a DefaultPage class and that works well, but this will end with a very big file with tens of methods not related to the same logic. What I would like, is to have a src/ folder in my site/ folder, with all the custom classes in relevant subfolders. I tried this: // in site/init.php $namespace = 'ProcessWire\\App'; $classLoader = $this->wire('classLoader'); if (!$classLoader->hasNamespace($namespace)) { $srcPath = 'src/'; // target folder is /site/src $classLoader->addNamespace($namespace, $srcPath); } Inside this site/src/ folder, there is a MyClass.php file, with the class MyClass namespace App; class MyClass { const hello = "hello"; } And in my template file: namespace ProcessWire; use App\MyClass; <?= MyClass::hello ?> But I can’t get class loaded... 😔 I tried variation with namespace and use, but it didn’t work... Any help please ? Thank you! Link to comment Share on other sites More sharing options...
da² Posted September 14 Share Posted September 14 (edited) Hi, I tried the same a while ago and it appears PW is forcing custom classes to be in site/classes directory. The code seems to be in ProcessWire.php: $cfg['paths']->data('classes', $cfg['paths']->site . "classes/"); Maybe you can overwrite this in your own config.php? Not sure if this is a good idea. ^^ But these classes dependencies can be in any package in site/templates/YourPackage (parent/abstract classes, Traits...). On my side the code I put in page classes is only related to the model part (getting/setting data), I don't use them to do rendering or controller stuff. The main part of the code is in my packages in site/templates. So I'm not really annoyed by the fact they have to be in the same directory, but I admit it would be better to put them in their related package. Edited September 14 by da² 1 Link to comment Share on other sites More sharing options...
fliwire Posted September 14 Share Posted September 14 <?php // site/init.php namespace ProcessWire; if (!defined("PROCESSWIRE")) die(); $classLoader = $wire->classLoader; $classLoader->addSuffix("Service", __DIR__ . '/services'); $classLoader->addSuffix("Form", __DIR__ . '/forms'); $classLoader->addNamespace("ProcessWire", __DIR__ . '/utils'); 2 1 Link to comment Share on other sites More sharing options...
TomPich Posted September 15 Author Share Posted September 15 Hey guys, @da², @fliwire, thank you for your help. It pushed me in the right direction. I got my things done and wanted to share with whoever would find that useful. Here was my need: a specific folder to store some classes, usable easily across templates (ie "use Class" and not "include ...". These classes wouldn’t fit (IMO) into a DefaultPage class for separation of concerns matter. And I didn’t want to try to develop a module, seemed an overkill and time is running... I decided to store my custom classes files into some subfolders of the /site/classes folder. At first, I used a /site/src folder (and it worked), but as the classes folder already exists, I thought it made more sense to use this folder. This is my architecture ├── site/ │ ├── assets │ ├── classes/ │ │ ├── Repository/ │ │ │ ├── AbstractRepository.php │ │ │ └── ContactRepository.php │ │ ├── DefaultPage.php │ │ ├── HomePage.php │ │ └── Utils.php │ ├── modules │ └── templates └── wire For autoloading use PW autoloader, in put in init.php $classLoader = $wire->classLoader; $classLoader->addNamespace("ProcessWire", __DIR__ . '/classes'); Then the magic happens. My ContactRepository.php, for example : namespace ProcessWire\Repository; use ProcessWire\Utils; class ContactRepository extends AbstractRepository { // my stuff here... } and when I need it in a template file : namespace ProcessWire; use ProcessWire\Repository\ContactRepository; $contactRepo = new ContactRepository; $speakers = $contactRepo->getAllSpeakersAndModerators(); Remarque: In the init.php file, I tried with and without $classLoader->addSuffix("Repo", __DIR__ . '/classes/repositories'); // does not change anything $classLoader->addPrefix("Repo", __DIR__ . '/classes/repositories'); // does not change anything I can't really grasp in which situation this useful, and the doc is quite short... 😅 So with this file structure, I can really get a step further in logic handling and code maintenance. Hope someone will find this useful. Cheers 4 Link to comment Share on other sites More sharing options...
da² Posted September 15 Share Posted September 15 I don't understand why this is necessary: $classLoader->addNamespace("ProcessWire", __DIR__ . '/classes'); I don't need this to get auto-load of custom classes. Link to comment Share on other sites More sharing options...
TomPich Posted September 15 Author Share Posted September 15 If I don’t use it, ProcessWire is apparently not able to import classes in the Repository Subfolder Link to comment Share on other sites More sharing options...
szabesz Posted September 15 Share Posted September 15 4 hours ago, TomPich said: For autoloading use PW autoloader, in put in init.php $classLoader = $wire->classLoader; $classLoader->addNamespace("ProcessWire", __DIR__ . '/classes'); If you need to do it even earlier than using init.php: https://processwire.com/talk/topic/26875-page-classes-with-traits/?do=findComment&comment=222333 also see: https://github.com/processwire/processwire/blob/3cc76cc886a49313b4bfb9a1a904bd88d11b7cb7/wire/config.php#L1756 1 Link to comment Share on other sites More sharing options...
da² Posted September 15 Share Posted September 15 (edited) 1 hour ago, TomPich said: If I don’t use it, ProcessWire is apparently not able to import classes in the Repository Subfolder Hmm, I don't need it on my side. Are you using the correct namespace? I added a directory Test in site/classes/, inside a class Foo with this namespace: <?php namespace ProcessWire\Test; class Foo{} And in a template.php I instanciate it: use ProcessWire\Test\Foo; $test = new Foo(); If you're using the same code, maybe it comes from my composer.json but I would be surprised. I updated the composer.json, but only to add my own namespaces. ** looking my composer.json and... Hoooooo yes I know why... 😁 ** "autoload": { "files": [ "wire/core/ProcessWire.php" ], "psr-4": { "Rfro\\Rfrorga\\ProcessWire\\": "site/templates/", "ProcessWire\\": "site/classes/", "Rfro\\Rfrorga\\WebApi\\": "webApi/", "Rfro\\Rfrorga\\Cron\\": "cron/" } }, I don't remember why but I added a namespace for site/classes. 🤔 Probably for the same problem as you... Could it be a cleaner way to solve your issue? Edited September 15 by da² 2 Link to comment Share on other sites More sharing options...
fliwire Posted September 15 Share Posted September 15 @TomPich // suffix is Repository not Repo. $classLoader->addSuffix("Repository", __DIR__ . '/classes/Repository'); Link to comment Share on other sites More sharing options...
TomPich Posted September 16 Author Share Posted September 16 9 hours ago, fliwire said: // suffix is Repository not Repo. $classLoader->addSuffix("Repository", __DIR__ . '/classes/Repository'); Yes... I tried Repository first, then I tested with another suffix (Repo), and it didn’t change anything (and I then commented it out...). The addnamespace does all the job. So I don’t get what this addSuffix does. My guess is that it allows better performance when there are a lot of classes, pointing out the sub-folder to look into. But then, so does the namespace ProcessWire\Repository; I can't figure it out... Link to comment Share on other sites More sharing options...
fliwire Posted September 16 Share Posted September 16 (edited) addSuffix loads class if filename ends with suffix. processwire/wire/core/ProcessWire.php at 3cc76cc886a49313b4bfb9a1a904bd88d11b7cb7 · processwire/processwire (github.com) my setup. changed default "classes" dir with "models". Edited September 16 by fliwire 2 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now