DZone
Web Dev Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Web Dev Zone > Building a small microframework with PHP (Part 2). Command line interface

Building a small microframework with PHP (Part 2). Command line interface

Gonzalo Ayuso user avatar by
Gonzalo Ayuso
·
Aug. 30, 11 · Web Dev Zone · Interview
Like (0)
Save
Tweet
5.66K Views

Join the DZone community and get the full member experience.

Join For Free

In my last post we spoke about building a small microframework with PHP. The main goal of this kind of framework was to be able to map urls to plain PHP classes and become those classes easily testeable with PHPUnit. Now we’re going to take a step forward. Sometimes we need to execute the script from command line, for example if we need to use them in a crontab file.

OK. We can use curl and perform a simple http call to the webserver. But it’s pretty straightforward to create a command line interface (CLI) for our microframework. Zend Framework and Symfony has a great console tools. I’ve used Zend_Console_Getopt in a project and is really easy to use and well documented. But now we’re going to build a command line interface from scratch.

We are going to reuse a lot of code from the earlier post, because of that we are going to encapsulate the code in a class (DRY).

We will use the getopt function from PHP’s function set.

$sortOptions = "";
$sortOptions .= "c:";
$sortOptions .= "f:";
$sortOptions .= "v::";
$sortOptions .= "h::";

$options = getopt($sortOptions);

Then we need to take the paramaters from $GLOBALS['argv'] superglobal according with the options. I use the following hack to prepare $GLOBALS['argv']:

foreach( $options_array as $o => $a ) {
while($k=array_search("-". $o. $a, $GLOBALS['argv'])) {
if($k) {
unset($GLOBALS['argv'][$k]);
}
}
while($k=array_search("-" . $o, $GLOBALS['argv'])) {
if($k) {
unset($GLOBALS['argv'][$k]);
unset($GL">github</a>OBALS['argv'][$k+1]);
}
}
}
$GLOBALS['argv'] = array_merge($GLOBALS['argv']);

And now we get the params into $param_arr array.

$param_arr = array();
$lenght = count((array)$GLOBALS['argv']);
if ($lenght > 0) {
for ($i = 1; $i < $lenght; $i++) {
if (isset($GLOBALS['argv'][$i])) {
list($paramName, $paramValue) = explode("=", $GLOBALS['argv'][$i], 2);
$param_arr[$paramName] = $paramValue;
}
}
}

Now we can get className and functionName:

$className    = !array_key_exists('c', $options) ?: $options['c'];
$functionName = !array_key_exists('f', $options) ?: $options['f'];

We add a “usage” parameter:

if (array_key_exists('h', $options)) {
$usage = <<<USAGE
Usage: cli [options] [-c] <class> [-f] <function> [args...]

Options:
-h Print this help
-v verbose mode
\n
USAGE;
echo $usage;
exit;
}

Now we can invoke the function with call_user_func_array

return call_user_func_array(array($className, $functionName), $this->realParams);

As you can see, instead of using $param_arr as parameters array, We need to create an extra $realParams array. The aim of this realParams arrays is to use call_user_func_array with named parameters. In getRealParams function we use reflection to see what are the real parameters of our function and use only those parameters form in the correct order instead. With this trick we will allow to the user to use the parameters in the his desired order, and without forcing to use the real order of our function.

private function getRealParams($params)
{
$realParams = array();
$class = new ReflectionClass(new $this->className);
$reflect = $class->getMethod($this->functionName);

foreach ($reflect->getParameters() as $i => $param) {
$pname = $param->getName();
if ($param->isPassedByReference()) {
/// @todo shall we raise some warning?
}
if (array_key_exists($pname, $params)) {
$realParams[] = $params[$pname];
} else if ($param->isDefaultValueAvailable()) {
$realParams[] = $param->getDefaultValue();
} else {
throw new Exception("{$this->className}::{$this->functionName}() param: missing param: {$pname}");
}
}
return $realParams;
}

And now we can use our microframework from the command line:

./cli -c 'Demo\Foo' -f hello
Hello

./cli -c Demo\\Foo -f getUsers
["Gonzalo","Peter"]

./cli -c Demo\\Foo -f helloName name=Gonzalo surname=Ayuso
Hello Gonzalo Ayuso

Full code on github

From http://gonzalo123.wordpress.com/2011/08/29/building-a-small-microframework-with-php-part-2-command-line-interface/

PHP Command-line interface Command (computing) Interface (computing)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Fintech and AI: Ways Artificial Intelligence Is Used in Finance
  • Why Is Software Integration Important for Business?
  • Use Lambda Function URL To Write a Serverless App Backed by DynamoDB
  • How to Minimize Software Development Cost

Comments

Web Dev Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo