Jump to content

how do I pass PW variables to my module?


fruid
 Share

Recommended Posts

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

@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

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();

 

  • Like 3
Link to comment
Share on other sites

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 ?

  • Like 4
Link to comment
Share on other sites

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

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',
      ],
    ],
  ],
]);

 

  • Like 2
Link to comment
Share on other sites

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

  • 1 month later...

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

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 ? 

  • Like 1
Link to comment
Share on other sites

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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...