Jump to content
Sipho

Storing nested data

Recommended Posts

I am trying to create a sort of database system using ProcessWire. I don't want all the data to show up as pages on the website but instead pull it into pages. Similar to the Skyscrapers demo except in that one the data shows up as pages. The data I wish to store is information about types of moths. So family, sub-family, genus and species. Each of these has information associated with it. For example, species has name, images and distribution. This is another example of information about the species. Initially, I attempted to do this using nested repeaters. This appears to work but I feel there is a better and more elegant way. Additionally, this page says: 

Quote

Repeaters aren't infinitely scalable in quantity, so avoid repeaters for quantities of items that you think may need to be infinitely scalable. 

...

It's better to use pages without repeaters when dealing with huge quantities of items. 

So I then tried using pages with children, but this also didn't work well. I had to make every single page unpublished as I don't want them showing up in menus and other places. This means they all have strikethroughs in the admin tree which is very annoying.

Is there a better way of handling this kind of data in ProcessWire or is this maybe not a suitable project for ProcessWire? I apologise if this is a silly question, but I could not find anything on this matter and am still new to ProcessWire.

Share this post


Link to post
Share on other sites

Hi @Sipho,

Welcome to the forums.

Instead of unpublished you could also make them hidden. They won't show in a $pages->find() either unless you explicit ask: $pages->find('include=hidden')'.

Also check out this famous post on how to organise content in ProcessWire with great examples. This will give you good insight on possibilities on how to structure your data.

 

  • Like 2

Share this post


Link to post
Share on other sites

In addition to all the above.

On 2017-7-10 at 8:00 PM, arjen said:

Instead of unpublished you could also make them hidden. They won't show in a $pages->find() either unless you explicit ask: $pages->find('include=hidden')'.

 @Sipho If you want to make sure hidden pages never show up accidentally (say they have a template, guest access, and someone happens to know/figure out its URL) then you can turn hidden into password protected with @adrian's great PageProtector module easily:

Another tip when dealing with related data: you might want to take a look at @Robin S's cool module:

Hope this helps too.

  • Like 2

Share this post


Link to post
Share on other sites

So after looking at 

and looking at my data again I came up with the following structure:

Capture.PNG.54fbd659269ce1a75ddd3fe6442c804d.PNG

The structure is families -> family -> subfamily -> genus -> species

This is how I originally thought of doing it, but I thought it would cause problems when I wanted to add new species and filter data. However, I have now realised that having a good page structure is very desirable. This way, people can link to the individual categories or browse through them but I can still have a separate page that references them and can filter through them.

Thanks for the help!

Also, I am loving how easy it is to use ProcessWire! It's much better than something like WordPress for a task like this. I don't have to constantly fight the system :)

 

  • Like 2

Share this post


Link to post
Share on other sites
7 minutes ago, Sipho said:

I am loving how easy it is to use ProcessWire! It's much better than something like WordPress for a task like this.

This is because as the inventor says:

"ProcessWire IS a native category system, whether by structure or relation. I think the distinction is that we don't call them "categories" or "tags". But "does not have" makes it sound like they aren't part of the plan. When in fact, it's one of the underlying purposes of the system."

to read more:

 

  • Like 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Harmen
      I want to add a few pages to an AsmSelect Page field inside a repeater using the following code:
      $trialsPage = wire("pages")->get(28422); // Get the page $trialsPage->of(false); $newTrial = $ordersPage->trial_repeater_orders->getNewItem(); // Add item to repeater foreach ($selectedProducts as $selectedProduct){ $productPage = $pages->get("template=product, reference=$selectedProduct"); $newTrial->trial_selected_products->add($productPage); } $newTrial->save(); $trialsPage->save(); However, when I check the page where the field is located it doesn't have the new values as expected. The selected pages exist, the field is in the right location, made sure that the output formatting is turned off: $page->of(false); But it still doesn't work with a variable. No matter what I try, it doesn't work.
      It only works when I replace $selectedProduct with a hardcoded string. Am I doing something wrong here?
    • By David Karich
      The Page Hit Counter module for ProcessWire implements a simple page view counter in backend. Page views of visitors are automatically tracked on defined templates, with monitoring of multiple page views. This gives you a quick overview of how many visitors have read a news or a blog post, for example, without first having to open complex tools such as Google Analytics. This module quickly provides simple information, e.g. for editors. Or, for example, to sort certain news by most page views. For example for "Trending Topics".

       
      Works with ProCache and AdBlockers. With a lightweight tracking code of only ~320 bytes (gzipped). And no code changes necessary! In addition GDPR compliant, since no personal data or IP addresses are stored. Only session cookies are stored without information. 
      In addition, there are some options, for example filtering IP addresses (for CronJobs) and filtering bots, spiders and crawlers. You can also configure the lifetime of the session cookies. Repeated page views are not counted during this period. It is also possible to exclude certain roles from tracking. For example, logged in editors who work on a page are not counted as page views.

      Sort by hits and access page views (hit value)
      Each trackable template has an additional field called phits. For example, you want to output all news sorted by the number of page views.
      // It is assumed that the template, e.g. with the name "news", has been configured for tracking. $news = $pages->find("template=news, sort=-phits"); To output the page views of a tracked page, use:
      echo $page->phits; Example: Tracking a page hit via API and jQuery
      If you want to track a template that does not represent a full page to automatically inject a tracking script, you can define allowed API templates in the module that you can track. Below is an example of how you can track a click on news tag using jQuery. This will allow you to find out which keywords are clicked the most. For example, you can sort and display a tag cloud by the number of hits. Suppose your keywords have the template "news_tag". The template "news_tag" was also configured in the Page Hit Counter Module as a trackable API template.
      Example PHP output of keywords / tags:
      // Required: the data attribute "data-pid" with the ID of the template to be tracked. echo $pages->find("template=news_tag, sort=-phits")->each("<a href='{url}' class='news_tag' data-pid='{id}'>{title}</a>"); Example Tracking Script with jQuery:
      /** * Required: Data attribute "data-pid" with the ID of the news tag template * Required: Send the POST request to the URL "location.pathname.replace(/\/?$/, '/') + 'phcv1'" * Required: The POST parameter "pid" with the ID of the template */ $(function(){ if($('a.news_tag').length > 0) { $('a.news_tag').each(function(){ var tPID = $(this).data("pid"); if(tPID) { $(this).on("click", function(){ $.post(location.pathname.replace(/\/?$/, '/') + 'phcv1', {pid: tPID}); }); } }); } }); So simply every click on a tag is counted. Including all checks as for automatic tracking. Like Bot Filtering, Session Lifetime, etc.
      _______________________________________________________
      Background: This module is the result of a customer requirement, where the editors are overwhelmed with analytics or no tracking tools were allowed to be used. However, a way had to be found to at least count page views in a simple form for evaluations. Furthermore, by using ProCache, a way had to be found to count views of a page without clearing the cache.
      _______________________________________________________
      Pros
      Automatic Page View Tracking Lightweight tracking code, only ~320 bytes (gzipped) No code or frontend changes necessary Works with ProCache! Even if no PHP is executed on the cached page, the tracking works Works with browser AdBlockers No cache triggers (for example, ProCache) are triggered. The cache remains persistent GDPR compliant, session-based cookie only, no personal information Filtering of IPs and bots possible Exclude certain roles from tracking Ability to reset Page Views Works with all admin themes Counter database is created as write-optimized InnoDB API to track events for templates that are not viewable No dependencies on libraries, pure VanillaJS (Automatic tracking script) Works in all modern browsers Pages are sortable by hits Cons
      Only for ProcessWire version 3.0.80 or higher (Requires wireCount()) Only for PHP version 5.6.x or higher No support for Internet Explorer <= version 9 (Because of XMLHttpRequest()) No historical data, just simple summation (Because of GDPR) Planned Features / ToDos
      API access to hit values Since version 1.2.1 Possibility to sort the pages by hits (Request by @Zeka) Since version 1.2.0 Don't track logged in users with certain roles (Request by @wbmnfktr) Since version 1.1.0 Possibility to reset the counter for certain pages or templates (Request by @wbmnfktr) Since version 1.1.0 Better bot filter Since version 1.1.0 Disable session lifetime, don't store cookies to track every page view (Request by @matjazp) Since version 1.2.1 Option to hide the counter in the page tree (Request by @matjazp) Since version 1.2.1 Option to hide the counter in the page tree on certain templates Since version 1.2.1 API to track events for templates that are not viewable Since version 1.2.2 Changelog
      1.2.3
      Bug-Fix: Tracking script triggers 404 if pages are configured without slash (#3) Reported by @maxf5 Enhancement: Reduction of the tracking script size if it's gzipped (~320 bytes) Enhancement: Documentation improvement Enhancement: Corrected few typos 1.2.2
      New feature: API to track events for templates that are not viewable Enhancement: Documentation improvement 1.2.1
      API access to hit values Use $page->phits Bug-Fix: No tracking on welcomepage (Reported by wbmnfktr; Thx to matjazp) Bug-Fix: Tracking script path on subfolders (Reported by matjazp) Bug-Fix: Tracking on pages with status "hidden" Enhancement: Change database engine to InnoDB for phits field Enhancement: Option to disable session lifetime set session lifetime to 0, no cookies Enhancement: Better installation check Enhancement: AJAX Request asyncron Enhancement: Reduction of the tracking script size by ~20% Enhancement: Option to hide the counter in the page tree You can output the counter with the field name "phits" Enhancement: Option to hide the counter in the page tree on certain templates Enhancement: Option for activate general IP validation Enhancement: Reduction of tracking overhead up to ~30ms Enhancement: Better bot list for detection 1.2.0
      New feature: Sort pages by hits – New field phits Migrate old counter data to new field 1.1.0
      New feature: Exclude tracking of certain roles New feature: Reset Page Views Better bot filter and detection 1.0.0
      Initial release Notes
      By default, the page views are stored as INT in the database. This allows a maximum counter value of 4.2 billion views (4,294,967,295) per page. If you need more, change the type to BIGINT directly in the database. But I recommend to use Google Analytics or similar tools if you have such a large number of users.
      _______________________________________________________
      Download GitHub: ProcessWire Page Hit Counter (Version 1.2.3)
      PW Module Directory: ProcessWire Page Hit Counter (Version 1.2.3)
      Install via ProcessWire (Classname): PageHitCounter
      _______________________________________________________
      Update information
      If you have used version 1.2.1 from the DEV branch, please replace it completely with the new master version.
    • By louisstephens
      So I have a form, once completed, will create new pages. All in all, this is eazy-peezy for me now. I guess I need a bit of guidance on how to actually structure the rest of my code.  I thought I could just write a function (_func.php) and pass the fields to the function and let it do its' thing. However, I am kinda hitting a road block when I do it this way. 
      I currently am passing first name, last name, city, state (options field), and making pages based on the first/last names. I guess where I run into some issues is I am trying to check to see if the "page" already exists, and if it does, throw out an error:
      In the home template:
      if(isset( $_POST['submit'])) { $firstName =Trim (stripslashes($_POST['firstname'])); $lastName = Trim(stripslashes($_POST['lastname'])); $fullName = $firstName . $lastName; $city = Trim(stripslashes($_POST['city'])); $state = Trim(stripslashes($_POST['state'])); $lowerCaseName = strtolower($fullName); $people = $pages->find("template=person"); foreach ($people as $person) { $checkFirstName = $person->first_name; $checkLastName = $person->last_name; $checkFullName = $checkFirstName . $checkLastName; if ($checkFullName === $lowerCaseName) { echo "<p>" . "This person has already created a page. Please choose a different name." . "</p>"; } else { echo "hey"; processNewPerson(need_to_pass_person_details_to_function); } } // end foreach In _func.php:
      function processNewPerson($list) { $u = new Page(); $u->template = "person"; $u->parent = wire('pages')->get("/people/"); $u->title = ; $u->first_name = ; $u->last_name = ; $u->state = ; $u->city = ; $u->save(); $u->setOutputFormatting(false); } I am a little unsure of how to actually pass all the information to the template, as well as if this is even the best approach to do this. Would it make more sense to do this in a class, or keep it the way it is?
    • By quickjeff
      Hi Guys,
      Right now, I am using parents as breadcrumbs but I have pages under a parent page just to keep things organized. The pages are called in other areas of the site. 
      I am trying to create user path history breadcrumbs.
      Meaning: If the user clicked a link to the page, it will show the path he took. Has anyone done this? Would love to see who has before I dive in.
      Thanks. 
    • By sam-vital
      Hi,
      I'm creating a News/Updates section for a client and they would like the 3 most recent Updates previewed on the home screen. So this would be Title and Date Posted. These blog posts will be child pages of a News and Updates page, which is a child of the Home page. So it's like Home -> News -> Blog posts. I don't need this to be a nav menu, just something to show the newest updates.
      All help is appreciated 🙂
×
×
  • Create New...