Статьи

Автоматизация PHP с помощью Phake — Примеры из реальной жизни

В первой части мы рассмотрели основы 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.

Есть какие-нибудь интересные задачи и варианты использования, которыми вы хотели бы поделиться с нами? Дайте нам знать об этом в комментариях.