I'm working on a couple of CakePhp projects these days and I was wondering how I should document them. I'm used with ruby on rails where documenting is made easy with the help of the framework.
Is there anything like this in CakePhp? I'm looking at the documentation of the framework and I can't find anything about that. If it's not part of the framework, what would be the proper way to document my project?
You should try the Api Generator plugin (introduced here) used to power the official CakePHP API.
It uses the Reflection class (available in PHP 5.2 and above) to dynamically introspect your code's docblock comments meaning you don't have to regenerate your documentation for every change you make.
There are also a few extra features such as search indexing, calculating documentation coverage of your code, and allowing the use of Markdown in your docblock comments to generate HTML in your documentation.
You can always use generic solutions that apply to any PHP codebase instead, such as phpDocumentor or doxygen.
You will need to add docblocks to your code with the appropriate tags for any of these solutions to work (some IDEs can generate these for you). The core CakePHP code (and associated documentation) can be used as a good example of what is required.
A few subtle standards I have noticed the CakePHP team use when documenting code:
Never indent the docblock comment, even inside a class. This allows you to scroll through code scanning by docblock, and also allows you the full horizontal width of each line to type (usually around 100 characters).
Finish every sentence with a full stop (or period) as this acts as a good signal to let you know if each part of the documentation is complete and well thought out.
Related
Goal
I've been tasked with versioning a pretty large PHP Lithium API.
The end result I'm looking for is to use namespacing to separate the versions.
For example, normally a lithium route that looked like this:
Router::connect('/{:controller}/{:action}/{:id:\d+}');
Could have the following URL, map to the following PHP call:
http://www.fungames.com/game/view/2
app\controllers\Game::View($gameId)
But I would like to create the following mapping:
Router::connect('/{:version}/{:controller}/{:action}/{:id:\d+}');
Such that the following two calls could be made:
http://www.fungames.com/v1/game/view/2
app\controllers\v1\Game::View($gameId)
http://www.fungames.com/v2/game/view/2
app\controllers\v2\Game::View($gameId)
Problem
Unfortunately, the Lithium documentation doesn't make much mention of API versioning. There's a brief mention here as an example of continuation routes. But that approach would required making if statements in my controllers to version my API, and I personally consider that a poor approach.
TLDR
What is the best way to achieved namespaced API versioning when using the PHP Lithium Framework?
API versioning is a really broad topic, and while Li3 gives you all the necessary tools to implement any approach you choose, the actual implementation is up to you. Having said that, the routing layer is fairly sophisticated and will get you very, very far. See this gist on routing configuration examples.
Combining this with Request::get() which allows you to match on any request parameters including headers (you can pass get()-compatible values as $params in Router::connect() — see examples here),
and Request::detect(), which allows you to implement custom matching logic, you can send any configuration of values down to the controller/dispatch layer. This allows you to segment your versions by differently namespaced controllers (with fallback to the default), prefixed actions, or pass a namespace/class path for a different model.
Yet another approach, and one that I would recommend in the general case, is implementing a set of transaction managers/mappers for any endpoints that need to be versioned, and using them as an intermediary between your controller and your model, then use routing to switch between them.
This approach is made easier if you evolve your API using, i.e. content types, since you can choose a mapper based on that. This is also nice since version numbers are strongly discouraged by REST's creator.
Anyway, hope that helps.
I'm somewhat familiar with using the Amazon MWS apis, but I'm new to CodeIgniter and the whole hmvc thing. I'm curious how I would add the api into CodeIgniter. Would I have to dissect the entire api into the appropriate mvc folders, or could I just add it as a library. If the latter is the case, how would I use the api?
I'm sorry if this is vague, but I would greatly appreciate any help you're willing to offer! Thanks
I cannot say anthing specific to CodeIgniter, but I've worked with various MVC libraries, so I can give a general overview. Your options are:
I) Write a model from scratch
New code accessing the MWS would mostly end up in the "Model" space. The controllers and views (which you'll probably eventually need) are outside the scope of the code that Amazon provides, so they need to be written anyways. As far as the MVC (and OOP) idea goes, this is the "proper" way to do it, you can make full use of inheritance and polymorphism.
Advantages: Your model accessing the MWS will follow the rules and guidelines of your MVC framework. It will be easy to integrate into other parts of the framework, and integrate nicely with the rest of the code.
Disadvantages: lots of code to write and (more importantly, since MWS is a moving target) maintain.
II) Use Amazon's code as a library
Amazon's code would go into the "Libraries" space. As it doesn't follow the rules of your MVC framework, it will "feel" foreign to the rest of the code.
Advantages: Less code to write and maintain.
Disadvantages: No usage of the framework, no code reuse, no inheritance and no polymorphism.
III) Write a wrapper
This is basically a mix of the two options above. You write a very thin wrapper around the library (goes into the Model space) which calls the unmodified Amazon library. Written properly, you might get a "best of both worlds" - this depends on how much the interface the library matches your desired model interface.
Advantages: Often only little extra code is needed, when compared to the "library" approach", while the model can be used in the same way as a complete rewrite.
Disadvantages: Sometimes needs almost as much code as writing from scratch.
Suggestions and Comments
My approach would probably be to go with a wrapper, unless I need just a fraction of the library's code. Since PHP does not have a strict object hierarchy, it is usually possibly to properly mimic inheritance anyways if needed.
A side note on designing a model around the MWS: Unlike most web services, some calls to the MWS API (e.g. SubmitFeed) work asynchronously in that information about the success or failure of an operation will only be available minutes (or even hours) after the call has been made. Most MVC model hierarchies and interfaces are not designed to handle that type of thing well, so a complete rewrite might not give you the benefits that you'd normally get.
Please remember, that I have no knowledge about CodeIgniter. Your mileage may vary.
My solution is specifically for the Yii PHP Framework but principle should work modifed for Codeigniter external library autoloader:
Put the entire Amazon MWS PHP SDK into your Vendors folder or into an Extensions folder or whatever CI prefers for external libraries. You might have to create that folder and refer to it within CI
Then find out how to use CI's autoloader so it autoloads the library from step 1 above.
Then just call whatever part of the Amazon MWS library from step 1 from your controllers.
This is quick reply, so if I've missed something let me know so I can edit.
For more in-depth discussion visit below to see how we overcame this along with exact code we used for the autoloader and other things dealing with the Amazon MWS PHP SDK
http://www.jescor.com/amazon-price-update-program/
I have been handed over a large undocumented code of a application written in php as the original coder went AWOL. My task is to add new features but I can't do that without understanding the code.I started poking around. honestly, I am overwhelmed by the amount of source code. I have found:
Its well written based upon MVC architecture, DB persistence, Templating & OOP
modular, there is concept of URL based routing,basic templating
Uses custom written php framework which has no documentation.And there no source control history(oops!)
there over 500 files, with each file containing hundreds of line of code. And every file has 3-4 require_once statements which include tons of other files, so its kinda hard to tell which function/class/method is coming from where
Now I am looking for some techniques that I use to understand this code. for example, consider the following code snippet:
class SiteController extends Common {
private $shared;
private $view;
protected function init(){
$this->loadShared();
$this->loadView();
}
private function loadShared(){
$this->shared = new Home();
}
private function loadView(){
$this->view = new HomeView();
}
I want to know
where HomeView() & Home() are defined? Where does $this->shared & this->view come from? I checked the rest of the file, there is no method named shared or view. so obviously, they coming from one of hundreds of classes being included using require_once() But which one? how can I find out?
Can I get a list of all the functions or methods that are being executed? If yes, then how?
this class SiteController overrides a base Common class. But I unable to find out where is this Common class is located. How to tell?
Further, Please share some techniques that that be used to understand existing code written in php?
First, in this kind of situation, I try to get an overview of the application : some kind of global idea of :
What the application (not the code !) does
How the code is globally organized : where are the models, the templates, the controllers, ...
How each type of component is structured -- once you know how a Model class works, others will typically work the same way.
Once you have that global idea, a possibility to start understanding how the code works, if you have some time before you, is to use a PHP Debugger.
About that, Xdebug + Eclipse PDT is a possibility -- but pretty much all modern IDEs support that.
It'll allow you to go through the generation of a page step by step, line by line, understanding what is called, when, from where, ...
Of course, you will not do that for the whole application !
But as your application uses a Framework, there are high chances that all parts of the application work kind of the same way -- which means that really understanding one component should help understanding the other more easily.
As a couple of tools to understand what calls what and how and where, you might want to take a look at :
The inclued extension (quoting) : Allows you trace through and dump the hierarchy of file inclusions and class inheritance at runtime
Xdebug + KCacheGrind will allow you to generate call-graphs ; XHProf should do the same kind of thing.
Using your IDE (Eclipse PDT, Zend Studio, phpStorm, netbeans, ...), ctrl+click on a class/method should bring you to its declaration.
Also note that an application is not only code : it often find very useful to reverse-engineer the database, to generate a diagram of all tables.
If you are lucky, there are foreign keys in your database -- and you'll have links between tables, this way ; which will help you understand how they relate to each other.
You need an IDE. I use netbeans for PHP and it works great. This will allow you to find out where the homeview/home classes are by right clicking and selecting a "find where defined" option or something similar.
You can get a list. This is called the stack. Setting up a debugger like xdebug with the IDE will allow you to do this.
grep is the only thing makes me survive such codez
Look inside of the script where you found this code snippet for additional included or required pages that PHP imported into the main script. Those scripts should define those classes that are being instantiated.
Sorry, not sure if you can find which functions/methods have been executed. I know you can find if they exist, and you can find the generated output of them... but not sure if they have been executed.
It is important to note that SiteController doesn't override, the Common class, but it extends, or builds on top of it, like how a building is built on a foundation. The Common class is the foundation. Again, check the included and required scripts to see where Common was defines.
Hope that helps,
spryno724
I would start with:
throwing exception at certain points to see a stacktrace where the call originated.
grep for Class Common for example
create a directory listing to get a feeling for the organization of the software
use get_included_files(); to see what is actually used for a certain call
Start documenting what I find out
Start working with an IDE, like NetBeans, Eclipse or Zend Studio
Figuring out class hierarchies with maybe this "php: determining class hierarchy of an object at runtime" approach
You seem to realize that you can't read/digest every file, so you've got to focus on the important ones. Looks like you've started that process with SiteController.
Hopefully between reading the requires and using your IDE you can chase down the Home() and HomeView()
There might be a few key XML files that dictate the mappings from URLs to controller files, so you'll want to figure out how they work also.
I've worked with a poorly documented (but decently working) custom framework before, and your situation seems pretty similar. I found things pretty smooth once I understood the main controller and basically formed an understanding for how URL requests were processed.
1) You can use a search tool such as grep to find code, including definitions. But on a big code base, grep is slow, and it gives a lot of false positives because it has no understanding of the PHP language.
Our Search Engine is a GUI-based tool that indexes your source code to achieve extremely fast lookup, indexing by the langauge elements (variable names, constants, keywords, strings, ..) and allowing to formulate queries that honor the langauge structure (e.g., it ignores whitespace and comments unless you say you want to see them). A query shows hits in a hit window, and a click takes you to the file/line in which the hit occurs. With some tiny bit of additional configuration, you can go from the code window into your favorite editor.
2) Sometimes you want to know where specific functionality exists, but you have no clue what to search for. Here a test coverage tool can really help. Simple set up test coverage for the (working) application, and exercise the functionality manually; what is "covered" is potentially the code you care about. Exercise something which is NOT the feature; what is covered is NOT the code you want. This is way easier than trying to run a debugger to find the code of interest. Our PHP Test Coverage tool can provide you this coverage, and not only show you the covered code in GUI, but also do that "coverage subtraction" so that you can see just the relevant code.
Start from the entry point of the application (usually index.php) and go deeper on what gets called when.
Give PHPstorm a go, it's an ide with excellent code analyzing features, can go to definition of any class and variable, show inheritance hierarchy, find usages and many other useful stuff.
I'll also plug my own tool:
http://raveren.github.io/kint/
It's works with zero set up and is extremely useful to get a grip on what's going on where. Use Kint::trace(); to see a pretty execution backtrace and d(get_defined_vars()); to see what is defined in the current context and eventually you'll get there.
Screenshot:
(source: github.io)
I am trying to code the process of creating Zend_Form objects using Doctrine2 ClassMetadatas so that form generation for my client database application is easier.
I needed somewhere to store the element labels, descriptions, and etc. using custom phpdoc tags seemed a good idea. But it seems ClassMetadataInfo doesn't provide 'annotations' outside what it's expecting.
Thats sensible I guess, but im struggling to find a way to get it to parse the entire phpdoc block.
I've looked at using getReflectionClass() and parsing it myself, but id loose out on the great caching. The Doctrine2 parser works really well for what it does, but I can't make heads or tails of it!
Being able to use the phpdoc short description as an element label, and long description as the description would be rather handy for my form<>model friendships.
Anyone else pondered on this?
Dotrine2 provides both an AnnotationDriver (which is used by the ORM) and an AnnotationReader (used by the driver and which provides more abstract method).
Take a look at the source
Doctrine\ORM\Mapping\Driver\AnnotationDriver
Doctrine\Common\Annotations\AnnotationReader
In case anyone finds this answer: The latest version of Doctrine as of now includes a more advanced annotation reader, including caching mechanisms (which you probably want). Take a look at the doctrine documentation for some nice examples of usage.
I am using PHP in eclipse. It works ok, I can connect to my remote site, there is colour coding of code elements and some code hints.
I realise this may be too long to answer all questions, if you have a good answer for one part, answering just that is ok.
Firstly General Coding
I have found that it is easy to
loose track of included files and
their variables. For example if
there was a database $cursor it is
difficult to remember or even know
that it was declared in the included
file (this becomes much worse the
more files you include). How are
people dealing with this?
How are people documenting their
code - in particular the required
GET and POST data?
Secondly OO Development:
Should I be going full OO in my
development. Currently I have a
functions library which I can
include and have separated each
"task" into a separate file. It is a
bit nasty but it works.
If I go OO how do I structure the
directories in PHP, java uses
packages - what about php?
How should I name my files, should I
use all lower case with _ for spaces
"hello_world.php"? Should I name
classes with Uppercase like Java
"HelloWorld.php"? Is there a
different naming convention for
Classes and regular function files?
Thirdly Refactoring
I must say this is a real pain. If
I change the name of a variable in
one place I have to go through whole
document and each file that included
this file and change the name their
too. Of course, errors everywhere
is what results. How are people
dealing with this problem? In Java
if you change the name in one place
it changes everywhere.
Are there any plugins to improve php
refactoring? I am using the
official PHP version of Eclipse from
their website.
thanks
Firstly General Coding
1) OO can help you with that. As you encapsulate variables and functionality, they don't go out and mess with the namespaces. Assumind I understand right what problem you hint at, using an OO approach helps alleviating conflicts that can arise when you are inadvertedly redeclaring varables. (Note: Alleviate. Not completely prevent on its own. ;))
Otherwise a practise i have encounterd is prepending variable names with something like a 'package name' -- which merely shifts the problem one level up and isn't exactely beautiful either. :|
2) "However suits their purpose". PHPdoc is a good start; will help to create API documentation.
Secondly OO Development:
3) As said before -- "it depends". Do it when needed. You don't have to go full OO for "hello world". But you can. Weigh the costs and benefits of either route and choose wisely. Though I personally want to suggest when in doubt favour OOP over 'unstructured' approaches. Basically, know your tools and when to use them -- then you can make that call on your own easily. :)
4) As far as I can see, the directories "are structured like packages". Mind you, "directories" and "like". Having said that, various frameworks have solved that problem for theirselves; cf; th eother answers.
5) Again, however you please. There is not a definitive way You Have To Do It Or Else. Just stick to it once you chose your path ;3
Aside of that certain frameworks etc. have their own naming conventions. Symfony, e.g., uses CamelCase like Java.
Thirdly Refactoring
I must say this is a real pain.
yes :3 But it pays off.
If I change the name of a variable in one place I have to go through whole
document and each file that included this file and change the name their too.
Of course, errors everywhere is what results. How are people dealing with
this problem? In Java if you change the name in one place it changes everywhere.
No, it doesn't. If you get yourself a tool with support you only have to use the refactoring tool once; but if you rename a class property in java, there is no magic bot that walks through the internet and automagically makes sure everyone on the planet uses the new name. ;)
But as for how to prevent it -- be smart. Honour program contracts, i.e. use interfaces. Do not use functions / members you shouldn't use directly. Watch the hierarchies. Use a reasonable division of code and respect this division's boundaries.
But how people deal with that problem? Well, search and replace I suppose ;)
As for the Eclipse-Plugin -- The dynamic nature of PHP makes it more difficult to automagically refactor code; we can't always use static type hinting etc., and divination of argument and return types is impossible more often than not. So, to the extent of my knowledge, 'automatic refactoring' is not as well-supported by tools as in the Java world. Though I am sure for the doable cases, there should be plugins. :)
I've found using a PHP framework (e.g. Zend, Cake, CodeIgniter, etc) can force class structures and naming conventions while generally addressing autoloading as well. Using PHPDoc formatting liberally helps with code-completion and hinting as well as documenting specific requirements (e.g. method parameter definitions).
For the OO Development part:
I am using the autoload functionality to load the classes dynamically. My directory structure is like packages in java. My classes are named like in java (e.g. HelloWorld.php). But the class is defined with the complete path to that class (e.g. class FW_package1_package2_HelloWorld {...}).
If a class is called the autoload method replaces all _ against / and searches for the class with the extracted path (e.g. FW/package1/package2/HelloWorld.php).
I am strongly influenced by Java, so that I chose this way.
Take a look at nWire for PHP. It is a plugin for Eclipse PDT which provides code exploration and visualization.
It can easily be used to trace dependencies within your application and it is very handy for OO projects, enabling you to visualize class hierarchies and much more.
It doesn't support refactoring, but it can assist by showing you the references of a given components (e.g. a function or a field).