PHPackages                             natecollins/nofus - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. natecollins/nofus

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

natecollins/nofus
=================

Nate's One-File Utilities Stash: Simple Single-use Classes for Common Tasks

v0.2.1(5mo ago)23.3k↓30%3[2 PRs](https://github.com/natecollins/nofus-php/pulls)BSD-2-ClausePHPCI passing

Since Nov 8Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/natecollins/nofus-php)[ Packagist](https://packagist.org/packages/natecollins/nofus)[ RSS](/packages/natecollins-nofus/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (9)Used By (0)

NOFUS: Nate's One-File Utilities Stash
======================================

[](#nofus-nates-one-file-utilities-stash)

About NOFUS
-----------

[](#about-nofus)

A collection of single purpose classes for common tasks, focusing on simple and straightforward use. Each class can be taken and used individually and requires no external code dependencies.

**Classes**

- [ConfigFile.php](#configfilephp) - Easy parser for config files
- [Logger.php](#loggerphp) - Simple logger class with built-in file logging implementation
- [DBConnect.php](#dbconnectphp) - Quick, safe interface for making MySQL/MariaDB queries
- [UserData.php](#userdataphp) - Simple validator for user data

Installation
------------

[](#installation)

The recommended method of installation is to use [Composer](https://getcomposer.org/). However, if all you need is a specific file, it can be downloaded independently and will work without any of the other files present.

To install via composer:

```
composer require natecollins/nofus

```

ConfigFile.php
--------------

[](#configfilephp)

A class to read in plain text config files.

- Simple "variable = value" syntax
- Allows quoted string values
- Allows line comments, including end line
- Allows variable scopes
- Allows scope section definitions
- Allows valueless variables
- Allows multiple values per variable name
- Can enumerate available scopes
- Can preload default values

**Sample Config File**:

```
####################################################
# My Config File
# Comment style 1
// Comment style 2

email = me@example.com
name = John Doe     # End line comments allowed
debug_mode
nickname = " John \"Slick\" Doe "
date.birth = 1975-02-18

[address]
home.line_1 = 123 Rural Rd
home.state = Ohio
home.city = Delta

work.line_1 = 456 Main St.
work.line_2 = Acme Corporation
work.state = Ohio
work.city = Napoleon

[children]
name = Alice
name = Bobby
name = Chris

```

**Examples:**

```
use Nofus\ConfigFile;

# Create config file object and attempt to load it
$cf = new ConfigFile('app.conf');

if (!$cf->load()) {
    echo "Could not load file!" . PHP_EOL;
    print_r( $cf->errors() ); // an array of reasons for failure to load
    exit(1);
}

####################################################
# Optionally preload default values (will NOT override already loaded values)
$cf->preload(
    array(
        "email"=>"root@localhost",
        "debug_mode"=>false,
        "address.home.city"=>"Kalamazoo",
        "address.home.state"=>"Michigan"
    )
);

####################################################
# Simple Variable
$email = $cf->get('email');
// if the email variable exists in the file, returns it as a string; if not, returns null

####################################################
# Simple Variable with Default Value
$phone = $cf->get('phone', '555-1234');
// if the phone variable exists in the file, returns it as a string; if not, returns '555-1234'

####################################################
# Simple Valueless Variable
$debug = $cf->get('debug_mode', false);
// valueless variables return true if they exist, otherwise returns the custom default of false

####################################################
# Get Quoted Value
$nickname = $cf->get('nickname');
echo "==${$nickname}==";
# will print: == John "Slick" Doe ==

####################################################
# Get Variable with Scope
$birthdate = $cf->get('date.birth');

####################################################
# Get Scope, Example 1
$home = $cf->get('address.home');
$home_line_1 = $home->get("line_1");

####################################################
# Get Scope, Example 2
$addresses = $cf->get('address');
$work_line_1 = $addresses->get("work.line_1");

####################################################
# Get Array of Values
$first_child = $cf->get("children.name");
$children = $cf->getArray("children.name");
// value of $first_child would be the string 'Alice'
// value of $children would be the array: ('Alice','Bobby','Chris')

####################################################
# Enumerate available scopes
$scopes1 = $cf->emumerateScope("address.work");
$scopes2 = $cf->emumerateScope();   // Default enumerates top level scope
// value of $scopes1 would be the array: ('line_1','line_2','state','city')
// value of $scipes2 would be the array: ('email','name','debug_mode','nickname','date','address','children')
```

**Loading only loads the first time**
Calling the `load()` method only parses and loads the config file the first time for any ConfigFile object. Subsequent calls check if the file was successfully loaded the first time, and then doesn't bother to re-parse.

If you want to force a config file to re-load a file, you must first `reset()` the ConfigFile object and then `load()` it again. Note that this will also clear out any `preload()` variables, so you will have to `preload()` them again after calling `reset()`.

```
$cf->reset();
$cf->load();
```

Logger.php
----------

[](#loggerphp)

A class to create logs, with a built-in simple file-logging implementation

- Very simple to setup and use
- Can register custom logger implementations to replace built-in file-logger
- Can specify log levels

Examples:

```
use Nofus\Logger;

# Initialize logger with built-in file logger; default level logs all levels
Logger::initialize('/path/to/file.log')

# Initialize logger with customize logger levels
Logger::initialize('/path/to/file.log', Logger::LOG_ERROR | Logger::LOG_CRITICAL);

# Disable logger
Logger::disable();

# Register custom logger instance which must implement `LoggingInterface`.
Logger::register( new CustomLogger() );

# Make log entries
Logger::debug("Debug!");
Logger::notice("Notice!");
Logger::warning("Warning!");
Logger::error("Error!");
Logger::critical("Critical!");

# Log entry which includes an exception stack trace
try {
    intdiv(1, 0);
}
catch (DivisionByZeroError $exc) {
    Logger::info("Caught something.", $exc);
}
```

DBConnect.php
-------------

[](#dbconnectphp)

A class to handle MySQL/MariaDB compatible database connections. Features include:

- Automatic failover between multiple servers
- Safe escaping of data via prepared statements
- Based off PDO extension
- Query tracking
- Query construction emulation (for debugging)
- Safe escaping of user supplied table and column names
- Single SQL connection shared among all instances

**Required Libraries**

- PDO
- MySQL

On Ubuntu, this can be installed via:

```
apt install php-pdo-mysql

```

**Establishing a Connection**Establishing a connection to SQL server requires an array object to be passed. This array must contain at least one set of server authentication parameters, including `host`, `username`, `password`, and `database`. More than one set of parameters can be passed if you have redundant SQL servers, in which case each server will be tried in-order until a connection is established or there are no connection left to try.

Pass the array of connection parameters to the `DBConnect` object to prepare your connection.

```
use Nofus\DBConnect;

$sql_servers = array(
    array(
        'host'=>'primarymysql.example.com',
        'username'=>'my_user',
        'password'=>'my_pw',
        'database'=>'my_db'
    ),
    array(
        'host'=>'secondarymysql.example.com',
        'username'=>'my_user',
        'password'=>'my_pw',
        'database'=>'my_db'
    )
);

$db = new DBConnect($sql_servers);
```

**Executing Queries**
To execute a query, you pass a query string and an array of values to the `query()` method. If there are no values, you can omit the second argument. All queries are processed as prepared queries.

Return values are dependent on the type of query that is run. `SELECT` queries return an array of rows; `INSERT` queries return the unique id of the new row or `null` otherwise; `DELETE`and `UPDATE` queries return the number of rows affected.

Additional means of running queries include:

- `queryRow` Only the first row of results is returned. If no rows are found, returns null.
- `queryColumn` Returns an array containing the values of a specific column. By default, the first column is used.
- `queryLoop` &amp; `queryNext` For gathering results one row at a time. See examples below.
- `queryPrepare` For manually creating a prepared query, with the ability to re-use it multiple times.

*Example Queries*:

```
####################################################
# Simple Query
$query = "SELECT firstname, lastname FROM users WHERE age > ? AND lastname != ?";
$values = array(21, "Smith");

$names = $db->query($query, $values);

foreach ($names as $row) {
    echo "{$row['lastname']}, {$row['firstname']}";
}

####################################################
# Labeled Placeholders
$query = "SELECT firstname, lastname FROM users WHERE hair_color = :hair";
$values = array(":hair"=>"brown");

$names = $db->query($query, $values);

####################################################
# Single Row Query
$query = "SELECT firstname, lastname FROM users WHERE user_id = ?";
$values = array(42);

$row = $db->queryRow($query, $values);

if ($row !== null) {
    echo "{$row['lastname']}, {$row['firstname']}";
}

####################################################
# Argument Expansion Query (requires anonymous placeholder: ?)
$user_id_list = array(2,3,5,7,11)
$query = "SELECT firstname, lastname FROM users WHERE user_id IN (?)";
$values = array($user_id_list);

$names = $db->query($query, $values);

foreach ($names as $row) {
    echo "{$row['lastname']}, {$row['firstname']}";
}

####################################################
# Column Query
$query = "SELECT number FROM phone_directory WHERE city = ?";
$values = array('Kalamazoo');

$phone_numbers = $db->queryColumn($query, $values);
// will contain an array of the values from the 'number' database column

####################################################
# Column Query (selected)
$query = "SELECT number, unlisted, area_code FROM phone_directory WHERE city = ?";
$values = array('Kalamazoo');

$area_codes = $db->queryColumn($query, $values, 2); // 2 = 3rd column, 0-based index
// will contain an array of the values from the 'area_code' database column

####################################################
# Loop Over Large Resultset Query
$query = "SELECT firstname, lastname FROM phone_directory WHERE country = ?";
$values = array('US');

$db->queryLoop($query, $values);
while ($row = $db->queryNext()) {
    echo "{$row['lastname']}, {$row['firstname']}";
}

####################################################
# Re-using Prepared Statements (argument expansion not permitted)
$query = "SELECT * FROM users WHERE lastname = ?";
$prepared = $db->prepare($query);

$lastnames = array('Smith','Cooper','Harris');
for ($lastnames as $lname) {
    $users = $db->query($prepared, array($lname));
    echo "Found ".count($users)." users with a lastname of ${lname}";
}

####################################################
# Insert Query
$query = "INSERT INTO users (firstname, lastname) VALUES(?,?)";
$values = array('John', 'Doe');

$user_id = $db->query($query, $values);
// returns the last insert id on success, or null on failure

####################################################
# Update Query
$query = "UPDATE users SET lastname = ? WHERE user_id = ?";
$values = array('doe', 42);

$update_count = $db->query($query, $values);
echo "Updated {$update_count} rows.";

####################################################
# Delete Query
$query = "DELETE FROM users WHERE user_id = ?";
$values = array(33);

$delete_count = $db->query($query, $values);
echo "Deleted {$delete_count} rows.";

####################################################
# Safe Table and Column Name Escaping
# (safe from SQL injections; you should still use caution to prevent other shenanigans)
$safe_table = $db->escapeIdentifier($table);
$safe_column = $db->escapeIdentifier($column);
$query = "SELECT firstname, lastname FROM {$safe_table} WHERE {$safe_column} = ?";
$values = array(42);

$names = $db->query($query, $values);

foreach ($names as $row) {
    echo "{$row['lastname']}, {$row['firstname']}";
}
```

**Showing Errors and Debug Information**
By default, an uninformative message is thrown on Exceptions. To enable automatic display of detailed errors and output of query information during development, make sure you enable debugging information:

```
$db->enableDebugInfo();         // See descriptive errors, and dumps error info into output stream
```

To enabled detailed exception messages, but disable auto-dumping query error information to the output stream:

```
$db->enableDebugInfo(false);    // See descriptive errors, but no dumping into output stream

```

Alternatively, you can manually retrieve the error information after catching the Exception:

```
echo $db->getErrorInfo();       // Manually get error info

```

**Throwing Exceptions**
The `silentErrors()` method will set the `PDO::ATTR_ERRMODE`. By default, PDO exceptions will be thrown.

```
$db->silentErrors();        // disables exceptions on MySQL errors
$db->silentErrors(true);    // also disables exceptions on MySQL errors
$db->silentErrors(false);   // an exception will be thrown on MySQL errors from this connection
```

**Setting PDO Attributes Manually**
You can always set PDO Attributes maually with the `setPDOAttribute()` method. This takes a PDO constant and an appropriate value and sets the attribute when creating a connection. If an attribute is set to `null`, then that previously set attribute is removed and will not be set. If a database connection had previously been established, calling this method will disconnect it, forcing a new connection with the updated attribute when the next query is called.

```
$db->setPDOAttribute(PDO::MYSQL_ATTR_COMPRESS, 1);
```

**Sanitizing Identifiers**
Table and column names are not typically something you want to use variables for, but there are rare circumstances where it might be needed. By calling `escapeIdentifier()`, you can ensure your identifer is sanitized and safe from SQL injection attacks. This is accomplished by querying the database for all valid table and column names, and only if the passed identifier exactly matches an existing database identifier pulled from the database is it considered safe. If the identifer is not safe, an empty string is returned.

*NOTE*: This only checks that the identifier is valid in the database. You should still **never** trust user supplied data for use in your queries.

For performance reasons, this method only queries the database for identifiers the first time it is called. The method caches the results and any subsequent calls make use of the data previously loaded.

An optional second boolean parameter can be passed if you want to specify that the resulting identifier should not be backtick quoted.

```
$column = $obj->getColumnMatch();   // NOT user supplied data

// $safe_column = $db->escapeIdentifier($column);        // by default, result is escaped with backticks
$safe_column    = $db->escapeIdentifier($column, false); // or you can have it not escape with backticks

if ($safe_column == '') {
    echo "Unable to match column!";
    exit(1);
}
$query = "SELECT * FROM books WHERE {$safe_column} = ?";
$values = array( $obj->getColumnValue() );
$results = $db->query($query,$values);
```

**Load Balancing Multiple Servers**
Not a true load balancer yet, the `loadBalance()` method will shuffle the order in which servers are connected to. Obviously, this must be called before any queries are run and any connections are established.

```
$db->loadBalance();
```

**Forcing a Connection to End**
You can force a connection to a database to end by calling the `close()` method. This method does nothing if the connection is already closed.

```
$db->close();
```

**Get Database Hostname**

```
// prints the domain string used for the 'host' when the current connection was created
$db->getHost();
// if no connection exists or if the connection was closed, empty string will be returned
$db->close();
$db->getHost(); // returns ''
```

**Get Database Name**
Returns the name of the database currently connected. If no database is connected, will attempt to connect to one and return it. If it cannot connect to any databases, it will return an empty string.

```
$db->getDatabaseName();
```

**Debugging a Query**
To dump the PDO debugParams and get a copy of the query string for the last query run, you can call the `getLast()` method. If you ran series of querys as a transaction, then it will include all queries that were part of that transaction.

```
$db->getLast()
```

To emulate a query before it's run and see what it will likely be combined as, you can call either the `queryReturn()` or `queryDump()` methods. The first of which emulates joining the query and values together and returns it as a string; the latter which does the same, but dumps the query to stdout.

```
$debug = $db->queryReturn($query,$values);
$db->queryDump($query,$values);
```

**Grabbing a List of Enum Values**
If a table column is an enum, you can get and array containing all possible enum values by calling the `enumValues()` method, and passing the table and column in question. The returned array will be ordered in the same order as the enum values are defined in the table.

```
$enums = $db->enumValues('mytable', 'mycolumn');
```

**Using Transactions**
Transactions can be used via the methods `startTransaction()`, `commitTransaction()`, and `rollbackTransaction()`assuming the database engine support it.

```
$db->startTransaction();

$update_count = $db->query($query, $values);
if ($update_count > 1) {
    $db->rollbackTransaction();
}
else {
    $db->commitTransaction();
}
```

By default, MySQL sets the transaction isolation to `REPEATABLE READ`. You can change this to `READ COMMITTED` by passing a boolean `true` when starting the transaction.

```
$db->startTransaction(true);
```

**Get Count of Query Calls Made**
To get a listing of the total number of queries for this specific instance of a DBConnect object, you can use the `getQueryCount()` method.

```
$count = $db->getQueryCount();
```

UserData.php
------------

[](#userdataphp)

A class to access and validate user data types from GET, POST, COOKIE, and FILES.

- Object based interface
- Support for retrieving arrays of values, including file data
- Functions auto-convert to basic data types
- Simple filter options for range, length, regexp, or pre-set values
- Default value option for all value retrieval functions

**Creating UserData Objects**
When creating a new UserData object, you must specify the name of the data field to retrieve, and optionally name where to look for the data at. If not specified, UserData will look for the value field in-order from these locations: GET, POST, COOKIE, and FILES.

```
use Nofus\UserData;

# Create UserData objects
$ud_userid = new UserData("user_id");
$ud_message = new UserData("message", "POST");

# Alternate way of creating UserData objects
$ud_attachments = UserData::create("attach", "FILES");
$ud_session = UserData::create("sess_key", "COOKIE");
```

**Getting Simple Values**
Getting simple values is easy, and returns the appropriate value type, or returns null if variable name was not passed.

```
# Get string values
$firstname = $ud_firstname->getStr();
$lastname = $ud_lastname->getString();

# Get integer values (truncates decimals)
$age = $ud_age->getInt();
$zip = $ud_zipcode->getInteger();

# Get float values
$temperature = $ud_temp->getFloat();
$distance = $ud_dist->getDouble();

# Get boolean values (true values are either: 1, true)
$allow_email = $ud_email->getBool();
$allow_text = $ud_text->getBoolean();
```

**Setting Default Values**
If no value was found, use the default value passed instead. With out a default value specified, the default is null.

```
$msg_type = $ud_type->getStr("public");
$guest = $ud_guest->getBoolean("1");
```

**Filter by Allowed Values**
If you know the value retrived must be from a set of values, you can set a filter to reject all but those values. Any non-allowed values will return the default value instead.

```
$ud_acct->filterAllowed( ['guest','normal','admin'] );
$acct_type = $ud_acct->getStr("guest");
```

**Filter by Range**
Only applicable when getting integer or float values. Values outside the range will return the default value, unless set to limit the value.

```
$ud_age->filterRange(0,120);
$age = $ud_age->getInteger();

# Only limit the minimum
$ud_minimum->filterRange(15.0);

# Only limit the maximum range
$ud_maximum->filterRange(null, 99.5);

# Limit the value to be within the filter range
$ud_limit->filterRange(0, 100, true);
```

**Filter by Length**
Only applicable for string values. Values not within length limits will return the default value, unless set to truncate.

```
# Filter minimum and maximum length
$ud_username->filterLength(2, 10);

# Filter minimum length only
$ud_username->filterLength(2);

# Filter minimum length and truncate string past maximum length
$ud_username->filterLength(2, 10, true);
```

**Filter by Regular Expression**
Only applicable for string values. Values not matching pattern will return the default value.

```
$ud_date->filterRegExp('/^\d{4}-\d\d-\d\d$/');
```

**Checking if Field with Name Exists**
To check if a field with a given name exists, even if the value passed was blank.

```
$ud_check = UserData::create('check');
if ($ud_check->exists()) {
    echo "Field with name 'check' was submitted.";
}
else {
    echo "Field 'check' was not sent to us.";
}
```

**Get Errors**
If your value is out of bounds of a filter, it will generate an error message. All error messages are stored in an array. Using `getErrors()`you can retrieve and view those filter errors.

```
$errors = $ud_data->getErrors();
foreach ($errors as $err) {
    echo "$err";
}
```

**Get File Values**
Get information about an uploaded file. Returns array containing:

- `name` The original name of the uploaded file
- `type` The mime type of the file (can be falsified by client)
- `size` The size of the uploaded file
- `tmp_name` The file location and name as it exists on the server
- `error` An error code if there was a problem with the upload (0 means no error)

```
$file_info = $ud_attachment->getFile();
```

**Get Array Values**
When using PHP form variable arrays, you can use the array version of the UserData functions. Any filters you've applied will apply to each value of the array.

```
$string_array = $ud_list->getStrArray();
# Can still provide default value to return
$string_array = $ud_list->getStringArray( array() );

$int_array = $ud_numbers->getIntArray();
$int_array = $ud_numbers->getIntegerArray();

$float_array = $ud_numbers->getFloatArray();
$float_array = $ud_numbers->getDoubleArray();

$bool_array = $ud_switches->getBoolArray();
$bool_array = $ud_switches->getBooleanArray();

$file_array = $ud_files->getFileArray();
```

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance75

Regular maintenance activity

Popularity25

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 74.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~369 days

Recently: every ~477 days

Total

7

Last Release

168d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/2531698?v=4)[Nate Collins](/maintainers/natecollins)[@natecollins](https://github.com/natecollins)

---

Top Contributors

[![natecollins](https://avatars.githubusercontent.com/u/2531698?v=4)](https://github.com/natecollins "natecollins (56 commits)")[![HoboJimYeti](https://avatars.githubusercontent.com/u/2904454?v=4)](https://github.com/HoboJimYeti "HoboJimYeti (18 commits)")[![schrauger](https://avatars.githubusercontent.com/u/6665521?v=4)](https://github.com/schrauger "schrauger (1 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/natecollins-nofus/health.svg)

```
[![Health](https://phpackages.com/badges/natecollins-nofus/health.svg)](https://phpackages.com/packages/natecollins-nofus)
```

###  Alternatives

[nystudio107/richvariables

Allows you to easily use Craft Globals as variables in Rich Text fields

441.5k](/packages/nystudio107-richvariables)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
