В первой части мы рассмотрели основы Phake и продемонстрировали способы выполнения задач с его помощью, включая группы, зависимости и аргументы. В этой части мы рассмотрим некоторые примеры реальных приложений Phake. Обратите внимание, что следующие примеры в значительной степени основаны на вещах, которые я обычно делаю вручную, которые требуют какой-то автоматизации.
Загрузка файлов на сервер с помощью задачи Phake
Давайте начнем с написания задачи, которая будет загружать файлы на 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"; } } } });
Как видно из приведенного выше кода, задача принимает пять аргументов:
- host — имя домена или IP-адрес сервера, на который вы хотите загрузить файлы
- пользователь
- проходят
- local_path — путь, который вы хотите загрузить
- remote_path — путь на сервере
Затем мы передаем эти аргументы методу ftp_connect
. Метод ftp_connect
возвращает поток ftp, который мы затем предоставляем в качестве первого аргумента для метода ftp_login
вместе с именем пользователя и паролем.
После этого мы можем перебрать все файлы в локальном пути, используя рекурсивный итератор итератор и рекурсивный итератор каталога . Итератор рекурсивного итератора принимает рекурсивный объект итератора каталога в качестве первого аргумента, а второй аргумент является константой из класса RecursiveIteratorIterator
. В нашей задаче мы RecursiveIteratorIterator::SELF_FIRST
в качестве второго аргумента. Это указывает итератору включать полный путь в каждую итерацию. Затем мы перебираем все файлы и каталоги по этому пути, используя цикл foreach
.
Мы можем проверить, является ли текущий путь файлом, используя метод isFile
. Если это файл, мы просто преобразуем его в строку, используя магический метод __toString
, и после преобразования мы присваиваем его переменной $current_file
. Далее мы объявляем другую переменную ( $dest_file
), которая будет содержать путь к текущему файлу без пути к корневому каталогу. Это будет использоваться в качестве имени пути для файла, который будет создан на сервере. Когда этим переменным присвоены значения, мы можем предоставить их в качестве аргументов для метода ftp_nb_put
. Это берет поток ftp, который был возвращен методом ftp_connect
ранее как первый аргумент. Второй аргумент — это путь к файлу на сервере, а третий — путь к файлу на вашем компьютере. Четвертый аргумент — это способ передачи; в этом случае мы использовали FTP_BINARY
. Затем мы можем загрузить файл, используя метод ftp_nb_continue
который принимает поток ftp в качестве аргумента. Пока этот метод возвращает константу FTP_MOREDATA
это означает, что конец файла все еще не достигнут, поэтому мы используем цикл while для его проверки. Как только это сделано, он возвращает FTP_FINISHED
.
Если текущий путь ссылается на каталог, мы также конвертируем его в строку, а затем проверяем, начинается ли он с .
потому что, как вы уже знаете, нам нужно исключить каталоги, которые начинаются с .
, Популярным примером является каталог .git
который git использует для хранения истории. Нам необходимо исключить эти каталоги, так как они часто не нужны для запуска приложения или веб-сайта и содержат метаданные или информацию о версиях.
Если текущий каталог не является скрытым, мы удаляем из него корневой путь, поскольку нам не нужно создавать этот путь на сервере. Вот почему мы используем str_replace
для замены str_replace
части пустой строкой.
Как только это будет сделано, мы можем просто вызвать метод ftp_mksubdirs
чтобы создать путь на сервере.
Метод 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); } } }
Эта функция создает каталоги, если они еще не существуют. Так что, если вы перейдете по следующему пути:
app / views / users
… И каталог app
, views
и users
еще не существует на сервере, он создает их все.
Вы можете запустить задачу выше, выполнив такую команду в терминале:
phake up host=someserver.com user=me pass=secret local_path=/home/wern/www/someproject remote_path=/public_html
Обратите внимание, что эта задача в основном относится к моему личному случаю использования — вы можете выполнять развертывание другим способом или вам вообще не нужна часть str_replace
. Важно то, что это живое задание, которое я на самом деле использую и которое облегчает мою жизнь.
Заполнение базы данных
С помощью Phake мы также можем написать задачу, которая будет заполнять базу данных для нас. Для этого нам понадобится библиотека под названием Faker. Чтобы использовать Faker, включите следующее в файл composer.json
вашего проекта:
{ "require": { "fzaninotto/faker": "1.5.*@dev" } }
Затем создайте задачу и назовите ее seed_users
. Это займет один аргумент под названием rows
. Это позволяет вам установить количество строк, которые вы хотите вставить в свои таблицы.
task('seed_users', function($args){ $rows = 1000; if(!empty($args['rows']){ $count = $args['rows']; } });
Далее мы подключаемся к базе данных, используя Mysqli :
$host = 'localhost'; $user = 'user'; $pass = 'secret'; $database = 'test'; $db = new Mysqli($host, $user, $pass, $database);
Затем мы инициализируем новый генератор 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";
Собрав все воедино, мы получаем следующую задачу:
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"; });
После этого вы можете вызвать задачу, выполнив следующую команду:
phake seed_users rows = 1000
Синхронизация данных
Другая задача, которую я обычно выполняю периодически, — это синхронизация изменений базы данных с моей локальной машины на сервер. С помощью Phake это можно легко автоматизировать с помощью mysqldump
, программы резервного копирования базы данных, которая поставляется с MySQL. Из этой задачи все, что вам нужно сделать, это выполнить команду mysqldump, используя метод exec
в PHP. Программа mysqldump принимает имя базы данных, пользователя и пароль в качестве аргументов. Затем вы можете передать его в команду ssh
. После того, как ssh
будет выполнен, он попросит вас mysql $remote_db
пароль, а после того, как вы mysql $remote_db
пароль, он выполнит команду 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"); });
Вы можете вызвать вышеуказанную задачу, используя следующую команду. Просто подставьте свои учетные данные:
phake sync_db db=my_db db_user=me db_pass=secret ssh_user=me host=somewebsite.com remote_db=my_db
Обратите внимание, что если это не работает, вам может потребоваться установить следующие значения в файле sshd_config
расположенном в /etc/ssh/sshd_config
:
X11Forwarding yes X11UseLocalhost no
После этого перезагрузите sshd, чтобы изменения вступили в силу:
sudo /etc/init.d/sshd reload
Вывод
Phake — это хороший способ автоматизировать повседневные задачи и сэкономить время, заставляя компьютер выполнять всю работу за вас. С помощью Phake вы можете автоматизировать практически все, о чем вы только можете подумать. Он предоставляет вам все необходимые инструменты для автоматизации задач. Если вы обнаружите, что делаете что-то повторяющееся, подумайте, как вы можете автоматизировать это с помощью Phake.
Есть какие-нибудь интересные задачи и варианты использования, которыми вы хотели бы поделиться с нами? Дайте нам знать об этом в комментариях.