Jump to content

Trying to create progress bars for Processwire generated cards.


Recommended Posts

I was hoping to be able to do this entirely in PHP but was having all kind of issues getting it to see my values as numbers instead of strings (got error messages because my PW debugging is currently set to true). I currently have about 10 cards that PW is generating that include thumbnails, descriptions, donation amounts (raised amounts and goal amounts), and donate buttons. What I was trying to do was take the goal amount divide it by the raised amount (using PHP) and simply insert that value into the Progress element's Value attribute. Sounded simple enough but I couldn't get PHP to simply divide those two fields. First I tried dividing the goal value by the raised value and inserting it into the value attribute, like so:

<? php
$raised = $page->get("raisedAmount$count");
$goal = $page->get("goalAmount$count");
$percent = $goalNum / $raisedNum;
?>

<progress value="<?php echo $percent; ?>" max="100"></progress>

Which gave me this error message:

Uncaught TypeError: Unsupported operand types: string / string

Then I tried converting the two strings to integers because apparently PHP couldn't detect they were numbers and do it, like so:

<?php
$raised = $page->get("raisedAmount$count");

$goal = $page->get("goalAmount$count");

$goalNum = (int) $goal;
$raisedNum = (int) $raised;

if ($raisedNum != 0) :
	$percent = $goalNum / $raisedNum;
else:
	$percent = 0;
endif;
?>

<progress value="<?php echo $percent; ?>" max="100"></progress>

but all of the progress bars remain at zero percent (not shown), even when I have values in some of the $raised variables.

Please note, if I add this code:

<?php echo $percent; ?>

below the Progress element, it shows 0 on every single card, so the $percent is never calculated (as per the $percent = $goalNum / $raisedNum;) even though $raisedNum should not equal 0 during that iteration of the loop (the original code includes a loop, which I omitted to keep the code sections above smaller, notice the $count at the end of the $raised and $goal variable declarations). When the loop goes over "raisedAmount1" there is a value in there; however, after typecasting it to an integer ($raisedNum) the value is 0 for someodd reason instead of 40,000, which is what is in the $raisedAmount1 field in Processwire...

I'm new to relatively new to PHP and Processwire and could really use some help on this one. Thanks in advance for any helpful replies!

Link to post
Share on other sites

What are raisedAmount$count and goalAmount$count you’re getting with $page->get? Fields that contain a dollar sign? Or is $count supposed to be a subfield of raisedAmount/goalAmount ? I’ve never seen a construction like that with dollar signs in, usually you do $page->field or $page->get('field') and field names cannot contain dollar signs, as far as I know. So what are the results of those two get calls if any and what are their types when you ask for gettype($goal) or gettype($goalNum)?

 

Link to post
Share on other sites

Hello Spercy16,

Firstly I don't think it is good practice (or possibility at all) to use dollar sign in fields name - raisedAmount$count - really bad practice to my opinion. Continue using camelCase style or add underscore - raisedAmountCount or raisedAmount_count. 

First error: In your first example - you are calling variables $goalNum and $raiseNum without declaring them at all. That is why these variables are empty. 

Second problem: raisedAmount$count and goalAmount$count are fields or pages? Get rid of dollar sign in field name and use direct aproach for calling fields in this scenario. $page->raisedAmountCount etc. (page->get documentation). 

Also do not typecast these variables in your code. If this field should contain only integer values than change field type in processwire to Integer. 

Really your main problem are fields you are calling raisedAmount$count. Is this the field name? Or is it child page with another field $count? Maybe give us more information about your field and page structure to tell you right way to call these fields. 

<? php

$raised = $page->raisedAmountCount; //if these fields are integer type
$goal = $page->goalAmountCount;

$percent = $goal / $raised; // You will change this, because you are calling not existing vars
?>

<progress value="<?php echo $percent; ?>" max="100"></progress> <!-- This should be working without any problems -->

 

Link to post
Share on other sites

Cehlo,

Firstly, in PHP you do not have to declare variables before assigning values to them... In other languages like C, C++, and Java you do, but not PHP.

Second, I have used raisedAmount$count and goalAmount$count in other places and they work correctly. $count is another variable that starts with 0 and increments each iteration through the loop (outputting my cards, as mentioned). Here is the full code:

<?php
    // https://processwire.com/api/arrays/
    // check if the array of images has items
    if (count($page->images)) :

     // get array of images from the field
     $images = $page->images;

     $count = 0;

     // iterate over each one
     foreach ($images as $image) :

      $count++;

      $sectionText = $page->get("paragraph_$count");

      $buttonCode = $page->get("url_$count");

      $options = array( 'quality' => 70 );

      $img = $image->size(550, 400, $options);

      $raised = $page->get("raisedAmount$count");

      $goal = $page->get("goalAmount$count");

      $goalNum = (int) $goal;
      $raisedNum = (int) $raised;

      if ($raisedNum !== 0) :
       $percent = $goalNum / $raisedNum;
      else:
       $percent = 0;
      endif;

    ?>

<span id="card<?php echo $count?>" class="card">

  <img class="cardThumb" src="<?php echo $img->url; ?>" alt="<?php echo $image->description; ?> Thumbnail" />

  <div class="cardBody">

    <div class="cardText">
      <h2><?php echo $image->description; ?></h2>
      <?php echo $sectionText; ?>
    </div>

    <div class="progressBarSection">
      <progress class="progressBar" id="progressbar<?php echo $count; ?>" value="<?php echo $percent; ?>" max="100"></progress>
      <span class="raisedAmount">
        <?php echo $raised; ?> ksh
      </span>
      <span class="goalAmount">
        <?php echo $goal; ?> ksh <?php echo $percent; ?>
      </span>
      <span id="raisedNum<?php echo $count?>" class="hidden">
        <?php echo $raised; ?>
      </span>
      <span id="goalNum<?php echo $count?>" class="hidden">
        <?php echo $goal; ?>
      </span>
    </div>

    <div class="primaryBtn">
      <a href="https://www.paypal.com/donate?hosted_button_id=
               <?php echo $buttonCode; ?>
               &source=url">
        <button>
          <i class="fas fa-donate"></i> Donate
        </button>
      </a>
    </div>

  </div>

</span>

<?php
     endforeach;
     endif;
    ?>

Sorry, should have just included this in the original post. It makes a lot more sense when you can see the whole structure of the cards.

As you can see I'm using $count successfully in the $sectionText and $buttonCode variables (paragraph_$count and url_$count respectively). I've been using the variables this way in PHP for a while and have had zero issues thus far. Also, when I echo $goal and $raised in the span elements in my html they display the correct values. The current problem I'm experiencing isn't with using $count when declaring variables, it's when trying to typecast the values into integers directly below that.

You suggested to use $page->raisedAmountCount to call fields, but you need to understand that by using $count here you are able to use a loop so that each time through it uses the next value (i.e. it's really grabbing $page->raisedAmount1, $page->raisedAmount2, etc. each run through it). I have numerous raisedAmount fields in my page (1-15) and listing them out individually would be incredibly inefficient. This is what i++ was created for, one of the several reasons anyways... If there is a more proper way to write that code and get the same results, efficiently, I'm all ears, but the way I am using those variables is working in all of the other declarations I've used them in, and from what I do understand about programming is exactly how you should use variables like that.

Hopefully the full code will help make what I'm trying to do a bit easier to understand.

Link to post
Share on other sites

This is how I would typically write those declarations (and I'm sure is the better, more proper way) but they do seem to work either way:

$sectionText = $page->get("paragraph_".$count);

 

Link to post
Share on other sites

Ah, okay, I see. It was a bit confusing without knowing the context. But what values/types exactly do you get after typecasting $goal and $raised? Did you try intval($val) instead of (int) $val?

Link to post
Share on other sites

You still didn’t reveal your results. Could you do something like that to see the four values and their according types?

$raised = $page->get("raisedAmount$count");
$goal = $page->get("goalAmount$count");
$goalNum = (int) $goal;
$raisedNum = (int) $raised;

echo $raised;
echo gettype($raised);
echo $goal;
echo gettype($goal);
echo $goalNum;
echo gettype($goalNum);
echo $raisedNum;
echo gettype($raisedNum);

Normally it shouldn't be much of a problem to divide two integers in PHP, so I suspect it to be slightly more hidden.

Link to post
Share on other sites

Now it is a lot clearer. Yes you are right in both points. Either way from your first post it was not certain. 

Regarding variables you are right, but in your first post your first php input was using variables without giving them value. So $percent = $goalNum / $raisedNum; will give you everytime 0, becasue variables $goalNum and $raisedNum are empty. But I can see from your next post that you are giving them values so it was just misunderstanding. 

If count is another variable it is also without problems from your full code, consider my first post as irrelevant then.  i

Ok and what about your fields? Are they Integer or Text fields? Can you change them and avoid typecasting at all?

 

 

 

Link to post
Share on other sites

Cehlo,

Bypassing typecasting worked. I had to create all new fields in ProcessWire (kind of a pain that I couldn't simply change the types from text to integers...) but now everything works. Thanks for all of your help!

Link to post
Share on other sites
2 minutes ago, cehlo said:

I am happy it worked 🙂

I am happy too! Though I don't understand why the typecasting didn’t work, (int) "40000" (or intval("40000")) should result in 40000, not 0. Strange …

Link to post
Share on other sites

As far as I know in PHP a quotient of integers with a non-integer value is treated as float.

So I'd try to cast the $percent value:  

$percent = (int) $percent;

or

$percent = intval($goalNum / $raisedNum);

Link to post
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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Robin S
      Lister Selector
      A Process module that uses Lister/ListerPro, but with a selector string input instead of the normal InputfieldSelector filters.
      Features
      For power users, typing a selector string is often faster and more intuitive than fiddling with InputfieldSelector. It also lets you copy/paste selector strings that you might be using somewhere else in your code.
      Allows the Lister rows to be sorted by multiple fields (not possible in Lister/ListerPro)
      Allows the use of OR-groups (not possible in Lister/ListerPro)
      If ListerPro is installed you can run ListerPro actions on the listed pages - the available actions are defined in the module config.
      Bookmarks can be configured in the module config and accessed via the flyout menu for the module page. For your convenience you can copy/paste a bookmark string from the note at the bottom of the Lister Selector results.
      Usage
      Type your selector string on the Selector tab. The selector is applied when the "Selector string" field is blurred, so hit Tab when you have finished typing your selector.
      Unlike Lister/ListerPro, you can't sort results by clicking the column headings. Control the sort within the selector string instead.
      Superusers can jump to the module config (e.g. to create a bookmark) by clicking the cog icon at the top right of the module interface.
      The module is mostly intended for use by superusers, because in most cases site editors won't understand the ProcessWire selector string syntax. If you want another role to be able to access Lister Selector then give the role the "lister-selector" permission. Only superusers can define bookmarks because in ProcessWire module config screens are only accessible to superusers.
      Screenshots
      Process page

      Module config (when ListerPro is installed)

      Advanced
      If for any reason you want to create dynamic bookmark links to Lister Selector for a given selector you can do that like this:
      /** @var $pls ProcessListerSelector */ $pls = $modules->get('ProcessListerSelector'); // Define selector $selector = "template=foo, title%=bar"; // Define columns (optional) $columns = 'title,modified'; $pls_link = $pls->getProcessPage()->url . '?bm=' . $pls->urlSafeBase64Encode($selector . ':' . $columns); echo "<a href='$pls_link'>My link</a>";  
      https://github.com/Toutouwai/ProcessListerSelector
      https://modules.processwire.com/modules/process-lister-selector/
    • By SwimToWin
      I have a nested page structure that fails for users without superuser permissions:
      Works for superusers / non-superusers:
          - foo
          -- bar
          --- page (status: published)
          ---- page (status: published)
          --- page (status: published)
      Fails for non-superusers (Works for superusers):
          - foo
          -- bar
          --- page (status: published)
          ---- page (status: published)
          --- page (status: unpublished <- apparently the template structure fails when there's one unpublished page)
      Template:
      <?php foreach ($page->children('include=all') as $p): #Fails for non-superusers ?> <?=$p->render()?> <?php endforeach; ?>     a) Works for non-superusers when I grant Page Edit permissions (on the template) to their assigned role/s.
          b) When I remove 'include=all' or 'include=unpublished' then it also works for non-superusers:
      <?php foreach ($page->children() as $p): #Works for non-superusers ?> <?=$p->render()?> <?php endforeach; ?> Error message (non-superusers)
          Internal Server Error
              The server encountered an internal error or misconfiguration and was unable to complete your request.
              Error has been logged.
          /www/site/assets/logs/errors.txt
              /foo/bar/baz/    Error:     Exception: Page '/foo/bar/baz/quz/' is not currently viewable.
          /www/site/assets/logs/exceptions.txt
              /foo/bar/baz/    Page '/foo/bar/baz/quz/' is not currently viewable. (in /wire/modules/PageRender.module line 410)
      Debug (non-superusers)
          Error: Exception: Page '/foo/bar/baz/quz/' is not currently viewable. (in wire/modules/PageRender.module line 410)
          #0 wire/core/Wire.php (397): PageRender->___renderPage(Object(HookEvent))
          #1 wire/core/WireHooks.php (823): Wire->_callMethod('___renderPage', Array)
          #2 wire/core/Wire.php (465): WireHooks->runHooks(Object(PageRender), 'renderPage', Array)
          #3 wire/core/WireHooks.php (924): Wire->__call('renderPage', Array)
          #4 wire/core/Wire.php (465): WireHooks->runHooks(Object(Page), 'render', Array)
          #5 site/templates/template.php (191): Wire->__call('render', Array)
       
    • By FireWire
      Hey all. I'm having an issue with the new custom page classes feature which is a fantastic tool.
      I am running into a recursion issue when attempting to call a custom page class. I have a class called BlogPostPage.php (for blog-post.php) which contains a method called getSummary(). That method gets a summary field or truncates the body in it's absence. I've attached photos of the template code, custom page class code (which I've simplified for testing), and the PW output error.
      There is no recursion in the getSummary() method. This error occurs whether I output multiple blog posts in a loop or if I output one blog post with no looping in my template code.

      In use:
      ProcessWire 3.0.164 dev
      PHP 7.3.13

      I am also using the Template Engine Twig module which has not caused any errors or issues thus far.
      Many thanks!



    • By neonwired
      I'm hoping someone has seen this before. There doesn't appear to be an issue with the user info.

       

    • By EyeDentify
      Hello Dear PW Gurus.

      Hope you fair well in these Corona Crisis times.

      Anyhow, i have a problem with a Cryptic error message that shows up when i am trying to Delete images out of a Images field.
      The Error message does say a little but it does not make sense to me why i can´t delete the images because of it.

      Is it some permission issue perhaps?

      I will attach screenshots of it and what i did prior to it.
      I am from sweden so ignore the funny words here and there.

      Hope you all can send me on the right track.
      i am running PW 3.0.139 on this install.

      Step1:

      Step 2: Select the images with the trashcan symbol

       
      Step 3: Cryptic Error message

      I am scratching my head on this one, have not seen this before.

      Thankfull for all help.
      /EyeDentify
×
×
  • Create New...