Статьи

Как использовать API Github с PHP

Github — один из лучших способов поделиться кодом и сотрудничать. В этой статье мы узнаем, как использовать их API и как мы можем использовать его для выполнения некоторых наших повседневных задач.

Github logo

Что мы строим

Мы собираемся изучить некоторые повседневные задачи, которые можно выполнить с помощью API Github, и создадим небольшое приложение с использованием Laravel для иллюстрации вариантов использования. Вы можете проверить окончательный результат на Github .

авторизация

Прежде чем начать использовать API, нам нужно установить некоторую форму авторизации. API предоставляет вам доступ ко всем общедоступным данным, но некоторые конечные точки требуют разрешения пользователя. Вы можете создать новый токен с определенным доступом к области, используя настройки приложения . Области зависят от потребностей вашего приложения, таких как доступ к электронной почте пользователя, обновление профиля пользователя и т. Д.

Авторизация по паролю необходима только в некоторых особых случаях, например при доступе к авторизованным пользователям приложениям . В этом случае вам необходимо указать свое имя пользователя или адрес электронной почты, а также пароль.

Настройка нашего приложения

Для нашего примера приложения я буду использовать Laravel 5 и PHP-реализацию KnpLabs Github. Обязательно обновите файл composer.json . Переименуйте .env.example в .env после создания нового проекта Laravel ( composer create-project laravel/laravel ) и обновите его, composer create-project laravel/laravel свои учетные данные.

 // .env APP_DEBUG=true GITHUB_EMAIL=USER_EMAIL GITHUB_USERNAME=USERNAME GITHUB_PASSWORD=PASSWORD GITHUB_TOKEN=ACCESS_TOKEN 

Вам на самом деле не нужно добавлять свое имя пользователя и пароль, мы используем их только для иллюстрации ограничения использования аутентификации токена.

Обязательный клиент Github

 // bootstrap/app.php $app->singleton('Github\Client', function(){ $client = new Github\Client(); return $client; }); 

Возможно, вы заметили, что мы не использовали наш токен. Это связано с тем, что большинство открытых действий выполняются без какой-либо авторизации, но для каждой конечной точки вы найдете уровень аутентификации, необходимый для доступа к ней.

Маршрутизация

Наше демо будет включать в себя несколько основных функций.

  • Список пользовательских репозиториев.
  • Навигация по файлам репозитория пользователя.
  • Отредактируйте и передайте файл.
  • Перечислите последние коммиты хранилища.
 // app/Http/routes.php Route::get('/', ['uses' => 'GithubController@index', 'as' => 'index']); Route::get('/finder', ['uses' => 'GithubController@finder', 'as' => 'finder']); Route::get('/edit', ['uses' => 'GithubController@edit', 'as' => 'edit_file']); Route::post('/update', ['uses' => 'GithubController@update', 'as' => 'update_file']); Route::get('/commits', ['uses' => 'GithubController@commits', 'as' => 'commits']); 

Контроллеры

Класс GithubController является нашим основным контроллером и содержит большую часть логики. Когда вызывается конструктор класса, мы определяем класс Github\Client из контейнера и загружаем нашу переменную окружения username.

 // app/Http/Controllers/GithubController.php class GithubController extends Controller { private $client; /* * Github username * * @var string * */ private $username; public function __construct(\Github\Client $client) { $this->client = $client; $this->username = env('GITHUB_USERNAME'); } } 

Листинговые репозитории

Репозитории по имени пользователя

Вы можете получить репозитории по имени пользователя, используя конечную точку /users/:username/repos . Мы можем получить доступ к конечной точке следующим образом:

 $repos = $this->client->api('user')->repositories($username); 

Метод api разрешит необходимый класс в зависимости от параметра ( user , current_user , repo и т. Д.).

Аутентифицированный пользователь

Другой способ — получить текущие аутентифицированные пользовательские репозитории, используя конечную точку /user/repos . Основное отличие заключается в том, что частные репозитории скрыты, когда используется только конечная точка имени пользователя.

 // client is our Github\Client $repos = $this->client->api('current_user')->repositories(); 

Теперь, когда мы знаем первое преимущество использования аутентифицированных запросов, давайте добавим наш токен в привязку Github\Client .

 $app->singleton('Github\Client', function () { $client = new Github\Client(); $token = env('GITHUB_TOKEN'); if (!isset($token)) { dd("Github token is not set."); } //$client->authenticate(env('GITHUB_EMAIL'), env('GITHUB_PASSWORD'), Github\Client::AUTH_HTTP_PASSWORD); $client->authenticate($token, null, Github\Client::AUTH_HTTP_TOKEN); return $client; }); 

Метод authenticate решает процесс аутентификации с использованием третьей константы параметра. Если вы выбрали метод электронной почты и пароль, обязательно измените проверку утверждения. Вы можете проверить документы для получения дополнительной информации.

 // app/Http/Controllers/GithubController.php public function index() { try { $repos = $this->client->api('current_user')->repositories(); return View::make('repos', ['repos' => $repos]); } catch (\RuntimeException $e) { $this->handleAPIException($e); } }//index 

Repos

Имя репо передается следующему маршруту, и оно используется для запроса API для содержимого репозитория. Вы можете прочитать больше в документации .

 // app/resources/views/repos.blade.php @extends('layouts.master') @section('content') <div class="list-group"> @foreach($repos as $repo) <a class="list-group-item" href="/finder?repo={{ $repo['name'] }}"> <h4 class="list-group-item-heading">{{ $repo['name'] }}</h4> <p class="list-group-item-text">{{ $repo['description'] }}</p> </a> @endforeach </div> @endsection 

Page index

На странице также может отображаться количество звездных наблюдателей, количество загрузок и т. Д. Когда пользователь нажимает на ссылку, нам нужно загрузить содержимое репозитория и предоставить возможность просматривать файлы репозитория.

Содержимое репозитория

Чтобы получить содержимое хранилища, вам нужно указать владельца, имя хранилища и путь, который вы хотите получить. Вы можете прочитать больше в документации .

 // app/Http/Controllers/GithubController.php public function finder() { $repo = Input::get('repo'); $path = Input::get('path', '.'); try { $result = $this->client->api('repo')->contents()->show($this->username, $repo, $path); return View::make('finder', ['parent' => dirname($path), 'repo' => $repo, 'items' => $result]); } catch (\RuntimeException $e) { $this->handleAPIException($e); } }//finder 

Метод Github\Api\Repository\Contents@show принимает четыре параметра, четвертый — ветвь и по умолчанию — master .

Repo content

Когда пользователь выбирает папку, мы перезагружаем ту же страницу с новым путем, а при выборе файла мы перенаправляем их на страницу редактирования.

Repo content

 // app/resources/views/finder.blade.php <ul class="list-group"> @foreach($items as $item) <li class="list-group-item"> @if(isset($item['type']) && $item['type'] == 'file') <a href="/edit?repo={{ $repo }}&path={{ $item['path'] }}">{{ $item['name'] }}</a> <span class="badge">F</span> @else <a href="/finder?repo={{ $repo }}&path={{ $item['path'] }}">{{ $item['name'] }}</a> <span class="badge">D</span> @endif </li> @endforeach </ul> 

Если текущий тип элемента является файлом, мы создаем ссылку на страницу редактирования, в противном случае мы создаем ссылку с новым путем к папке. Мы также добавляем значок, чтобы упростить идентификацию типа файла и ссылку возврата.

Редактирование файлов

Метод Github\Api\Repository\Contents@show возвращает либо массив элементов, либо элемент с правильным типом файла .

Single file dump

Когда тип файла является file , содержимое будет закодировано в file base64. Мы не будем иметь дело с другими типами, такими как submodule или symlink .

 // app/Http/Controllers/GithubController.php public function edit() { $repo = Input::get('repo'); $path = Input::get('path'); try { $file = $this->client->api('repo')->contents()->show($this->username, $repo, $path); $content = base64_decode($file['content']); $commitMessage = "Updated file " . $file['name']; return View::make('file_update', [ 'file' => $file, 'path' => $path, 'repo' => $repo, 'content' => $content, 'commitMessage' => $commitMessage ]); } catch (\RuntimeException $e) { $this->handleAPIException($e); } }//edit 
 // app/resources/views/file_update.blade.php <ol class="breadcrumb"> <li><a href="{{ $file['download_url'] }}" target="_blank">Download</a></li> <li><a href="{{ $file['html_url'] }}" target="_blank">View file</a></li> </ol> {!! Form::open(['url' => '/update', 'method' => 'POST']) !!} <input name="path" value="{{ $path }}" type="hidden"/> <input name="repo" value="{{ $repo }}" type="hidden"/> <div class="form-group"> <label for="content">File content:</label> <textarea class="form-control" name="content" id="content" cols="30" rows="10">{{ $content }}</textarea> </div> <div class="form-group"> <label for="commit">Commit message:</label> <input class="form-control" type="text" id="commit" name="commit" value="{{ $commitMessage }}"/> </div> <div class="form-group"> <input type="submit" class="btn btn-primary btn-control" value="Submit" /> </div> {!! Form::close() !!} 

После получения файла мы декодируем содержимое, создаем стандартное сообщение о коммите и генерируем представление редактирования. Другие переданные переменные необходимы для хранения обновлений файла.

Edit file

Конечная точка /repos/:owner/:repo/contents/:path принимает три других обязательных параметра наряду с owner , repo и path . Подробнее о репо-контенте вы можете прочитать в документации .

  • message : сообщение коммита.
  • content : содержимое файла.
  • sha : контрольная сумма файла.
 // app/Http/Controllers/GithubController.php public function update() { $repo = Input::get('repo'); $path = Input::get('path'); $content = Input::get('content'); $commit = Input::get('commit'); try { $oldFile = $this->client->api('repo')->contents()->show($this->username, $repo, $path); $result = $this->client->api('repo')->contents()->update( $this->username, $repo, $path, $content, $commit, $oldFile['sha'] ); return \Redirect::route('commits', ['path' => $path, 'repo' => $repo]); } catch (\RuntimeException $e) { $this->handleAPIException($e); } }//update 

Вы можете передать контрольную сумму файла как скрытый ввод внутри нашей формы, как мы сделали с path чтобы избежать вызова API, но я предпочитаю этот путь. Последний параметр метода обновления — это ветвь, по умолчанию master . После успешного обновления мы перенаправляем пользователя на страницу коммитов для просмотра последних коммитов.

Фиксации

Конечная точка /repos/:owner/:repo/commits возвращает список коммитов для определенного репозитория. У нас также есть возможность фильтровать коммиты по диапазону дат, автору или пути. Вы можете прочитать больше о поддерживаемых параметрах в документации .

 // app/Http/Controllers/GithubController.php public function commits() { $repo = Input::get('repo'); $path = Input::get('path'); try { $commits = $this->client->api('repo')->commits()->all($this->username, $repo, ['path' => $path]); return View::make('commits', ['commits' => $commits]); } catch (\RuntimeException $e) { $this->handleAPIException($e); } } 

Commits page

Метод handleException только handleException произошедшее исключение, но вы можете использовать код ответа и сообщение об исключении для выполнения соответствующих действий.

 // app/Http/Controllers/GithubController.php public function handleAPIException($e) { dd($e->getCode() . ' - ' . $e->getMessage()); } 

Вывод

Что мне понравилось в Github API, так это то, что он очень удобочитаемый. Вы можете расширить демонстрационную версию, добавив возможность загружать репозиторий на свой компьютер или создать фильтр для страницы коммитов, чтобы легко фильтровать коммиты пользователей и т. Д.

API Github дает вам возможность создавать удивительные инструменты, используя его данные. На самом деле, есть замечательный GithubArchive, созданный с использованием общедоступного API, не забудьте проверить его. Если у вас есть какие-либо комментарии или вопросы, оставьте их ниже.