Key Takeaways
- Phake is an automation tool designed for PHP, allowing developers to automate repetitive tasks such as updating the database structure, seeding the database, writing CRUD code, running tests, and uploading files to a server.
- To use Phake, tasks must be created and configured in a Phakefile, which is similar to a Gruntfile. Tasks can be executed in order, have dependencies, and can be grouped together for related tasks.
- Phake also allows for the description of tasks, making it easier to understand what a specific task does. This is particularly useful when dealing with a large number of tasks in a Phakefile.
- Phake tasks can be made more flexible by passing in arguments, allowing for specific task customization. This is done by declaring a parameter in the function, which can then be used to access individual arguments passed into the task.
As developers, we often have to do repetitive tasks such as updating the database structure, seeding the database, writing CRUD code, running tests, and uploading files to a server. Wouldn’t it be great if we could automate these mundane tasks and proceed with solving the more important problems such as making our app more secure or more usable to our users?
Phake, an automation tool written for PHP, can do those tasks for you. If you’re familiar with Ruby, it’s basically a Rake clone. In this two-part series I’m going to walk you through integrating Phake into your workflow. I will walk you through the installation, some of the basics in using Phake and then finally some real-world examples.
Installation
Phake should be installed globally via Composer:
composer global require 'jaz303/phake=*'
This makes Phake accessible from any folder, and doesn’t require you to change your project’s composer.json
file.
If you don’t have access to the ‘composer’ command, install Composer globally.
Basics
To execute Phake tasks, you need to create a Phakefile. The Phakefile
contains the configuration for the tasks that you want to execute. If you’ve used Grunt before, a Phakefile
is similar to a Gruntfile
.
An important note about the Phakefile
is that it’s just a PHP file so you can just write it the same way as you do with your PHP projects.
Creating Tasks
You can create tasks by calling the task()
method. This takes up the name of the task as the first argument, and the function to execute as the last argument.
<?php
task('task_a', function(){
echo "Hi I'm task A!\n";
});
You can then execute it with the following command:
phake task_a
This will then return the following output:
Hi I'm task A!
Dependencies
If one task depends on another task, you can supply the name of that task right after the main task:
<?php
task('task_a', function(){
echo "Hi I'm task A!\n";
});
task('task_b', 'task_a', function(){
echo "Hi I'm task B! I need task A to execute first before I can do my thing!\n";
});
To execute the tasks in order you just have to call the task which has a dependency first. In this case task_b
depends on task_a
so we call it first:
phake task_b
Executing it will return the following output:
Hi I'm task A!
Hi I'm task B! I need task A to execute first before I can do my thing!
And you can keep on adding dependencies:
<?php
task('task_a', function(){
echo "I get to execute first!\n";
});
task('task_b', 'task_a', function(){
echo "Second here!\n";
});
task('task_c', 'task_b', function(){
echo "I'm the last one!\n";
});
Execute them by calling the the final task that needs to be called. In this case, it’s task_c
that we want to execute last:
phake task_c
It will then return the following output:
I get to execute first!
Second here!
I'm the last one!
Note that with this method of declaring dependencies, calling task_b
would result in task_a
being called first. If you don’t want this to happen and you still want to execute a specific task separately without executing its dependencies first then you can declare it using the following method:
task('task_a', function(){
echo "I get to execute first!\n";
});
task('task_b', function(){
echo "Second here!\n";
});
task('task_c', 'task_a', 'task_b', function(){
echo "I'm the last one!\n";
});
In the example above we are setting task_a
, and task_b
as the dependencies of task_c
. Note that the order matters here. So the task right after the main task (task_a
) will get executed first, and the one right next to it (task_b
) will be the second and then finally the main task (task_c
) is executed.
With Phake there’s another way of defining your dependencies: through the use of before or after blocks right after defining the main task. In this case our main task is to eat
so we define the tasks that we want to execute before and after it under its declaration:
task('eat', function(){
echo "Yum!";
});
before('eat', function(){
echo "Wash your hands before you eat\n";
});
after('eat', function(){
echo "Brushy brush! brush!\n";
});
When you execute eat
you get the following output:
Wash your hands before you eat
Yum!
Brushy brush! brush!
Grouping Tasks
With Phake you can also group related tasks together:
group('clean_the_house', function(){
task('polish_furniture', function(){..});
task('wash_the_clothes', function(){..});
task('mop_the_floor', function(){..});
});
Grouped tasks can be called using the group name that you specified, followed by a colon, then the name of the task that you want to execute:
phake clean_the_house:polish_furniture
If you want to execute all of the tasks in a group you can just make the final task depend on the first and second task. In the example below, the final task that we want to execute is the mop_the_floor
task so we make it depend on the polish_furniture
and wash_the_clothes
task:
group('clean_the_house', function(){
task('polish_furniture', function(){..});
task('wash_the_clothes', function(){..});
task('mop_the_floor', 'polish_furniture', 'wash_the_clothes' function(){..});
});
Then we simply call the mop_the_floor
task from the terminal:
phake clean_the_house:mop_the_floor
This will then call the tasks in the following order:
polish_furniture
wash_the_clothes
mop_the_floor
Describing Tasks
After some time of using Phake, you might accumulate a bunch of tasks in your Phakefile
, so its a good idea to have some sort of documentation. Lucky for us, Phake comes with a utility that allows us to describe what a specific Phake task does. You can use it by calling the desc
method right before the declaration of the task that you want to describe:
desc('Allows you to water the plants');
task('hose', function(){..});
desc('Allows you to wash the dish');
task('dish_washer', function(){..});
You can then list out the available tasks in your Phakefile with the following command:
phake -T
It will return an output similar to the following:
hose Allows you to water the plants
dish_washer Allows you to wash the dish
Passing Arguments to Tasks
To make the tasks more flexible we can also pass in arguments. This can be done by declaring a parameter in the function. This can then be used to access individual arguments that you pass in to the task:
task('brush_teeth', function($args){
$motion = (!empty($args['motion'])) ? $args['motion'] : 'circular';
$includes = (!empty($args['includes'])) ? $args['includes'] : '';
brush($motion, $includes);
});
Arguments can be passed by including a name-value pair right after the name of the task. If you wish to pass in more than 1 argument you can separate them by using a single space between the value of the first argument and the name of the second argument:
phake brush_teeth motion=horizontal includes=tongue,teeth,gums
If you need to pass in arguments with spaces between them you can simply wrap it up in single or double quotes:
phake brush_teeth motion="circular horizontal and vertical"
Conclusion
Now that we’ve seen what Phake is for and how we can execute tasks with it, we’ve readied the terrain for some real world applications in part two. Stay tuned!
Frequently Asked Questions about Automating PHP with Phake
How do I install Phake in my PHP project?
To install Phake in your PHP project, you need to use Composer, a tool for dependency management in PHP. You can install it by running the command composer require --dev phake/phake
. This command tells Composer to add Phake as a development dependency in your project. After running this command, Composer will download Phake and its dependencies into your project.
What is the purpose of the Phakefile in a PHP project?
The Phakefile is a crucial part of a PHP project that uses Phake. It’s where you define tasks that Phake can run. These tasks can include anything from running tests to deploying your application. The Phakefile is written in PHP, and it uses Phake’s API to define tasks.
How do I define a task in a Phakefile?
To define a task in a Phakefile, you use the task
function provided by Phake. This function takes two arguments: the name of the task and a closure that defines what the task does. For example, to define a task that runs PHPUnit tests, you could write the following code in your Phakefile:task('test', function() {
exec('phpunit');
});
How do I run a task defined in a Phakefile?
To run a task defined in a Phakefile, you use the phake
command followed by the name of the task. For example, to run the ‘test’ task defined in the previous question, you would run the command phake test
in your terminal.
Can I define dependencies between tasks in a Phakefile?
Yes, you can define dependencies between tasks in a Phakefile. To do this, you use the dependsOn
function provided by Phake. This function takes one or more task names as arguments, and it tells Phake that the current task depends on the tasks passed as arguments. For example, if you have a ‘deploy’ task that depends on a ‘test’ task, you could define this dependency like so:task('deploy', function() {
// deployment code here
})->dependsOn('test');
How do I use Phake to mock objects in my tests?
Phake provides a powerful and flexible API for mocking objects in your tests. To create a mock object, you use the Phake::mock
function, passing the name of the class you want to mock as an argument. You can then use the Phake::when
function to define how the mock object should behave when its methods are called. For example, to create a mock of a UserRepository
class and define its find
method, you could write the following code:$userRepository = Phake::mock('UserRepository');
Phake::when($userRepository)->find(Phake::anyParameters())->thenReturn(new User());
How do I verify that a method was called on a mock object?
To verify that a method was called on a mock object, you use the Phake::verify
function. This function takes two arguments: the mock object and a call to the method you want to verify. For example, to verify that the find
method was called on the UserRepository
mock from the previous question, you would write the following code:Phake::verify($userRepository)->find(Phake::anyParameters());
Can I use Phake to stub methods on real objects?
Yes, you can use Phake to stub methods on real objects. To do this, you use the Phake::partialMock
function instead of the Phake::mock
function. This function creates a mock object that inherits from the real object, allowing you to stub methods while preserving the real object’s behavior for other methods.
How do I define a default task in a Phakefile?
To define a default task in a Phakefile, you use the defaultTask
function provided by Phake. This function takes the name of the task that should be run when no task name is provided to the phake
command. For example, to set the ‘test’ task as the default task, you would write the following code in your Phakefile:defaultTask('test');
Can I use Phake with other testing frameworks?
Yes, you can use Phake with other testing frameworks. Phake is not tied to any specific testing framework, so you can use it with any framework that supports mocking, such as PHPUnit or Behat. To use Phake with another testing framework, you simply need to include Phake in your project using Composer and then use Phake’s API in your tests as you normally would.
Wern is a web developer from the Philippines. He loves building things for the web and sharing the things he has learned by writing in his blog. When he's not coding or learning something new, he enjoys watching anime and playing video games.