Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I autoload classes that have a file name different from the class name?

Tags:

php

php-5.5

psr-4

I have seen these,

How to autoload class with a different filename? PHP

Load a class with a different name than the one passed to the autoloader as argument

I can change but in my MV* structure I have:

/models
    customer.class.php
    order.class.php
/controllers
    customer.controller.php
    order.controller.php
/views
...

In the actually classes they are,

class CustomerController {}
class OrderController{}
class CustomerModel{}
class OrderModel{}

I was trying to be consistent with the names. If I do not put the class name suffix (Controller, Model), I cannot load the class because that is redeclaring.

If I keep the names of my classes, autoload fails because it will look for a class file named

CustomerController

when the file name is really,

customer.controller.php

Are my only ways to (in no order):

  • use create_alias
  • rename my files (customer.model.php to customermodel.php)
  • rename my classes
  • use regular expressions
  • use a bootstrap with included files (include, require_once, etc.)

?

Example code,

function model_autoloader($class) {
    include MODEL_PATH . $class . '.model.php';
}

spl_autoload_register('model_autoloader');

It seems I have to rename files,

http://www.php-fig.org/psr/psr-4/

"The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name."

like image 380
johnny Avatar asked Nov 10 '22 11:11

johnny


1 Answers

Looks to me this can be handled with some basic string manipulation and some conventions.

define('CLASS_PATH_ROOT', '/');

function splitCamelCase($str) {
  return preg_split('/(?<=\\w)(?=[A-Z])/', $str);
}

function makeFileName($segments) {
    if(count($segments) === 1) { // a "model"
        return CLASS_PATH_ROOT . 'models/' . strtolower($segments[0]) . '.php';
    }
    
    // else get type/folder name from last segment
    $type = strtolower(array_pop($segments));
    
    if($type === 'controller') {
        $folderName = 'controllers';
    }
    else {
        $folderName = $type;
    }
    
    $fileName = strtolower(join($segments, '.'));
    
    return CLASS_PATH_ROOT . $folderName . '/' . $fileName . '.' . $type . '.php';
}

$classNames = array('Customer', 'CustomerController');

foreach($classNames as $className) {
    $parts = splitCamelCase($className);
    
    $fileName = makeFileName($parts);
    
    echo $className . ' -> '. $fileName . PHP_EOL;
}

The output is

Customer -> /models/customer.php

CustomerController -> /controllers/customer.controller.php

You now need to use makeFileName inside the autoloader function.

I myself am strongly against stuff like this. I'd use namespaces and file names that reflect the namespace and class name. I'd also use Composer.

(I found splitCamelCase here.)

like image 171
Sergiu Paraschiv Avatar answered Nov 14 '22 21:11

Sergiu Paraschiv