git 实际应用示例
In part one, we covered the basics of Phake and demonstrated ways of executing tasks with it, covering groups, dependencies, and arguments. In this part, we’ll look at some sample real world applications of Phake. Note that the following examples are largely based on things that I usually do manually that need some sort of automation.
在第一部分中 ,我们介绍了Phake的基础知识,并演示了使用它执行任务的方式,包括组,依赖项和参数。 在这一部分中,我们将研究Phake的一些示例实际应用。 请注意,以下示例在很大程度上基于我通常需要一些自动化的手动操作。
使用Phake任务将文件上传到服务器 (Uploading Files to Server with a Phake task)
Let’s start by writing a task that will upload files to an FTP server.
让我们从编写一个将文件上传到FTP服务器的任务开始。
task('up', function($args){
$host = $args['host'];
$user = $args['user'];
$pass = $args['pass'];
$port = 21; //default ftp port
$timeout = 60; //timeout for uploading individual files
//connect to server
$ftp = ftp_connect($host, $port, $timeout);
ftp_login($ftp, $user, $pass); //login to server
$root_local_dir = $args['local_path'];
$root_ftp_dir = $args['remote_path'];
$dir_to_upload = $args['local_path'];
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir_to_upload), RecursiveIteratorIterator::SELF_FIRST);
//iterate through all the files and folders in the specified directory
foreach($iterator as $path){
//if the current path refers to a file
if($path->isFile()){
$current_file = $path->__toString();
$dest_file = str_replace($root_local_dir, $root_ftp_dir, $current_file);
$result = ftp_nb_put($ftp, $dest_file, $current_file, FTP_BINARY);
//while the end of the file is not yet reached keep uploading
while($result == FTP_MOREDATA){
$result = ftp_nb_continue($ftp);
}
//once the whole file has finished uploading
if($result == FTP_FINISHED){
echo "uploaded: " . $current_file . "\n";
}
}else{
//if the current path refers to a directory
$current_dir = $path->__toString();
//if the name of the directory doesn't begin with dot
if(substr($current_dir, -1) != '.'){
//remove the path to the directory from the current path
$current_dir = str_replace($root_local_dir, '', $current_dir);
//remove the beginning slash from current path
$current_dir = substr($current_dir, 1);
//create the directory in the server
ftp_mksubdirs($ftp, $root_ftp_dir, $current_dir);
echo "created dir: " . $current_dir . "\n";
}
}
}
});
As you can see from the code above, the task accepts five arguments:
从上面的代码中可以看到,该任务接受五个参数:
host – the domain name or the ip address of the server where you want to upload the files
主机 –您要在其中上传文件的服务器的域名或IP地址
user
用户
pass
通过
local_path – the path that you want to upload
local_path –您要上传的路径
remote_path – the path in the server
remote_path –服务器中的路径
We then pass on these arguments to the ftp_connect
method. The ftp_connect
method returns an ftp stream which we then supply as a first argument for the ftp_login
method along with the username and password.
然后,我们将这些参数传递给ftp_connect
方法。 ftp_connect
方法返回一个ftp流,然后我们将其作为ftp_login
方法的第一个参数以及用户名和密码提供。
After that, we can iterate through all the files in the local path using the recursive iterator iterator and recursive directory iterator. The recursive iterator iterator takes up a recursive directory iterator object as its first argument and the second argument is a constant from the RecursiveIteratorIterator
class. In our task, we have supplied RecursiveIteratorIterator::SELF_FIRST
as the second argument. This instructs the iterator to include the full path in every iteration. We then loop through all the files and directories in that path using a foreach
loop.
之后,我们可以使用递归迭代器迭代器和递归目录迭代 器遍历本地路径中的所有文件。 递归迭代器迭代器将递归目录迭代器对象作为其第一个参数,第二个参数是RecursiveIteratorIterator
类中的常量。 在我们的任务中,我们提供了RecursiveIteratorIterator::SELF_FIRST
作为第二个参数。 这指示迭代器在每次迭代中包括完整路径。 然后,我们使用foreach
循环foreach
该路径中的所有文件和目录。
We can check whether the current path is a file using the isFile
method. If it’s a file, we just convert it to a string using the __toString
magic method, and once converted we assign it to the $current_file
variable. Next, we declare another variable ($dest_file
) that will hold the path to the current file without the path to the root directory. This will be used as the name of the path for the file that will be created on the server. Once those variables have values assigned to them, we can supply them as the arguments for the ftp_nb_put
method. This takes the ftp stream which was returned by the ftp_connect
method earlier as the first argument. The second argument is the path to the file on the server and the third one is the path to the file in your computer. The fourth argument is the mode of transfer; in this case we used FTP_BINARY
. We can then upload the file by using the ftp_nb_continue
method which takes the ftp stream as its argument. As long as this method returns the FTP_MOREDATA
constant it means the end of the file still hasn’t been reached, so we’re using a while
loop to check for it. Once it’s done it returns FTP_FINISHED
.
我们可以使用isFile
方法检查当前路径是否为文件。 如果是文件,则只需使用__toString
magic方法将其转换为字符串,然后将其分配给$current_file
变量。 接下来,我们声明另一个变量( $dest_file
),该变量将保存当前文件的路径而不包含根目录的路径。 这将用作将在服务器上创建的文件的路径的名称。 一旦为这些变量分配了值,我们就可以将它们作为ftp_nb_put
方法的参数提供。 这将前面由ftp_connect
方法返回的ftp流作为第一个参数。 第二个参数是服务器上文件的路径,第三个参数是计算机上文件的路径。 第四个论点是转移方式。 在这种情况下,我们使用FTP_BINARY
。 然后,我们可以使用ftp_nb_continue
方法上传文件,该方法将ftp流作为其参数。 只要此方法返回FTP_MOREDATA
常量,就意味着仍未到达文件结尾,因此我们正在使用while
循环进行检查。 完成后,将返回FTP_FINISHED
。
If the current path refers to a directory, we also convert it to a string, then check if it begins with .
, because as you might already know we need to exclude directories that begin with .
. A popular example is the .git
directory that git uses to store history. We need to exclude these directories as they’re often not needed for the app or website to run and contain meta data or versioning info.
如果当前路径指向目录,我们还将其转换为字符串,然后检查其是否以开头.
,因为您可能已经知道,我们需要排除以开头的目录.
。 一个流行的示例是git用于存储历史记录的.git
目录。 我们需要排除这些目录,因为应用程序或网站通常不需要它们,并且不包含元数据或版本信息。
If the current directory isn’t a hidden directory, we remove the root path from it because we don’t need to create that path in the server. That is why we’re using str_replace
to replace the part that we don’t need with an empty string.
如果当前目录不是隐藏目录,则由于不需要在服务器中创建该路径,因此我们从其中删除了根路径。 这就是为什么我们使用str_replace
用空字符串替换不需要的部分。
Once that’s done we can just call the ftp_mksubdirs
method to create the path in the server.
完成后,我们可以调用ftp_mksubdirs
方法在服务器中创建路径。
The ftp_mksubdirs
method takes the ftp stream, the root directory in the server and the path to the current directory. Note that this is not a method that’s built into PHP; we first need to declare it before we can use it. Here’s the function:
ftp_mksubdirs
方法采用ftp流,服务器中的根目录以及当前目录的路径。 请注意,这不是PHP内置的方法。 我们首先需要声明它才能使用它。 功能如下:
function ftp_mksubdirs($ftpcon, $ftpbasedir, $ftpath){
@ftp_chdir($ftpcon, $ftpbasedir);
$parts = explode('/',$ftpath);
foreach($parts as $part){
if(!@ftp_chdir($ftpcon, $part)){
ftp_mkdir($ftpcon, $part);
ftp_chdir($ftpcon, $part);
}
}
}
What this function does is create the directories if they do not exist yet. So if you pass in the following path:
该功能的作用是创建尚不存在的目录。 因此,如果您输入以下路径:
app/views/users
…and the the app
, views
and users
directories don’t exist on the server yet, it creates all of them.
…并且服务器上尚不存在app
, views
和users
目录,它将创建所有目录。
You can run the task above by executing a command like this one in the terminal:
您可以通过在终端中执行以下命令来运行上述任务:
phake up host=someserver.com user=me pass=secret local_path=/home/wern/www/someproject remote_path=/public_html
Note that this task applies to my own personal use case mostly – you might be doing your deploys another way, or you might not be needing the str_replace
part at all. What matters is that this is a live task that I actually use, and which makes my life easier.
请注意,此任务主要适用于我自己的个人用例–您可能正在以其他方式进行部署,或者根本不需要str_replace
部分。 重要的是这是我实际使用的实时任务,这使我的生活更轻松。
播种数据库 (Seeding the Database)
With Phake we can also write a task that will seed the database for us. For that, we’re going to need to use a library called Faker. To use Faker include the following in your project’s composer.json
file:
使用Phake,我们还可以编写一个任务,为我们播种数据库。 为此,我们将需要使用一个名为Faker的库。 要使用Faker,请在项目的composer.json
文件中添加以下内容:
{
"require": {
"fzaninotto/faker": "1.5.*@dev"
}
}
Next create a task and call it seed_users
. It will take one argument called rows
. This allows you to set the number of rows you want to insert into your tables.
接下来创建一个任务并将其seed_users
。 它需要一个称为rows
参数。 这使您可以设置要插入表中的行数。
task('seed_users', function($args){
$rows = 1000;
if(!empty($args['rows']){
$count = $args['rows'];
}
});
Next, we connect to the database using Mysqli:
接下来,我们使用Mysqli连接到数据库:
$host = 'localhost';
$user = 'user';
$pass = 'secret';
$database = 'test';
$db = new Mysqli($host, $user, $pass, $database);
Then, we initialize a new Faker generator and assign it to the $faker
variable. With a for
loop, we repeatedly execute the code which generates and saves the user data into the database. We set it to execute until it reaches the number of rows that we have as an argument. By default it will execute 100 times which generates 100 random users, but all with the same password, so we can easily log in as one in case we need to.
然后,我们初始化一个新的Faker生成器,并将其分配给$faker
变量。 通过for
循环,我们重复执行代码,该代码生成用户数据并将其保存到数据库中。 我们将其设置为执行,直到达到参数的行数为止。 默认情况下,它将执行100次,生成100个随机用户,但是所有用户都使用相同的密码,因此我们可以轻松地以一个人的身份登录。
$faker = Faker\Factory::create();
for($x = 0; $x <= $rows; $x++){
$email = $faker->email;
$password = password_hash('secret', PASSWORD_DEFAULT);
$first_name = $faker->firstName;
$last_name = $faker->lastName;
$address = $faker->address;
$db->query("INSERT INTO users SET email = '$email', password = '$password'");
$db->query("INSERT INTO user_info SET first_name = '$first_name', last_name = '$last_name', address = '$address'");
}
echo "Database was seeded!\n";
Putting everything together we end up with the following task:
将所有内容放在一起,我们将完成以下任务:
task('seed_users', function($args){
$rows = 1000;
if(!empty($args['rows']){
$rows = $args['rows'];
}
$host = 'localhost';
$user = 'user';
$pass = 'secret';
$database = 'test';
$db = new Mysqli($host, $user, $pass, $database);
$faker = Faker\Factory::create();
for($x = 0; $x <= $rows; $x++){
$email = $faker->email;
$password = password_hash('secret', PASSWORD_DEFAULT);
$first_name = $faker->firstName;
$last_name = $faker->lastName;
$address = $faker->address;
$db->query("INSERT INTO users SET email = '$email', password = '$password'");
$db->query("INSERT INTO user_info SET first_name = '$first_name', last_name = '$last_name', address = '$address'");
}
echo "Database was seeded!\n";
});
Once that’s done you can call the task by executing the following command:
完成后,您可以通过执行以下命令来调用任务:
phake seed_users rows=1000
同步数据 (Syncing Data)
Another task that I usually find myself doing repetitively is syncing the database changes from my local machine to a server. With Phake, this can be easily automated by using mysqldump
, a database backup program that comes with MySQL. From the task, all you have to do is execute the mysqldump command using the exec
method in PHP. The mysqldump program accepts the name of the database, the user and the password as its arguments. You can then pipe it to the ssh
command. Once ssh
is executed, it will ask you for the password, and once you’ve entered the password it will execute the mysql $remote_db
command. What this does is get the query that was dumped by the mysqldump
command earlier and execute it on the server. Note that this overwrites whatever it is that’s currently on the server so this is only recommended when you’re still in the development phase of your app.
我通常会发现自己反复进行的另一项任务是将数据库更改从本地计算机同步到服务器。 使用Phake,可以通过使用mysqldump
(这是MySQL附带的数据库备份程序)轻松地实现自动化。 从该任务开始,您要做的就是使用PHP中的exec
方法执行mysqldump命令。 mysqldump程序接受数据库的名称,用户和密码作为其参数。 然后,您可以将其通过管道传递给ssh
命令。 一旦执行了ssh
,它将要求您输入密码,而一旦输入密码,它将执行mysql $remote_db
命令。 这样做是获取较早之前mysqldump
命令转储的查询并在服务器上执行它。 请注意,这将覆盖服务器上当前的内容,因此仅当您仍处于应用程序的开发阶段时才建议这样做。
task('sync_db', function($args){
$db = $args['db']; //name of the local database
$user = $args['db_user']; //database user
$pass = $args['db_pass']; //the user's password
$host = $args['host']; //domain name of the server you want to connect to
$ssh_user = $args['ssh_user']; //the user used for logging in
$remote_db = $args['remote_db']; //the name of the database in the server
exec("mysqldump $db -u $user -p$pass | ssh $ssh_user@$host mysql $remote_db");
});
You can call the task above by using the following command. Just substitute the credentials for your own:
您可以使用以下命令来调用上述任务。 只需将凭据替换为您自己的凭据即可:
phake sync_db db=my_db db_user=me db_pass=secret ssh_user=me host=somewebsite.com remote_db=my_db
Note that if this doesn’t work you might need to set the following values in your sshd_config
file located at /etc/ssh/sshd_config
:
请注意,如果这不起作用,则可能需要在/etc/ssh/sshd_config
中的sshd_config
文件中设置以下值:
X11Forwarding yes
X11UseLocalhost no
Once that’s done reload sshd for the changes to take effect:
完成后,重新加载sshd以使更改生效:
sudo /etc/init.d/sshd reload
结论 (Conclusion)
Phake is a nice way to automate mundane tasks and save time by making the computer do the work for you. With Phake, you can automate pretty much anything that you can think of. It provides you with with all the necessary tools for task automation. If you find yourself doing something repetitive, think of how you can automate it with Phake.
Phake是使平凡的工作自动化并节省时间的一种好方法,它可以使计算机为您完成工作。 使用Phake,您几乎可以想到的任何东西都可以自动化。 它为您提供了用于任务自动化的所有必要工具。 如果您发现自己做了重复的事情,请考虑如何使用Phake使其自动化。
Got any interesting tasks and use cases you’d like to share with us? Let us know in the comments.
有想要与我们分享的有趣任务和用例吗? 让我们在评论中知道。
翻译自: https://www.sitepoint.com/automate-php-phake-real-world-examples/
git 实际应用示例