PHP PSR-0 + several namespaces in one file and autoload

I’ve been thinking for a while about defining several namespaces in one php file and so, having several classes inside this file.

Suppose, I want to implement something like DoctrineORMQueryExpr:

Expr.php
Expr
|-- Andx.php
|-- Base.php
|-- Comparison.php
|-- Composite.php
|-- From.php
|-- Func.php
|-- GroupBy.php
|-- Join.php
|-- Literal.php
|-- Math.php
|-- OrderBy.php
|-- Orx.php
`-- Select.php

It would be nice if I had all of this in one file – Expr.php:

namespace DoctrineORMQuery;
class Expr {
    // code
}

namespace DoctrineORMQueryExpr;

class Func {
    // code
}

// etc...

What I’m thinking of is directories naming convention and, unlike PSR-0 having several classes and namespaces in one file. It’s best explained by the code:

ls Doctrine/orm/query
Expr.php

that’s it – only Expr.php

Since Expr.php is somewhat I call a “meta-namespace” for ExprFunc, it make sense to place all the classes inside Expr.php (as shown above).

So, the vendor name is still starts with an uppercased letter (Doctrine) and the other parts of namespace start with lowercased letter. We can write an autoload so it would respect this notion:

function load_class($class) {
    if (class_exists($class)) {
        return true;
    }
    $tokenized_path = explode(array("_", "\"), DIRECTORY_SEPARATOR, $class);
    // array('Doctrine', 'orm', 'query', 'Expr', 'Func');
    //                                    ^^^^
    // first, we are looking for first uppercased namespace part
    // and if it's not last (not the class name), we use it as a filename 
    // and wiping away the rest to compose a path to a file we need to include
    if (FALSE !== ($meta_class_index = find_meta_class($tokenized_path))) {
        $new_tokenized_path = array_slice($tokenized_path, 0, $meta_class_index);
        $path_to_class = implode(DIRECTORY_SEPARATOR, $new_tokenized_path);
    }
    else { // no meta class found
        $path_to_class = implode(DIRECTORY_SEPARATOR, $tokenized_path);
    }
    if (file_exists($path_to_class.'.php')) {
        require_once $path_to_class.'.php';
    }
    return false;
}

Another reason to do so is to reduce a number of php files scattered among directories.
Usually you check file existence before you require a file to fail gracefully:

file_exists($path_to_class.'.php');

If you take a look at actual DoctrineORMQueryExpr code, you’ll see they use all of the “inner-classes”, so you actually do:

file_exists("/path/to/Doctrine/ORM/Query/Expr.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/AndX.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/Base.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/Comparison.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/Composite.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/From.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/Func.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/GroupBy.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/Join.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/Literal.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/Math.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/OrderBy.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/Orx.php");
file_exists("/path/to/Doctrine/ORM/Query/Expr/Select.php");

in your autoload which causes quite a few I/O reads.
Isn’t it too much to check on each user’s hit?

I’m just putting this on a discussion.

I want to hear from another PHP programmers what do they think of it.
And, of course, if you have a silver bullet addressing this problems I’ve designated here, please share.

I also have been thinking if my vogue question fits here and according to the FAQ it seems like this question addresses “software architecture” problem slash proposal.

I’m sorry if my scribble may seem a bit clunky 🙂
Thanks.

2

Keep using a single file per class.

You use APC, right? If you don’t, start doing it right now. APC will cache the opcode, thus there will be no performance hit on the file checking.

It’s not worth losing so much readability.

I am not convinced, that you really want to have all your classes in one file. Of course it is possible, but I wouldn’t want to maintain it. You can use multiple namespaces in one file. There are two allowed syntaxes:

Example #1 Declaring multiple namespaces, simple combination syntax

<?php
namespace MyProject;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }

namespace AnotherProject;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
?>

Example #2 Declaring multiple namespaces, bracketed syntax

<?php
namespace MyProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}

namespace AnotherProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}
?>

I would go with the second one, for readability, maintenance and error avoidance reasons.

However, I don’t like the idea of using one file for multiple classes. I would suggest to use one file per class, organized in folders according to your namespace. This allows you to use really straightforward autoloading:

spl_autoload_register(function ($className) {
    $className = (string) str_replace('\', DIRECTORY_SEPARATOR, $className);
    if(file_exists($className)) {
        include_once($className . '.class.php');
    } else {
        // throw class not found
    }
}); 

Thats a pattern I usually use in my applications. If you are concerned about IO and speed, I would look at the things Yannis Rizos mentioned:

Have you thought of just putting everything in a phar archive? Still a
file per class (easier to maintain), but a bit less strain on the
filesystem (especially with APC).

You could even use the HipHop compiler.

2

You were asking if the classes in question would cause IO on every class. But you might overlooked this code at the beginning of the autoload function

if (class_exists($class)) {
    return true;
}

as soon as the ‘container’ file Expr.php is loaded, all the classes inside will be registered in php and therefore every subsequent call to autoload would result in class_exists() == true

If you decide to have several classes in one file, simply make sure that the class which would resolve the autoload correctly is used before any other inline classes. This would effectively save I/O compared to the one-class-per-file approach.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật