froot Posted July 14, 2022 Share Posted July 14, 2022 Hi all, I want to use the PW supplied variable, namely $database, in a public function inside a module I'm developing. class ProcessMyModule extends Process { public function execute() { $table = $this->modules->get('MarkupAdminDataTable'); $indices = wire('database')->getIndexes('myTable'); for ($i=0; $i<count($indices); $i++) { $headerRows .= $indices[$i]; if ($i==count($indices)) { break; } $headerRows .= ', '; } $table->headerRow([$headerRows]); $out .= $table->render(); return $out; } } But $database is unknown. How do I pass it? Link to comment Share on other sites More sharing options...
elabx Posted July 14, 2022 Share Posted July 14, 2022 You can access it like: $this->database->getIndexes('my_table') Or wire('database')->getIndexes('my_table'); EDIT: Your code seems correct ? Can you paste the error thrown? 2 Link to comment Share on other sites More sharing options...
froot Posted July 14, 2022 Author Share Posted July 14, 2022 @elabx tried that before, doesn't work though… I get Method WireDatabasePDO::getIndexes does not exist or is not callable in this context search also, guessing it's relevant, this is where I create the table in the database: class myModule extends WireData implements Module { public function ___install() { $sql = " CREATE TABLE myTable ( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, order_product VARCHAR(500) NOT NULL, order_customer_name VARCHAR(191) NOT NULL, order_customer_address VARCHAR(500) NOT NULL, order_customer_emailaddress VARCHAR(191) NOT NULL, order_date VARCHAR(191) NOT NULL ) ENGINE={$this->config->dbEngine} DEFAULT CHARSET={$this->config->dbCharset} "; try { $this->wire()->database->exec($sql); } catch(\Exception $e) { $this->error($e->getMessage()); } } } Link to comment Share on other sites More sharing options...
bernhard Posted July 15, 2022 Share Posted July 15, 2022 Do you really want to create a custom DB table? You can do that if you want/need to do it, but usually working with PW pages and the PW API is a lot more convenient. The API is easier to develop and use and also you get the benefit of a GUI for editing your data. Instead of creating a table in the DB I'd suggest you create two templates: orders, order Then you set the family settings of orders and order so that order is the only allowed child of orders and orders is the only allowed parent for order. Then you add fields to your "order" template: product (page reference field), customer_name (text), customer_address (textarea), customer_email (email) You don't need order_date, because PW stores the created timestamp of every page that you can use for that. Then you create your table with PW API: <?php $out = "<table>"; $orders = $this->wire->pages->find("template=order, limit=20"); foreach($orders as $order) { $out .= "<tr><td>$order</td><td>{$order->customer_name}</td></tr>"; } $out .= "</table>"; You can also use MarkupAdminDataTable but I don't know the correct syntax by heart ? Pagination can be tricky... Adding pages would be like this: <?php $p = new Page(); $p->template = 'order'; $p->parent = $pages->get("/orders"); $p->title = 'order XY'; $p->product = $yourproduct; $p->customer_name = 'John Doe'; ... $p->save(); 3 Link to comment Share on other sites More sharing options...
teppo Posted July 15, 2022 Share Posted July 15, 2022 Generally speaking I second what Bernhard said above. Custom tables are rarely a good idea — though there are some exceptions ? Now, as for your error: 23 hours ago, fruid said: Method WireDatabasePDO::getIndexes does not exist or is not callable in this context search As the error states, the problem is not that you don't have access to $database — that part works just fine. The issue is that in this case $database does not provide a method called "getIndexes". This method was added in ProcessWire 3.0.182, so the first thing to check is your ProcessWire version. If it's earlier than 3.0.182, this error is expected. If it's a later one, then we can continue debugging from there. Also, as a loosely related note, the use of getIndexes() seems a bit odd here. Usually one would use $database->getColumns() (which, just for the record, was added in ProcessWire 3.0.180) to display column names/labels ? 4 Link to comment Share on other sites More sharing options...
froot Posted July 19, 2022 Author Share Posted July 19, 2022 I was out of town for the weekend. Thanks for your replies, it all makes sense what you say, now that you're saying it, the reason I chose this way was, I look at other module's code to see how they go about creating tables and all I could find was this SQL way. What I am missing is the proper PW API way. The thing is, creating the templates and fields via the PW admin GUI is of course easy, but that's in case I just have one project in mind. What if I want this to be a module, i.e. have these things created "automatically" upon module installation? What's to consider? That's where example modules would come in handy. Do you know of any that illustrate that so I can use them as a reference? I never coded a standalone PW module before. Also, not sure if I need a separate page for each order, wouldn't one line in a table be enough? That might also be why I thought a custom database table would make sense. Link to comment Share on other sites More sharing options...
bernhard Posted July 19, 2022 Share Posted July 19, 2022 The questions you are asking need a lot of experience and/or testing. It always depends on the specific use case or environment. In general plain DB tables are better for performance, but have the drawback that you can't directly edit them via GUI. Also querying might be a little more complicated than what we get from PW pages and PW api. PW pages on the other hand have the benefit of having a GUI built in and making it easy to manipulate data via API, use hooks, use PW fields (eg for storing images) etc.; Basically all the PW magic. The drawback is that they have a bigger footprint. The need more memory, they might not be as efficient as direct DB queries, etc.. 5 minutes ago, fruid said: the reason I chose this way was, I look at other module's code to see how they go about creating tables and all I could find was this SQL way. What I am missing is the proper PW API way. The thing is, creating the templates and fields via the PW admin GUI is of course easy, but that's in case I just have one project in mind. What if I want this to be a module, i.e. have these things created "automatically" upon module installation? What's to consider? That's one of the reasons why I built RockMigrations. You can do all that using the PW api and you'll find several examples for that. For example the blog module does it like this: https://github.com/kongondo/Blog/blob/a13af302af9e6ce1bcbbe623a36b8efc1a033763/BlogInstallWizard.php#L352 As you can see those things can quickly get complex... RockMigrations abstracts that logic and can be used to help you built modules that create fields, templates, pages etc... <?php $rm->migrate([ 'fields' => [ 'field1' => ..., // create field1 'field2' => ..., // create field2 ], 'templates' => [ 'blog' => [ // define fields of blog template 'fields' => [ 'title', 'field1', 'field2', ], ], ], ]); 2 Link to comment Share on other sites More sharing options...
teppo Posted July 19, 2022 Share Posted July 19, 2022 Another example of creating fields/templates during module install: https://github.com/apeisa/Discussions/blob/master/Discussions.module#L280. That code is 10+ years old and a bit verbose, but that's exactly why it's (in my opinion) a good example. No abstraction layers, no potentially confusing shortcuts, etc. ? 3 Link to comment Share on other sites More sharing options...
froot Posted July 19, 2022 Author Share Posted July 19, 2022 Though I understand that handling pages is still the easiest approach in PW, my requirements are actually pretty simple. Just a couple of things to be saved somewhere and displayed on an admin page. It doesn't need a dedicated url, no further interaction with the user, there are no user accounts that users login to and whatnot. The info is merely for the content manager. But anyways, when using pages, I would just do public function ___install() { $t = new Template(); $t->name = 'some_template'; // add some settings $t->save(); } and then public function ___uninstall() { $templates = wire('templates'); $templates->delete($templates->get('some_template')); } and that's it? Pretty much what you explained above with the GUI, only this time with the API. Link to comment Share on other sites More sharing options...
froot Posted September 1, 2022 Author Share Posted September 1, 2022 OK here's a follow up question. Since each data set I would create a page with is a simple php array to begin with, and since I would only return this data in a "Process"-module anyway (the pages themselves are of practically no interest), wouldn't it make more sense to just store the entire array, json encoded in just one (e.g. text-) field? I reckon that way you could add to the data sets more easily and the data would also be more easily accessible for potential further application. What do you think? Link to comment Share on other sites More sharing options...
bernhard Posted September 1, 2022 Share Posted September 1, 2022 I think that pages are a fundamental concept of pw and many things are built around that concept. If you think that storing data in pages is not a good idea, then you'll likely end up in a situation where you can not use some of the great tools that you can use when being aligned with pw concepts... That does not mean that one way is better or worse than the other. It always depends on the situation. But there are not many things in pw that are more fundamental than pages ? Imagine you want to add notifications whenever an entry changes. Using pages: $wire->addHookAfter("Pages::saved", function($event) { // send mail }); Using custom storage solution: No idea - I know why I'm using ProcessWire ? 1 Link to comment Share on other sites More sharing options...
froot Posted September 1, 2022 Author Share Posted September 1, 2022 I agree, pages are easier to use and I got it to work already. I just thought it would be easier and more flexible to store the entire input in json format in a field on that page instead of, when installing the module, creating specific fields for that template. Because if it's just json in a field, it would be much easier to add fields that weren't there at the time you installed the module and more versatile for different users – talk about Nächstenliebe. Does that make any sense? Or maybe there's a more PWish way for that scenario as well… Link to comment Share on other sites More sharing options...
bernhard Posted September 1, 2022 Share Posted September 1, 2022 Sure, if you only need to store data and don't want (need) the overhead of creating fields you can just use json. Have a look at https://processwire.com/api/ref/page/meta/ 1 Link to comment Share on other sites More sharing options...
froot Posted September 1, 2022 Author Share Posted September 1, 2022 thanks! I will try that there's a typo BTW // set and save a meta value $page->meta()->set('colors', [ 'red, 'green', 'blue' ]); missing a ' 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