Showing posts with label php. Show all posts
Showing posts with label php. Show all posts

Oct 8, 2010

PHP Preprocessor

I've thought of a random cool project, but this time instead of starting out on it, getting halfway through and then abandoning it, I figure I'll put it up for public discussion where others can throw in their two cents, tell me if such a thing already exists, or tell me I'm a moron and that it's a stupid idea (actually there will be people who will always say this, regardless of what the idea is).

I want to add some sort of preprocessor to PHP, to extend the power of the language. It seems a bit silly to add a preprocessor to something that is already a preprocessor, but I figure it is more practical to build this thing as something that outputs a language that is already very widely supported - my main incentive for this project is to then use it for PHP sites and put onto servers that already support PHP without needing additional software.

My main inspiration for such a project is from Ruby on Rails. See, Rails has a lot of good ideas, but many of them are easily translatable to PHP and other languages. You can use PHP's __call(), __get() and __set() methods to mimic a lot of the things that Rails does - I do this in MinMVC for model objects already.

What I think is much more powerful is the ability to use code to manipulate classes (aka metaprogramming). In Ruby I can do stuff like this:
class MyClass
  awesome_function_that_manipulates_MyClass

  ...
end
In PHP you can't do this. While PHP has a reflection API (I haven't actually used it much, so I can't comment on how good it is) it appears to be a read-only API. You can get information about classes and methods, but you can't modify them. You can't stick random methods into a class at run-time (unless I haven't read the PHP Reflection documentation properly). So you can't do something like this in PHP:
class MyClass
  has_many :users
The has_many method would add certain methods to MyClass to make it nice and easy to interact with the users that this class has. While you can mimic this functionality using some __call() hackery, I think adding some sort of metaprogramming capabilities would make this much simpler and more maintainable.

What this preprocessor would do is scan for files that end with .m.php and convert them to .php files. The project would involve writing a parser that would scan for preprocessor blocks and execute them. The code in the preprocessor blocks would also be PHP, so you can do whatever you like in there. The key difference would be the use of $this: if you're inside a class, $this would refer to a Class object that represents the current class. So you would write something like this:
class MyClass {
#begin
  $this->has_many("users");
#end
It's not nearly as elegant as the Ruby version, but that's ok. What this would do is the PHP preprocessor would execute the code in between #begin and #end and output some sort of PHP code to affect MyClass, like add methods called getUsers(), addUser(...), etc.

Quick aside on the use of the extension: I use .m.php instead of .phpm or something because Apache has a tendency to just serve files if it doesn't recognize the extension, which is a security risk. If it ends with .m.php, Apache will just execute it as a PHP file and fire out a PHP error when it sees weird stuff.

I'm still thinking about the details as to how you might add methods to $this, so that people can write add-ons. It might look something like this:
class_function has_many($what){
  ...
}
Who knows. Any comments on this idea?

May 3, 2010

Introducing MinMVC

A long time ago I announced that I had built up a PHP framework for my job that was designed for high-traffic websites. It was modeled after Ruby on Rails, but let you scale a bit more easily using things like memcached and MySQL master-slave configurations (Rails probably supports these features nowadays, I just haven't paid much attention to Rails in about a year after I stopped working with it).

I finally decided to get off my ass and remake this framework (I couldn't use the old version because it was not my intellectual property, however there isn't anything stopping me from just using the same ideas). Unfortunately the current incarnation doesn't really have any of those nice scaling features, although I don't think they'd be terribly difficult to add. Adding master-slave configurations would just require a bit of tweaking on the database connection class, and the cached-model-identity-map system that it had would require making a subclass of Model that uses memcached in addition to the database.

You can grab the current version from Github here. I will warn you though, use at your own risk! It isn't very well tested yet and will probably have security holes and random bugs. Also there isn't much by way of docs yet, so you'll have to figure out how it works on your own. If you've worked with Rails before then it shouldn't be too bad, it's just a matter of figuring out what you can't do anymore (like associations, migrations, lots of helpers, support for anything other than MySQL, ...).

What's the selling point? There isn't really one. This framework is pretty simple. It doesn't have many features, and it doesn't really enforce too much. It has a basic MVC structure, pretty URLs, a simple ORM layer, and...well not really anything else. The focus is on getting out of your way so that you can do what you need to do.

Anyway if you want to fiddle around with it feel free, and if you find bugs/problems or you have a feature request or something, please post it on the Github issues page.