PHPackages                             tombrown86/workframe - 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. [Framework](/categories/framework)
4. /
5. tombrown86/workframe

ActiveFramework[Framework](/categories/framework)

tombrown86/workframe
====================

A framework that works

25452PHP

Since Jun 20Pushed 7mo ago2 watchersCompare

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

READMEChangelogDependenciesVersions (3)Used By (0)

Thanks for looking at WorkFrame!
================================

[](#thanks-for-looking-at-workframe)

1. [Introduction](#introduction)
2. [Motivation](#motivation)
3. [Quick start](#quick-start)
4. [Features](#basic-features)
5. [Ideas / future](#ideas)
6. [Shortfalls](#shortfalls)

.... More will come

Introduction [¶](#introduction)
-------------------------------

[](#introduction-)

This is a first attempt at a super lightweight PHP7 - PHP8.2 compatible framework that exists to achieve the basic standard requirements of an MVC style framework with (hopefully) a couple of useful unexpected extras.

Motivation [¶](#motivation)
---------------------------

[](#motivation-)

In my experience, frameworks are great for handling the bread and butter basics. However, they can become tiresom to work with when they have overbearing complexity.

Then they get upgraded, rewritten, changed beyond recognition which then causes everyone pain!

My advice is to avoid relying on the framework for detailed application logic.

Anything more complex is likely to have bespoke requirements that the framework does not attempt to provide.

This is a small flexible framework thats basically simple enough to upgrade to future PHP versions, yet powerful enough to provide the primary features we tend to require.

---

Quick start [¶](#quick-start)
-----------------------------

[](#quick-start-)

Do the following:

1. Pull the github project () or include it in your composer.json
2. Understand what is included (3 directories) The *www* directory - This is your web root (often called htdocs, public\_html, etc)
    The *ExampleApp* directory - This contains the custom application code, store it outside your web root
    The *WorkFrame* directory - This is the framework, store it outside your web root

3. Here is a typical vhost config (for apache), the Directory bit shows the essential ReWrite bit (routing all requests to the framework entry script).
     ```

    	ServerName local.workframe
    	DirectoryIndex index.php index.html
    	DocumentRoot /var/www/site/www
    	ErrorLog /var/log/apache2/workframe/local.workframe.error.log

    	Require all granted
    	RewriteEngine on
    	RewriteBase /var/www/site/www
    	# Or If WorkFrame is running in a subdir:
    	# RewriteBase /var/www/site/www/subdir
    	RewriteCond $1 !^(index.php|public/|robots.txt)
    	RewriteRule ^(.*)$ /index.php?$1 [L]

    ```
4. Update the definitions in init script for your application (like in ./ExampleApp/init.php) that are hopefully self explanatory.
5. Maybe check out the [features](#basic-features "Read about the basic features")

---

Basic features [¶](#basic-features)
-----------------------------------

[](#basic-features-)

Your app code will essentially follow the pattern of an HMVC framework, but by no means needs to be used as such. Your app will probably at least contain the following:

### Standard constructs

[](#standard-constructs)

 Request\_handlers (a bit like a controllers) You write your own by extending *\\WorkFrame\\Request\_handler* These purely exist as landing points for HTTP requests Requests are mapped to these handlers based on URL segments, with the last being the action name (method name) (E.g. /directoryname/subdirectoryname/request\_handler\_name/method\_name?get\_vars\_here) If not provided, index is taken as the default values for both method names and Request\_handler names Note, feel free to override pre\_action\_hook and post\_action\_hook, you can probably guess when they get called You can perform Exception based rerouting by throwing a *\\WorkFrame\\Exceptions\\Request\_handler\_rewrite\_exception*
 Model layer (see below) Handles "business logic" including data manipulation and data storage Request\_handlers (usually) set these up and invoke procedures which retain data to be passed through to the view layer
 View layer Templates - page templates Partials - snippets to be includedAn application with a large degree of complexity may benefit from having it's own class structure, nonconforming to this pattern.

### Model layer

[](#model-layer)

These consist of 3 classes of thing

 Services You write your own by extending *\\WorkFrame\\Service* These contain the bulk of the business logic They are responsible for (probably all) manipulation of Domain\_object's and also handle data persistance (through Data\_mappers) They would usually end up returning outcomes or output related data (presentation data) but wouldn't be expected to return HTML. (Instead your Request\_handlers would take this outcome info and map them into the view layer.)
 Domain\_objects You write your own by extending *\\WorkFrame\\Domain\_object* They can represent any kind of entity you like, including web forms &amp;/or data for persistance (sometimes 1:1 with DB tables) They can optionally exhibit **scenarios**, which you define as the programmer to describe the different roles &amp;/or rules of the object Attribute lists can be defined for each scenario to dictate which attributes can be "mass assigned" (E.g. from a \_POST or data mapper) There are some convenience methods like **from\_assoc** and **to\_assoc** which you can use to help work with the objects data You can use the \\WorkFrame\\Magic\_get\_set\_trait to automatically implement get/set behaviour for calls to nonexisting *$this-&gt;get\_privatevarname()* methods AS WELL AS referencing private attributes externally with *$this-&gt;$varname* (Use this sesnsibly!)
 Data\_mapper You write your own by extending *\\WorkFrame\\Data\_mapper* ... or more likely one of it's children *like \\WorkFrame\\Database\_data\_mapper* This is the persistance end of the model layer They should accept and return Domain\_objects (individually or as lists where appropriate) This is where you should put DB queries for DB CRUD. These should not contain (hardly any!) logic.. keep them simple. Their most complex feature may be to apply a condition to a data select You may want to implement this instead with an ORM library, or perhaps have it just implement a DB access helper library (ActiveRecord, data table gateway etc)### Loader / instance sharing

[](#loader--instance-sharing)

Anything extending/implementing any core WorkFrame components (most things) can easily label and share instances.

**For example:**

- Use **$this-&gt;SERVICE('Service\_name', 'service\_label')** to instantiate a service, and then reference it anywhere with **$this-&gt;service\_label**

(or just omit the 2nd param to get an individual instance) - You can also do this with domain objects and data mappers with **$this-&gt;DOMAIN\_OBJECT(...)** and **$this-&gt;DATA\_MAPPER(...)** respectively

To unload an existing instance call:
*$this-&gt;UNLOAD($component\_type, $component\_name)*

### The Renderer\_trait

[](#the-renderer_trait)

All your Request\_handlers will exhibit this trait automatically.

Whilst not written in stone, you'll most likely invoke templates and partials from classes that have this trait

Things using this trait can make use of it's add\_script*s*() and add\_stylesheet*s*() methods to conveniently append JS/stylesheet tags to a template
(Note: There is a built in tool to minify such client side code by passing true as the 2nd parameter to *add\_script(...)* based methods)

View data can be passed to the templates and partials with the add\_view\_var/add\_view\_vars() method.

By default, each Request handler and action will have a corresponding partial file path (***$YOUR\_APP**/html/partials/request\_handler\_dir\_path/request\_handler\_name/action\_name* (lowercased))

There is also a directory for templates: ***$YOUR\_APP**/html/templates/*. You can automatically render your partials into templates by passing the template sub path into **$this-&gt;render(...)**

### The Processor\_trait

[](#the-processor_trait)

Processors can be attached to fields and can manipulate and/or validate data. The framework comes with some but you can add your own. There is a mechanism for them to work client side (with JavaScript), if the processor has been coded as such

Processors (/validation rules) can be attached to a subset to fields as well as a subset of scenarios on the entity (if the trait is used on a Domain\_object (or infact anything with a scenario attribute)).

These can be used to validate/correct form fields inline - on the fly (using client, serverside or both).

### \\WorkFrame\\Html\\Form\_tools

[](#workframehtmlform_tools)

To help you write your HTML. These can be instantiated and entities. They return HTML for common things (like form fields and validation errors).

They also (like most things) be extended if you want extra functionality.

### \\WorkFrame\\Libraries\\Session

[](#workframelibrariessession)

A simple session library is provided. You may use it's following static methods.

- write($key, $value)
- read($key, $child=FALSE)
- delete($key)
- dump() *\[echos current session data array\]*
- regenerate\_session\_id()
- destroy()
- ... if you need more, it might have what you need - check it out.

### Application class (\\App\\App), hooks, etc

[](#application-class-appapp-hooks-etc)

Your app will probably want one of these sitting in it's route. It must have the same classname (and filename) as your application namespace. It must extend \\WorkFrame\\WorkFrame.

There are some standard hooks (like pre router, pre action etc) that can be defined in this class. You can also use this class to do anything application wide (like store current user, etc).

### Logging

[](#logging)

There is a very simple logging mechanism which is basically a single function: *log\_message($level, $message, $debug\_silent=FALSE)*. It writes to a logs directory in your App.

You can use your own customer error levels as well if you like, but there are some predefined constants you may use: APP\_LOG\_LEVEL\_WARNING, APP\_LOG\_LEVEL\_ERROR and APP\_LOG\_LEVEL\_INFO. Unless $debug\_silent is passed as TRUE, any errors which aren't APP\_LOG\_LEVEL\_INFO will get printed in the response if the app is in debug mode.

### Conf

[](#conf)

This is a simple mecahnism to define and retrieve config from files in the Conf directory.

Simple call conf($conf\_filename) to call and return data from the conf with that $conf\_filename.

If you want to use the existing mysql DB support, you must define (1 or more) DB connections in db.php (see example file).

---

### Security

[](#security)

A basic Security library has been added. So far all it can do is perform simple XSS filtering. If you enable this filtering (see security.php in conf). If enabled, you'll want to access the cleaned get/post/request variables with $this-&gt;GET(...), $this-&gt;POST(...) etc in the Request\_handlers. With \_GET as an example, calling $this-&gt;GET() will return the entire cleaned \_GET array, passing in a $key as the 1st parameter will return the cleaned item with that key. You can still access the uncleaned original values by passing TRUE as the 2nd parameter.

---

Ideas / future [¶](#ideas)
--------------------------

[](#ideas--future-)

Here is what I hope to work on (in chronological order)

1. User type based auth rules / config
2. A built in DB accessor system (for use in your Data\_mapper's)
3. Simple RESTful API support
4. A cookie library
5. .. anything else fundamental missing? Please [let me know](mailto:tombrown86@gmail.com "Email me")

---

Shortfalls [¶](#shortfalls)
---------------------------

[](#shortfalls-)

1. Currently, built in DB access is limited to mysqli
2. Some of the front end features rely on the availability of JavaScript
3. Will not work on windows! (basically due to directory separators!)
4. No support for internationalisation
5. No built in benchmarking
6. No testing suite. Infact, the framework itself isn't unit tested..
    Unit tests could probably be written for your application components without problem. There is potentially an issue with anything loaded through the WorkFrame Loader ($this-&gt;LOAD) since it loads components using some magic (and not using dependency injection). I think this issue can be worked around by overwriting the loader with your own fake test loader (you can inject it with set\_loader, a func which should be available on all components).
7. No caching
8. ... it could go on for a while

This framework provides the fundamentals and can easily be extending with any additional desired functionality :)

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance44

Moderate activity, may be stable

Popularity18

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 92.2% 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/98ab23fbe18aa3494afab377843b90e3a8d814417ff8c4227a6891f566979636?d=identicon)[tombrown86](/maintainers/tombrown86)

---

Top Contributors

[![tombrown86](https://avatars.githubusercontent.com/u/15341007?v=4)](https://github.com/tombrown86 "tombrown86 (83 commits)")[![pugelarouge](https://avatars.githubusercontent.com/u/45174682?v=4)](https://github.com/pugelarouge "pugelarouge (5 commits)")[![cyrusb](https://avatars.githubusercontent.com/u/53196?v=4)](https://github.com/cyrusb "cyrusb (2 commits)")

### Embed Badge

![Health badge](/badges/tombrown86-workframe/health.svg)

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

###  Alternatives

[laravel/telescope

An elegant debug assistant for the Laravel framework.

5.2k67.8M192](/packages/laravel-telescope)[spiral/roadrunner

RoadRunner: High-performance PHP application server and process manager written in Go and powered with plugins

8.4k12.2M84](/packages/spiral-roadrunner)[nolimits4web/swiper

Most modern mobile touch slider and framework with hardware accelerated transitions

41.8k177.2k1](/packages/nolimits4web-swiper)[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k36.7M259](/packages/laravel-dusk)[laravel/prompts

Add beautiful and user-friendly forms to your command-line applications.

708181.8M596](/packages/laravel-prompts)[cakephp/chronos

A simple API extension for DateTime.

1.4k47.7M121](/packages/cakephp-chronos)

PHPackages © 2026

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