Where to put a "miscellaneous" function and how to call it within the PHP and Mysql: Novice to Ninja Framework

I am creating a website using the framework in this book and I’m at a point where I need to add “miscellaneous” functions.

For example, I have a requirement to display (in layout.html.php) a number and its ordinal (29th as opposed to just 29). I have the function to do this:

function ordinal($number)
    {
    $ends = array('th','st','nd','rd','th','th','th','th','th','th');
    if ((($number % 100) >= 11) && (($number%100) <= 13))
        return $number. 'th';
    else
        return $number. $ends[$number % 10];
    }

I can call this with:

 echo ordinal(29);

Ok, my problem is (and I suppose this is because I am still learning to structure code in a framework) is:

  1. Not sure WHERE to put the function, and

  2. How to call it from THAT location

Here’s what I’ve tried and how I’ve thought about it…

The function is something I could use in ANY website so it could go into the framework part of the site rather than the specific-project part. I’ve called my framework… er… Framework (as opposed to Ninja in the book). Also, thinking ahead, I may have other useful, but miscellaneous, functions.

So, I created a class called FunctionLibrary (which I may later split into separate classes if logical groups emerge) and added it to the Framework namespace. And I put my function in there.

Here we go:

<?php

namespace Framework;

class FunctionLibrary
{

    public function __construct()
    {
        
    }


    function ordinal($number)
    {
    $ends = array('th','st','nd','rd','th','th','th','th','th','th');
    if ((($number % 100) >= 11) && (($number%100) <= 13))
        return $number. 'th';
    else
        return $number. $ends[$number % 10];
    }
}

So…

  1. Is this logic (to put the function here) good?
  2. If so, is the class OK (little bit new to custom classes and unsure about that empty constructor - used to passing stuff in)
  3. If so, how can I call it from my template? I have tried:
echo ordinal($years);
echo FunctionLibrary ordinal($years);
echo Framework\FunctionLibrary ordinal($years);

I don’t think I need a leading slash, this is not a built-in function. None of these work:

Fatal error: Uncaught Error: Call to undefined function ordinal() in /var/www/<domain>/templates/layout.html.php on line *228*

Ideas?

You have a couple of things going on here so lets start with the basics and then maybe do some refining.

The thing to understand is that in spite of the keyword ‘function’, class methods are not actually functions. Functions are global in nature and are not defined within a class. So the code you posted will not work as you expect it to.

Here is an example using actual functions and two php files:

<?php
# File: functions.php

function ordinal($number) {
    return 'Ordinal ' . $number . "\n";
}

<?php
# File: main.php

require_once 'functions.php';

echo ordinal(42);

Notice the require_once statement. This tells php to basically load the functions.php file and make the functions defined in it available. You would typically have this statement somewhere in your startup code. You can of course add additional functions to functions.php.
It’s a pretty common pattern.

I would suggest making these two file and actually running the code from the command line with “php main.php” just to understand the details of what is happening.

There are of course other approaches. What you posted was sort of trying to use more of a class based approach. Which is certainly doable but will require some tweaks.

1 Like

ahundiak,

Thank you very much for your response.

Yes, you have reminded me: this is not a method, it’s a function. And that explains my concern about the empty constructor… no need for one as it’s not a class.

I have kept the FunctionLibrary.php file I had but removed the constructor and I have “included” it directly in the master template for now. This works but is not logical within the framework created in the book.

I could have used a require instead and put it in a controller and just returned the result but it is accessed from the master page template which doesn’t have a controller. I need to consider some more.

However, thank you. You did clear up my mistake of treating it like a method.

One thing… would you still keep the functions file within a namespace and, if so, would this affect how it was called?

You can use the NumberFomatter class to put ordinals on integers.
https://www.php.net/manual/en/class.numberformatter.php

1 Like

Here is a slightly changed version of the original code which shows using a namespace:

# functions.php
namespace Obama;
function ordinal($number) {
    return 'Ordinal ' . $number . "\n";
}
# main.php
require_once 'functions.php';
echo \Obama\ordinal(42);

You don’t actually see too many namespaced functions.

I think what you are really looking for is static class methods.

1 Like

SamA74,

Thanks. I was unaware of that and will look into it.

ahundiak,

Cheers. I’ll read up on those and thanks for the alteration: makes sense.

It’s not a direct answer to the question, but worth noting there is an existing class that can deal with ordinals.
Just a simple example to show it in action:-

$numbers = range(1,24);	// Array of numbers, 1 to 24
	
$nf = new NumberFormatter( 'EN_gb' , NumberFormatter::ORDINAL );  // Instantiate formatter
	
foreach($numbers as $n){
		echo $nf->format($n) . "<br>\n"; // Call format method on each number
}

But it is still worth learnig how to expand upon the framework built in the book, with your own custom functions/classes/methods, when you do need them.

1 Like

Thank you, Sam.

Yes, agreed with everything you’ve said there. I usually find built in PHP functions very good, so good it’s not worth doing it your own way but, yes, knowing how to is important.

Cheers for the guidance, I appreciate that.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.