Asked  7 Months ago    Answers:  5   Viewed   74 times

I am trying to use namespaces in fatfree framework, but somehow its not able to find the class following is my setup


GET /=SrcControllersIndex->index


namespace SrcControllers;

class Index {
    function index($f3) {
        echo View::instance()->render('template.htm');

Global index.php

// Retrieve instance of the framework

// Initialize CMS

// Define routes

// Execute application



Not Found

HTTP 404 (GET /)

• index.php:13 Base->run()



; Where the framework autoloader will look for app files
; Remove next line (if you ever plan to put this app in production)
; Where errors are logged
; Our custom error handler, so we also get a pretty page for our users
; Where the framework will look for templates and related HTML-support files
; Where uploads will be saved

I'm not sure what's going wrong.

Thanks In advance.



The autoloader of the Fat-Free Framework is very basic. It expects you to define one or more autoloading folders, each of them will map to the root namespace.

So let's say you define $f3->set('AUTOLOAD','app/;inc/') and your file structure is:

- app
- inc
- lib
  |- base.php
- index.php

Then a class named MyClass belonging to the FooBar namespace (full path: FooBarMyClass) should be stored in either app/foo/bar/myclass.php or inc/foo/bar/myclass.php (remember: we specified two autoloading folders).

NB: don't forget to specify namespace FooBar at the beginning of myclass.php (the autoloader won't do it for you).


So to answer your specific problem, having the following file structure:

- lib
  |- base.php
- src
  |- controllers
     |- index.php
- index.php

three configurations are possible:

Config 1


Then all the files under src/controllers/ will be autoloaded, but remember : src/controllers/ maps to the root namespace, so that means the Index class should belong to the root namespace (full path: Index).

Config 2


Then all the files under src/ will be autoloaded, which means the Index class should belong to the Controllers namespace (full path: ControllersIndex).

Config 3


Then all the files under ./ will be autoloaded, which means the Index class should belong to the SrcControllers namespace (full path: SrcControllersIndex).

Wednesday, March 31, 2021
answered 7 Months ago

The F3 instance variable which is declared at the very start of your index.php ($f3=require...) can be retrieved anywhere in the code using the static call $f3=Base::instance().

Anyway, for convenience purpose, at routing time this F3 instance as well as the route parameters are passed to the route handler. Therefore, instead of defining your route handler as:

function display() {
    echo 'I cannot object to an object' . $f3->get('');

you could define it as:

function display($f3) {
    echo 'I cannot object to an object' . $f3->get('');

or even better:

function display($f3,$params) {
    echo 'I cannot object to an object' . $params['page'];

These 3 functions are absolutely identical so you should pick up the one that you understand best. But you should remember that $f3 and $params are only passed at routing time, which means to 3 functions: the route handler, the beforeRoute() hook and the afterRoute() hook. Anywhere else in the code (including inside a class constructor), you should call Base::instance() to retrieve the F3 instance.

PS: your question being "why do i have to pass the $f3 class to the function?", I would suggest you to rename its title to reflect it.

UPDATE: Since release 3.2.1, the F3 instance is also passed to the constructor of the route handler class:

class myClass {
    function display($f3,$params) {
        echo 'I cannot object to an object' . $params['page'];
    function __construct($f3) {
        //do something with $f3
Wednesday, March 31, 2021
answered 7 Months ago

DB querying

There are 3 variants to loop through db results:

Without mapper:

Execute a SQL query and fetch the result set as an array of associative arrays:

$users = $db->exec('SELECT * FROM users');
foreach($users as $user)
  echo $user['name'];//associative array

With mapper->load:

Fetch mapper rows one by one (your method):

$user=new DBSQLMapper($db,'users');
while(!$user->dry()) {
  echo $user->name;//db mapper

With mapper->find:

Fetch the result set as an array of mappers:

$mapper=new DBSQLMapper($db,'users');
foreach($users as $user)
  echo $user->name;//db mapper

DB error handling

DBSQL is a subclass of PDO so it can throw catchable PDO exceptions. Since these are disabled by default, you need to enable them first. This can be done in 2 different ways:

  • at instantiation time, for all transactions:

    $db = new DBSQL($dsn, $user, $pwd, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ));

  • later on in the code, on a per-transaction basis:


Once PDO exceptions are enabled, just catch them as other exceptions:

try {
  $db->exec('INSERT INTO mytable(id) VALUES(?)','duplicate_id');
} catch(PDOException $e) {
  //$err[0] contains the error code (23000)
  //$err[2] contains the driver specific error message (PRIMARY KEY must be unique)

This also works with DB mappers, since they rely on the same DBSQL class:

$db=new DBSQL($dsn,$user,$pwd,array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
$mytable=new DBSQLMapper($db,'mytable');
try {
  $mytable->save();//this will throw an exception
} catch(PDOException $e) {
  echo $err[2];//PRIMARY KEY must be unique
Wednesday, March 31, 2021
answered 7 Months ago

You don't have to define a route for this. F3 will automatically generate a 404 status code for any non-defined route.

If you want to define a custom error page, you need to set the ONERROR variable.

Here's a quick example:

$f3->route('GET /','App->home');
  echo Template::instance()->render('error.html');

with error.html defined as:

<!DOCTYPE html>
  <p>Error code: {{@ERROR.code}}</p>

Now if you call any non-defined route like /foo, the template error.html will be rendered with a 404 status code.

NB: this works for other error codes. Other error codes are triggered by F3 or your application with the command $f3->error($status), $status being any valid HTTP status code (404, 500, 403, etc...)

Wednesday, March 31, 2021
answered 7 Months ago

You need to fully qualify the relative class name Yii.

The most convenient way to do this is by importing the class: just add use Yii; below your namespace declaration.

Saturday, May 29, 2021
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :