Hi...
Manuel, could you post a small example? Say a person's contact details, equivalent to...Originally Posted by mlemos
yours, MarcusPHP Code:class Contact {
getName() { }
getEmail() { }
}
| SitePoint Sponsor |
Of course, where can I download the source
Um, I would have to take a look at it
No, definitely not.
What's code generation?





Hi...
Manuel, could you post a small example? Say a person's contact details, equivalent to...Originally Posted by mlemos
yours, MarcusPHP Code:class Contact {
getName() { }
getEmail() { }
}
Marcus Baker
Testing: SimpleTest, Cgreen, Fakemail
Other: Phemto dependency injector
Books: PHP in Action, 97 things





It does ? Umm... Proberly I've missed something huh ?...makes code generation more desirable![]()


If you download Metastorage archive, without having to install the full MetaL/Metastorage packages, you can see inside the install directory what is generated for the example model defined in the file cms.component.Originally Posted by lastcraft
Keep in mind that Metastorage follows the JE WIN approach (Just Exactly What I Need), which means that it will only generate classes with the functions to manipulate your data objects that you require. For instance, if you do not need a function to delete an object, no code will be generated to implement such function. This is meant to make classes and lightweight as possible.
Currently, Metastorage does not generate automatic setters and getters functions. It may generate getters/setters functions for accessing class variables that store references to another objects (ie foreign keys).
So, if you would expect it to generate getters and setters for basic data types variables, that will be available if explicitly request it. The reason for this is that not everybody likes to bloat their classes with setters/getters functions. OTOH, without requesting setters/getters, the variables have to be made public and so in that case other features are disabled like lazy loading, automated persistence of only the variables that changed, etc..
Bottom line, is that you will get what you ask explicitly. The examples that come with Metastorage distribution may not show how to enable setters/getters but that does not mean they will not be supported.
Manuel Lemos
Metastorage - Data object relational mapping layer generator
PHP Classes - Free ready to use OOP components in PHP

Ala Typo3?I must say that it's incredibly helpful. The general process (briefly) is to create a project, add a db, add tables and fileds to that db, then generate forms for that db. The form fields have server side validation, calendar popups, file uploading and resizing (using ImageMagick) as well as saving file info to specified table. Finally add any extra components, like login (specifying which fields in what tables are used for username, password, etc).
Res
Hi,
I've only had a really quick look at this (Propel) so far, so I'm probably setting myself up for a pratfall here...
They've hidden it too well for me to seeOriginally Posted by lastcraft
. I've only had a scan thru the source/docs/files, but it looks from my glance that rather than using Torque as a persistence layer, it's a pretty direct port of Torque into PHP5. Having never looked at Torque myself I'm basing that assumption on the number of comments in the code that pop up with a (Torque) attribution, and those that refer to Java stuff. Maybe I'm just failing to see the crucial bit so far.
This idea of porting things almost directly from Java into PHP5 is intriguing, if a little odd. I guess it kind of maybe makes sense in avoiding reinventing the wheel...?
(btw, I don't know if this is why binary cloud is quiet, but Phing development is only PHP5 now too, maybe it'll be really loud when there's a release).
Interesting quote in their docs:
Given that it works with PHP4 I'm going to have to take a look at Metastorage - is there no way you can post even a little code Manuel, to save everyone an extra visit somewhere else? I've just tried to hit the link in your post but it's not working for me...There are quite a number of object persistence layers for Java...however, there are very few solutions that even provide very basic o/r mapping for PHP. A few noteable:
* Metastorage - The only other comprehensive persistence layer for PHP [HL: that I know of]
(One last (entirely OT) thing, does anyone know of a tool to generate arbitrary amounts of random test data based on a SQL schema?)
Anyway, this is all interesting stuff, good luck with the project!
Cheers,
Jon





Hi Manuel...
I had a ten minute look and it looks quite thorough...
I am afraid I found it about as clear as mudOriginally Posted by mlemos
.
Assuming I want getters, setters, lazy loading, etc (which I always do) is this definition correct for the example above?
How much is missing?Code:<class> <name>Contact</name> <variable><name>name</name><type>text</type></variable> <variable><name>email</name><type>text</type></variable> </class>
Some interim comments and questions...
1) I could do without the strict adherence to canonical XML. XML is verbose enough without making it any worse. What is wrong with a few attributes?
2) How do I inherit/use this storage class for domain objects? Apart from a single generated persist method there does not seem to be much control over exactly what gets written out. Do I just decorate that method? If I do, how do I tell the internal factories that I want my version, not the raw one?
3) How are transactions handled?
I would be very curious to know how you solved these issues.
yours, Marcus
Marcus Baker
Testing: SimpleTest, Cgreen, Fakemail
Other: Phemto dependency injector
Books: PHP in Action, 97 things





Hi...
No I think you are right. I found some in the master directory and lots of Java properties files, but these may be relics. They also mention it in their FAQ. Not much else to go on, so I have probably jumped the gun.Originally Posted by JonR
yours, Marcus
Marcus Baker
Testing: SimpleTest, Cgreen, Fakemail
Other: Phemto dependency injector
Books: PHP in Action, 97 things


Of course, this is all new to you and unless somebody explains or you read the documentation, it is natural that you did not find it clear. Don't worry, you just need to experience it more.Originally Posted by lastcraft
As I said, setters/getters are an option that is not yet implemented but they will be. Keep in mind that this a project being developed like any other Open Source project. I developed it to address my own needs and then I decided to document it to make it useful to others, so you can provide feedback that will help the project evolve.Originally Posted by lastcraft
So, you will find that some things that you would like are not yet implemented, but if you would like them, you can always tell me what you think it should have.
This is just a definition of data variables. You need also to specify whatever types of functions you need to manipulate your objects.Originally Posted by lastcraft
XML attributes are not extensible, ie, you can't use tags in attribute values. This is against the meaning of X in XML, eXtensible markup language. So, using attributes limits what can be done to make the format more flexible and convinient.Originally Posted by lastcraft
Anyway, ideally you will use a more productive tool to edit your component definitions. I have a friend that told me that he will be working on a Dreamweaver template for Metastorage. Since I don't use Dreamweaver, I do not know how much more productive you can be with it.
In any case, component definitions are simple. You will not be editing them all the time to get so bothered with their verbosity.
Originally Posted by lastcraft
This is explained in Metastorage documentation but it will detailed in a simpler to understand way in the tutorial.html]Metastorage tutorial that is being written as we speak.
Basically, all objects are created by a factory class of which you need to create one instance per script/program. That applies to either objects being created from scratch or retrieved from storage. From than on, you just access the objects to do whatever you want and call a persist function to store the changes.[/font]
Metastorage generates final code. You should not edit the code generated by Metastorage. You should not need to edit the generated code either. What Metastorage generates it is like an API that was written by somebody else for a given purpose that you have. The way it works is that you just call this API to build your application.Originally Posted by lastcraft
If you need to customize any details, you do it in the component definition. If for some reason, you realize that the generated API does not satisfy any particular needs, you just need to tell me what you want so I can figure what can be done to address your needs consistently.
Transactions are not yet support but it will be like any database transactions, you need to start and end transactions by commiting or roll back any changes.Originally Posted by lastcraft
Manuel Lemos
Metastorage - Data object relational mapping layer generator
PHP Classes - Free ready to use OOP components in PHP





Hi...
Well I certainly know what MDA is and I certainly know what a persistence layer is, so if it was not immediately apparent to me what it does you have a problem. I think you have a big problem unless documentation makes an effort to address this fundamental point or provide any straightforward example. It desperately needs that tutorial.Originally Posted by mlemos
I still don't know after your four posts in this thread. What does it do? I mean with an answer as a single example, not a verbal description. I don't want to get spammed by Yahoo just to find out. Do you not have other web space to place it on.
Sorry, wasn't paying attentionOriginally Posted by mlemos
. I would formally add this as a feature request though, either as getName()/setName($name) or get("name")/set("name", $name).
Could you give an example for this case. I am trying to guage how much work it is to create a simple persistent object.Originally Posted by mlemos
This sounds a philosophical objection rather than a practical one. Attributes like "name" would likely never need extension in that way. As you can have both attributes and tags together, even if this unlikely scenario arrived, migration is easy. Meanwhile you have nearly doubled te length of the sourcecode.Originally Posted by mlemos
I thought that would happen too. Two years later and where I am based we are still hand editing the XML. As a result we pay much more attention to language construction now.Originally Posted by mlemos
I don't think that is strictly true. Once you get free of the DB you suddenly want to refactor it all the timeOriginally Posted by mlemos
.
Cool.Originally Posted by mlemos
That much is obvious. What happens when one object has a one to many relationship with another? I want business objects to come from business objects. To achieve that with the information so far (if I get you right) I have to create factories on top to convert/wrap the MetaL objects into the domain ones. If so then that is an easily fixed flaw. It means that schema changes cause me to update not just the MetaL files, but also my extra factory layer. This is the kind of duplication code generation is meant to avoid. The fix is to have a mechanism for overriding the class created in the factories. Is this possible?Originally Posted by mlemos
I figured that, otherwise it would be completely useless. As Jeff says, Wizards suck.Originally Posted by mlemos
What would the generated API look like for the example I gave above? I really don't want to wade through half finished docs to find out myself.Originally Posted by mlemos
OuchOriginally Posted by mlemos
. Do you know when you will be finished with the core functionality?
yours, Marcus
Marcus Baker
Testing: SimpleTest, Cgreen, Fakemail
Other: Phemto dependency injector
Books: PHP in Action, 97 things


I am not talking of MDA or persistence layers in general. There are thousands of products for that and all of them have differences. So, it is natural to me that you do not know the specifics of each product and things are not clear just by looking at the generated code.Originally Posted by lastcraft
You could save me a lot of typing if instead of assuming that there is a problem with the documentation, you actually go and read it. I have provided the URLs for the main documentation and tutorial 3 times and instead of making an effort to learn what you need from what is provided, you keep asking me needless questions.Originally Posted by lastcraft
I already told you where the tutorial is available. The tutorial is in progress but is more than half done. I have even halted further development until I finish the tutorial document, which should happen in the next weeks.
The tutorial is there because it is in the area of files belonging to metal-dev mailing list. Once it is reviewed and finished it will be put in the MetaL projects documentation page.Originally Posted by lastcraft
AFAIK Yahoo does not spam anybody that joins Yahoo Groups. Anyway, if you do not believe me, I have uploaded the tutorial as it is now to another site.
It will be done soon or later, but you can check Metastorage project progress to keep track of the features in the to do list and what is being implemented.Originally Posted by lastcraft
You can read about that already in the Metastorage tutorial. It comes with examples.Originally Posted by lastcraft
Not really. Using attributes turned out to be a real problem during the development of Metabase database schema format. What happened is that I realized that I need to be able to pass external values that would act as macros for composing the values of any tag values in the schema definition.Originally Posted by lastcraft
I wanted to use tags with values that represented the macro names but I could not insert them in the schema if they were to be used in tag attributes. I would probably need to resort to a new markup language that does not clash with XML special characters. That would be awkward because XML is already the markup language itself. So, I moved all tag attributes to sub-tags before Metabase went public and never looked back.
Suggesting migration at a later stage is a bad idea. It just reflects that you lack of vision and planning. Usually you break bakwards compatibility and annoy everybody that is using your project. If you are doing this for a closed project that only envolves a few people, that may not be a big deal. But doing it in Open Source projects only makes people hate you for the lack of planning. Better safe than sorry.
I also edit my XML files by hand. It is that some people make it a big deal if it is not all GUI driven. These people do not want to care about goes on behind the scenes.Originally Posted by lastcraft
Sure, but still it will not be the thing you will be spending most of the development time.Originally Posted by lastcraft
I am not sure what you are talking about. Business objects are business objects and data objects are data objects. Metastorage generates classes for data objects. Your application should be built around them without changing them. If you mix business logic in data object classes, you will be dealing with a major maintenance nightmare.Originally Posted by lastcraft
It depends on the wizards. If the wizard application generates lame code that makes you need to edit it, you can say they suck. However, if you use a wizard application that generates proper code that is complete and satisfies your needs, there is no reason to complain.Originally Posted by lastcraft
Sorry, I am not going to duplicate what is already written in the documentation and provided in the examples. The site even provides you UML diagrams of the classes generated from the examples. With some good will you can check it out yourself.Originally Posted by lastcraft
Like with any Open Source projects, it will be done when somebody writes the code for it.Originally Posted by lastcraft
This is not a commercial project that has to satisfy the needs of paying customers, so I do not need to lie to you and say it will be done soon. It is more likely that it will be done when I need each thing unless somebody else is willing to put up some work too.
Meanwhile, I suggest that you keep an eye in the Metastorage project progress and, if you want to help, just try what is available now and try to provide constructive feedback.
Manuel Lemos
Metastorage - Data object relational mapping layer generator
PHP Classes - Free ready to use OOP components in PHP





Hi...
I had read some of it. I hadn't read the tutorial (still haven't). I also read everything that was in the package itself and looked at the samples. That is more effort than most people will make.Originally Posted by mlemos
I think you have made the right decision.Originally Posted by mlemos
Cool.Originally Posted by mlemos
Fair dues, but the language is now a pain IMO.Originally Posted by mlemos
Yes, but you are balancing the risk of that against ease of use in the meantime. You say there are internal reasons then fair enough.Originally Posted by mlemos
Ok, I didn't put that very well. Some of the persistent objects will have special behaviour similar to triggers, but at the object level. Typically these problems arise with timing information and transitions of the object model. I assume that in MetaLStorage I have to place all behaviour into higher level classes. This means that I have to wrap the classes (rather than inherit) and that means that I have to create my own factories that add wrappers in these cases. Correct?Originally Posted by mlemos
Wild guess based on progress so far?Originally Posted by mlemos
yours, Marcus
Marcus Baker
Testing: SimpleTest, Cgreen, Fakemail
Other: Phemto dependency injector
Books: PHP in Action, 97 things
Hi all,
The java->PHP translator I'm working on is going pretty well (but I decided to avoid issues with namespaces and inner classes and a few other issues).
Anyways, I'm including a persistence layer, which will be in the active style (because the translator is run every time you make a change to your java code; of course, you still run the translator...)
My goal was to make it easy for beginners to get going with the layer. Thus, there is no need to run an external program (like Torque's generator program).
Example Java:
The main problem now is that n-m relations are hecka hard! I'm still trying to think of a good way to go about this... there are no decent persistent layers I know of for PHP. The megastorage looks interesting but the XML, ACK! Extremely un-newbie friendly. As you can see from my excerpt, though, it should be relatively easy to add functionality to your persistable objects. Currently, users will have to modify the database structure manually.Code:public class Member extends PersistableObject { StringProperty memberName=new StringProperty("name"); PrimaryKeyProperty id=new PrimaryKeyProperty(); //static Member _instance=null; //static ThingSet things=new ThingSet(); Composition moreData=new Composition(new MemberData()); Association possibleData=new Association(new PossibleData(),"fk2"); Aggregation items=new Aggregation(this,new Item()); /* (non-Javadoc) * @see persistent.PersistableObject#tableName() */ public String tableName() { return "members"; } }
BTW, I'm against functions like set($name) because if you have a typo when passing the name parameter then it's pretty painful. Once I became used to Java's strict-typing and numerous compiler checks, I've become very wary of checks that are only done at run-time (such as passing a string parameter representing the attribute).
I should also clarify that the intended audience is relatively new to web programming. I will probably not include transaction support (I've never seen the need for it myself yet because I only do fairly small projects).
So, this seems to be the approach that people would favor... I hope! Can anyone help me with the persistence layer? I'll release the relevant code if needed... (not sure yet if this will become open-source)


I think you have a wrong impression regarding how viable Open Source projects work. The way I see it, Open Source projects will only survive if they are useful to the developers working on them. The main goal is not to please others unless there is some commercial or ego based motivation which is not my case.Originally Posted by lastcraft
I have already wrote documentation with tens of kilobytes. Most of that documentation is not even useful to me because I wrote the project and so I know how it works without documentation.
The way you put it, it seems that I have to put your priorities over mine. The way I see it, if you decide to use the project, fine. I may even provide free support for you to develop whatever you want with Metastorage. If you decide to not use it, that is fine too. I try hard but I can't do miracles. I need to justify every minute that I spend developing this project, or else it means it is not being useful to me.
So, I think there must be good will in your part to move with the documentation that I already provide and do not ask me for doing something that I can hardly justify.
I think you are exaggerating. A pain is having to write all the code that Metastorage can generate manually from a little effort of specifying in its XML format what you want it to do.Originally Posted by lastcraft
I already tried to explain why it is the way it is. I can't justify the effort of changing it just because you are nit-picking.
If it is a big deal for you, I suggest that you design the XML format the way you want and and use XSL to transform it in a format that Metastorage takes.
Maybe I was not clear. Just because I do not intende to support customizations done on generated code, it does not mean I do not intend to support customizations done in event handlers.Originally Posted by lastcraft
The way I want to make it work, is that you will be able to define your own event handler functions to be added to the generated data object classes if and when you want them. So, your component definition will include the code (in PHP) that will be used to fill in the event handlers that you need. See what I mean?
That is vague. What is the core functionality for you? Try looking at the current Metastorage project todo list and tell me which items or others that may be missing you consider to belong to the core functionality.Originally Posted by lastcraft
Then I can tell you which I see more likely to be implemented first based on my needs for my current projects or eventually things that I may not need much but they are simple to implement and document.
Manuel Lemos
Metastorage - Data object relational mapping layer generator
PHP Classes - Free ready to use OOP components in PHP





Manuel , off topic but talking of Justification ....
can you specify the bug -affected version that caused this please , and perhaps where exactly it broke ?Unfortunately the latest PHP versions have become a nightmare. Despite newer versions have fixed some old bugs, they also introduce new bugs in unsuspected places that break existing code.
Now that PHP is much more complex than it used to be, it is hard to determine where new bugs will affect the code of the site that has now over 50,000 lines of PHP source code. It seems to be safer to stay with old versions and deal with their bugs than to upgrade to a newer version and deal with surprise bugs.
.....
In any case, as much as the origin of the problem was in a PHP bug for which I am not responsible, I wish to apologize for this incident. I am working on better procedures to prevent that incidents like this will happen again. I will also keep improving the site avoiding as much as possible to make upgrades to unsafe newer PHP versions





Hi...
You are being overly sensitive to say the least. If you have taken the trouble to plug your stuff in this forum then you clearly have an interest in others using it. I am giving you feedback on the likelyhood of that. I am saying that the tutorial is your most important priority right now (from my point of view). Far better to do this in the short term than the tens of K of other stuff.Originally Posted by mlemos
If you can't handle feedback then don't post messages about the thing in the first place.
Yes.Originally Posted by mlemos
I am not. Let it go.Originally Posted by mlemos
That would likely happen.Originally Posted by mlemos
That was the kind of information I was after.Originally Posted by mlemos
I was hoping you would choose. What are your immediate aims for the project?Originally Posted by mlemos
yours, Marcus
Marcus Baker
Testing: SimpleTest, Cgreen, Fakemail
Other: Phemto dependency injector
Books: PHP in Action, 97 things


It is something with the flock() function. It seems it has several problems setting with non-blocking locks.Originally Posted by firepages
The site has daemon scripts that process the mail delivery queue one message at once. It is just a PHP script that gets called from cron every 15 minutes. New class notifications take more than 15 minutes because they go to many users.
When the delivery is started the script attempts to locks a flag file. If it succeeds, it is free to start a new delivery with the next message in the queue. Otherwise the script quits because there is a delivery in progress.
What was happening is that it was succeeding all the time. So the same message started being delivered many times.
Anyway, if you do not use flock or non-blocking locks, you should not be concerned with this. There are other serious bugs in other places though, especially in functions that deal client socket connections. Some of the problems I am trying to fix PHP itself once I have some time.
Manuel Lemos
Metastorage - Data object relational mapping layer generator
PHP Classes - Free ready to use OOP components in PHP


I am sorry but you are putting yourself as if you are doing a big favor and you do not have an interest on moving yourself to find what you need without depending on me. What I am telling you is that I will not be fishing for you. At most I can tell you how to fish for yourself.Originally Posted by lastcraft
This means that it upsets me when have to stop to write explanations about things that you could learn by yourself if you have looked at the reference manual and the tutorial that is partly written but is already useful.
If you had an idea of how busy I am and how much I have to struggle to find time to write tutorials and other stuff that is meant mostly to make the project useful to others, you could understand why this upsets me.
What I said is that making it useful to others is not my main goal for this project. This does not mean that I am not interested or do not value the feedback that others can provide.Originally Posted by lastcraft
It seems to me that you even haven't looked at the tutorial, or else you would know that when I say that the tens of K of documentation that is not even useful to me, it is the tutorial document that I am talking about, as it has now over 60K.Originally Posted by lastcraft
You just need to be more understanding and realize when you are asking too much beyhond the acceptable limits of patience.Originally Posted by lastcraft
I want to start working on the support forums that will be made available for each package published in the PHP Classes site. It may envolve implementing some things that are already on the todo list, but probably not all.Originally Posted by lastcraft
Manuel Lemos
Metastorage - Data object relational mapping layer generator
PHP Classes - Free ready to use OOP components in PHP

So you're saying that while you don't care about making your tool useful to us, we should still spend our precious time (yes, we're busy too) to help you do your homework?What I said is that making it useful to others is not my main goal for this project. This does not mean that I am not interested or do not value the feedback that others can provide.
This is/was a discussion about useful tools for code generation. If your tool does not fit that bill and is not intended to, then please don't tout it here. If you need help or feedback, ask for it on a thread of your own.
Things that try to look like Things, sometimes
look more like Things than Things. - Granny Weatherwax


You are still not getting my point. I never said I do not care about making the tool useful to others. I even said that is the main reason why I wrote almost 200K of documentation and tutorial.Originally Posted by ZangBunny
When I say that it is not my main goal to make the project useful to others, I mean that I have to make it useful to use in my projects first, so my projects needs will have priority over other users requests. This does not mean that other user requests will not be satisfied. It is all a matter of priorities. I hope it is now clear for you.
Manuel Lemos
Metastorage - Data object relational mapping layer generator
PHP Classes - Free ready to use OOP components in PHP
One of the guys in our office has started a tool for our LogiCreate system called PBDO - PHP Business Data Objects. It's essentially a code generator which can take a Torque file and create PHP objects. It handles one->one and one->many relationships (I think many->many as well), cascading deletes, that sort of stuff. There's a clear separation in the generated code between what you can edit and what you can't. If you regenerate the base, your custom code won't be overwritten (though it may need to be tweaked).
You can download an earlier version of it from http://www.logicreate.com I know there's been some newer versions internally which aren't available for download yet, but that's just a time issue in posting. If anyone's interested in contributing, simply email us and we'll get you the files.
Also, you can get a somewhat newer version in the LogiCampus project on sourceforge.
I wrote in another post about this in another forum that it's tied to the LogiCreate platform's db layer. It's not all that hard to change it to generate code that works with something else, but that's just not been a priority for us at this point. If you'd like to contribute to that, feel free to pitch in.
For anyone interested, where we see LC going is being a dev framework *and* tools which complement each other and work together, rather than a disparate set of tools which are intended to be standalone (too many of those already, imo).
I'll answer theoretical questions about it, or help someone get it workin if you need that.
Thanks.
Michael Kimsal
=============================
groovymag.com - for groovy/grails developers
jsmag.com - for javascript developers
I want to let you know about my php code generation tool.
http://www.phpbackend.com/create_database.php
It generates forms and navigation menu given a database sql structure.
It includes html editors in text field on demand, big files transfert management with java applet (in the generated code), ordering system, and more important than anything: one-to many (or integrity constraints) management in mysql.
A postgresql version is almost done
Of course I want to evoluate my tool, and maybe later it will become more general purpose, and accept objects and uml as input.
I've been developping this for my clients projects and using it a lot. I got the idea that web backend could be generated by using field type and naming
However, I need some clients to have a reason to work more on it.
Any feedback is welcome
Nadine St-Amand
http://www.phpbackend.com




I use DB_DataObject (link) and I loooove it.
Jeffrey Hunt, freelance PHP & MySQL developer
Resume: http://www.jeffreyhunt.org/resume/





"Página não encontrada"Originally Posted by mlemos
Can you post a "hello world" style (code!) example?
Douglas
Hello World


Sorry for the delay. I just made a new release of Metastorage that introduces report generation classes and relationships between classes defined in different components (application modules).Originally Posted by DougBTX
Anyway, that tutorial was finished a long time a ago, so I removed it from that temporary site. You may find updated documentation including the tutorial here.
I don't know if that meets your expectations of a "hello world" example, but keep in mind that MetaL is one thing (a meta-language) and Metastorage (a persistent object classes generator) is an application of MetaL but you do not see any traces of MetaL when you use the result of Metastorage.
I admit this may seem confusing because all comes from the same site.
Manuel Lemos
Metastorage - Data object relational mapping layer generator
PHP Classes - Free ready to use OOP components in PHP
Bookmarks