New Breakthrough
Detecting AI-Written code is now easier and more accurate with the latest engine update. Start checking
Start checking
Read more
Developer API
PHP SDK
Build plagiarism detection into your apps. Check code against 427B+ sources.
const response = await fetch('https://codequiry.com/api/v1/check', {
method: 'POST',
headers: { 'apikey': 'YOUR_API_KEY' },
body: formData
});
// Check created!
PHP SDK
Codequiry SDK for PHP
The official PHP SDK for Codequiry provides a clean, object-oriented interface for integrating plagiarism detection into your PHP applications. Compatible with modern PHP frameworks including Laravel, Symfony, and CodeIgniter.
Open Source: View the complete source code and contribute at
github.com/cqchecker/codequiry-php
Installation
Composer (Recommended)
The SDK is distributed from its GitHub repository rather than Packagist, so point Composer
at the repository first, then require it by its package name,
codequiry/codequiry-sdk.
composer config repositories.codequiry vcs https://github.com/cqchecker/codequiry-php
composer require codequiry/codequiry-sdk:dev-master
Or declare it directly in composer.json:
{
"repositories": [
{ "type": "vcs", "url": "https://github.com/cqchecker/codequiry-php" }
],
"require": {
"codequiry/codequiry-sdk": "dev-master"
}
}
Manual Installation
git clone https://github.com/cqchecker/codequiry-php.git
cd codequiry-php
composer install
Requirements: PHP 7.4 or higher, cURL extension, JSON extension
Quick Start
1. Basic Setup
@php
require_once 'vendor/autoload.php';
use Codequiry\Client;
use Codequiry\Exceptions\CodequiryException;
// Initialize the client
$client = new Client([
'api_key' => 'your-api-key-here',
'base_url' => 'https://codequiry.com/api/v1', // Optional
'timeout' => 30, // Request timeout in seconds
]);
// Test connection
try {
$account = $client->getAccountInfo();
echo "Connected as: " . $account['name'] . PHP_EOL;
echo "Checks remaining: " . $account['checks_remaining'] . PHP_EOL;
} catch (CodequiryException $e) {
echo "Connection failed: " . $e->getMessage() . PHP_EOL;
}
2. Complete Workflow Example
@php
class PlagiarismChecker
{
private $client;
public function __construct($apiKey)
{
$this->client = new Client(['api_key' => $apiKey]);
}
public function runCompleteCheck($assignmentName, $language, array $filePaths)
{
try {
// 1. Create a new check
$check = $this->client->createCheck([
'name' => $assignmentName,
'language' => $language
]);
echo "Created check: {$check['id']}" . PHP_EOL;
// 2. Upload files
$uploadedFiles = [];
foreach ($filePaths as $filePath) {
if (!file_exists($filePath)) {
throw new Exception("File not found: {$filePath}");
}
$result = $this->client->uploadFile($check['id'], $filePath);
$uploadedFiles[] = $result;
echo "Uploaded: {$result['filename']}" . PHP_EOL;
}
// 3. Start the analysis
$analysis = $this->client->startCheck($check['id'], [
'webcheck' => true, // Check against web sources
'dbcheck' => true // Check against database
]);
echo "Analysis started..." . PHP_EOL;
// 4. Wait for completion
$results = $this->waitForCompletion($check['id']);
// 5. Get overview results
$overview = $this->client->getOverview($check['id']);
echo "Analysis complete!" . PHP_EOL;
echo "Found {$overview['submissions_count']} submissions" . PHP_EOL;
// 6. Process results
$suspiciousSubmissions = array_filter(
$overview['submissions'],
function($sub) {
return floatval($sub['total_result']) > 50;
}
);
foreach ($suspiciousSubmissions as $submission) {
echo "⚠️ {$submission['filename']}: {$submission['total_result']}% similarity" . PHP_EOL;
// Get detailed results
$details = $this->client->getDetailedResults($check['id'], $submission['id']);
// Process other matches
foreach ($details['other_matches'] as $match) {
echo " → Match with {$match['file_matched']}: {$match['similarity']}%" . PHP_EOL;
}
}
return $overview;
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . PHP_EOL;
throw $e;
}
}
private function waitForCompletion($checkId, $maxWaitTime = 600)
{
$startTime = time();
while (time() - $startTime < $maxWaitTime) {
$status = $this->client->getCheckStatus($checkId);
if ($status['status_id'] == 4) { // Completed
return $status;
}
echo "Status: " . ($status['message'] ?? 'Processing...') . PHP_EOL;
sleep(30); // Wait 30 seconds before checking again
}
throw new Exception("Check did not complete within {$maxWaitTime} seconds");
}
}
// Usage
$checker = new PlagiarismChecker('your-api-key-here');
$results = $checker->runCompleteCheck(
'Assignment 1 - PHP Basics',
3, // PHP language ID
[
'student1_submission.php',
'student2_submission.php',
'student3_submission.php'
]
);
echo "Check completed successfully!" . PHP_EOL;
Laravel Integration
Seamlessly integrate Codequiry into your Laravel applications:
1. Environment Configuration
# .env
CODEQUIRY_API_KEY=your-api-key-here
CODEQUIRY_BASE_URL=https://codequiry.com/api/v1
2. Service Provider
@php
// app/Providers/CodequiryServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Codequiry\Client;
class CodequiryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(Client::class, function ($app) {
return new Client([
'api_key' => config('services.codequiry.api_key'),
'base_url' => config('services.codequiry.base_url'),
'timeout' => config('services.codequiry.timeout', 30),
]);
});
}
public function boot()
{
//
}
}
3. Controller Example
@php
// app/Http/Controllers/PlagiarismController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Codequiry\Client;
use App\Assignment;
use App\Jobs\ProcessPlagiarismCheck;
class PlagiarismController extends Controller
{
private $codequiry;
public function __construct(Client $codequiry)
{
$this->codequiry = $codequiry;
}
public function upload(Request $request)
{
$request->validate([
'assignment_id' => 'required|exists:assignments,id',
'files.*' => 'required|file|max:10000', // 10MB max
]);
$assignment = Assignment::findOrFail($request->assignment_id);
try {
// Create check
$check = $this->codequiry->createCheck([
'name' => $assignment->title,
'language' => $assignment->language_id
]);
// Store check ID
$assignment->update(['codequiry_check_id' => $check['id']]);
// Upload files
$uploadedFiles = [];
foreach ($request->file('files') as $file) {
$tempPath = $file->store('temp');
$fullPath = storage_path('app/' . $tempPath);
$result = $this->codequiry->uploadFile($check['id'], $fullPath, $file->getClientOriginalName());
$uploadedFiles[] = $result;
// Clean up temp file
unlink($fullPath);
}
// Start analysis in background
ProcessPlagiarismCheck::dispatch($assignment);
return response()->json([
'success' => true,
'check_id' => $check['id'],
'uploaded_files' => count($uploadedFiles),
'message' => 'Files uploaded successfully. Analysis started.'
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'error' => $e->getMessage()
], 500);
}
}
public function status(Assignment $assignment)
{
if (!$assignment->codequiry_check_id) {
return response()->json(['error' => 'No check ID found'], 404);
}
try {
$status = $this->codequiry->getCheckStatus($assignment->codequiry_check_id);
if ($status['status_id'] == 4) { // Completed
$overview = $this->codequiry->getOverview($assignment->codequiry_check_id);
return response()->json([
'status' => 'completed',
'results' => $overview
]);
}
return response()->json([
'status' => 'processing',
'message' => $status['message'] ?? 'Analysis in progress...'
]);
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
}
}
4. Background Job
@php
// app/Jobs/ProcessPlagiarismCheck.php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Assignment;
use Codequiry\Client;
class ProcessPlagiarismCheck implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $assignment;
public function __construct(Assignment $assignment)
{
$this->assignment = $assignment;
}
public function handle(Client $codequiry)
{
try {
// Start the check
$codequiry->startCheck($this->assignment->codequiry_check_id, [
'webcheck' => true,
'dbcheck' => true
]);
// Wait for completion (with timeout)
$maxWaitTime = 600; // 10 minutes
$startTime = time();
while (time() - $startTime < $maxWaitTime) {
$status = $codequiry->getCheckStatus($this->assignment->codequiry_check_id);
if ($status['status_id'] == 4) { // Completed
// Get results and store in database
$overview = $codequiry->getOverview($this->assignment->codequiry_check_id);
$this->assignment->update([
'plagiarism_results' => json_encode($overview),
'plagiarism_status' => 'completed',
'processed_at' => now()
]);
// Send notification to instructor
$this->assignment->instructor->notify(
new PlagiarismCheckCompleted($this->assignment)
);
return;
}
sleep(30); // Wait 30 seconds before checking again
}
// Timeout occurred
$this->assignment->update(['plagiarism_status' => 'timeout']);
} catch (\Exception $e) {
$this->assignment->update([
'plagiarism_status' => 'failed',
'plagiarism_error' => $e->getMessage()
]);
throw $e; // Re-throw to mark job as failed
}
}
}
Advanced Features
File Upload Methods
@php
// Upload from file path
$result = $client->uploadFile($checkId, './code.php');
// Upload from string content
$code = 'Hello World';
$result = $client->uploadString($checkId, $code, 'hello.php');
// Upload with custom filename
$result = $client->uploadFile($checkId, './temp.php', 'student1.php');
// Bulk upload
$files = ['file1.php', 'file2.php', 'file3.php'];
$results = $client->uploadMultiple($checkId, $files);
// Upload with progress callback
$result = $client->uploadFile($checkId, './large-file.php', null, function($uploaded, $total) {
$percent = round(($uploaded / $total) * 100);
echo "Upload progress: {$percent}%" . PHP_EOL;
});
Configuration & Options
@php
// Client configuration
$client = new Client([
'api_key' => 'your-api-key',
'base_url' => 'https://codequiry.com/api/v1',
'timeout' => 30,
'retries' => 3,
'debug' => false,
'user_agent' => 'MyApp/1.0'
]);
// Analysis options
$client->startCheck($checkId, [
'webcheck' => true, // Check web sources
'dbcheck' => false, // Skip database check
'test_type' => 1, // Analysis engine type
'sensitivity' => 'high' // Detection sensitivity
]);
// Custom headers
$client->setHeaders([
'X-Custom-Header' => 'value',
'X-Client-Version' => '1.0'
]);
Error Handling & Best Practices
@php
use Codequiry\Exceptions\CodequiryException;
use Codequiry\Exceptions\RateLimitException;
use Codequiry\Exceptions\UnauthorizedException;
class RobustPlagiarismChecker
{
private $client;
private $maxRetries;
public function __construct($apiKey, $maxRetries = 3)
{
$this->client = new Client(['api_key' => $apiKey]);
$this->maxRetries = $maxRetries;
}
public function checkWithRetry($assignment, $retryCount = 0)
{
try {
return $this->performCheck($assignment);
} catch (RateLimitException $e) {
if ($retryCount < $this->maxRetries) {
// Wait with exponential backoff
$waitTime = pow(2, $retryCount) * 1000000; // microseconds
usleep($waitTime);
return $this->checkWithRetry($assignment, $retryCount + 1);
}
throw new Exception("Rate limit exceeded after {$this->maxRetries} retries");
} catch (UnauthorizedException $e) {
throw new Exception("Invalid API key or access denied");
} catch (CodequiryException $e) {
if ($e->getCode() === 422) {
throw new Exception("Invalid request: " . $e->getMessage());
}
if ($retryCount < $this->maxRetries) {
sleep(2 * ($retryCount + 1)); // Linear backoff for other errors
return $this->checkWithRetry($assignment, $retryCount + 1);
}
throw new Exception("Check failed after {$this->maxRetries} attempts: " . $e->getMessage());
}
}
private function performCheck($assignment)
{
// Validate input
if (empty($assignment['files'])) {
throw new InvalidArgumentException('No files provided for analysis');
}
foreach ($assignment['files'] as $file) {
if (!file_exists($file)) {
throw new InvalidArgumentException("File not found: {$file}");
}
$fileSize = filesize($file);
if ($fileSize > 10 * 1024 * 1024) { // 10MB limit
throw new InvalidArgumentException("File too large: {$file} ({$fileSize} bytes)");
}
}
// Create check
$check = $this->client->createCheck([
'name' => $assignment['name'] ?? 'Untitled Check',
'language' => $assignment['language'] ?? 1
]);
echo "Created check: {$check['id']}" . PHP_EOL;
// Upload files with progress
$totalFiles = count($assignment['files']);
$uploaded = 0;
foreach ($assignment['files'] as $file) {
try {
$result = $this->client->uploadFile($check['id'], $file);
$uploaded++;
echo "Progress: {$uploaded}/{$totalFiles} files uploaded" . PHP_EOL;
} catch (Exception $e) {
echo "Failed to upload {$file}: " . $e->getMessage() . PHP_EOL;
// Continue with other files
}
}
if ($uploaded === 0) {
throw new Exception('No files were successfully uploaded');
}
// Start analysis
$this->client->startCheck($check['id'], [
'webcheck' => $assignment['check_web'] ?? true,
'dbcheck' => $assignment['check_database'] ?? true
]);
echo "Analysis started for {$uploaded} files..." . PHP_EOL;
// Monitor progress
return $this->waitForCompletion($check['id']);
}
private function waitForCompletion($checkId, $timeout = 600)
{
$startTime = time();
$lastStatus = '';
while (time() - $startTime < $timeout) {
$status = $this->client->getCheckStatus($checkId);
if ($status['status_id'] == 4) { // Completed
echo "Analysis completed!" . PHP_EOL;
return $this->client->getOverview($checkId);
}
$currentStatus = $status['message'] ?? 'Processing...';
if ($currentStatus !== $lastStatus) {
echo "Status: {$currentStatus}" . PHP_EOL;
$lastStatus = $currentStatus;
}
sleep(30);
}
throw new Exception("Analysis did not complete within {$timeout} seconds");
}
public function generateReport($checkId, $format = 'json')
{
$overview = $this->client->getOverview($checkId);
switch ($format) {
case 'csv':
return $this->generateCsvReport($overview);
case 'html':
return $this->generateHtmlReport($overview);
default:
return $overview;
}
}
private function generateCsvReport($overview)
{
$csv = "Filename,Total Similarity,Web Matches,Peer Matches\n";
foreach ($overview['submissions'] as $submission) {
$csv .= sprintf(
"%s,%.2f%%,%d,%d\n",
$submission['filename'],
$submission['total_result'],
$submission['web_matches'] ?? 0,
$submission['other_matches'] ?? 0
);
}
return $csv;
}
}
// Usage
try {
$checker = new RobustPlagiarismChecker(getenv('CODEQUIRY_API_KEY'));
$results = $checker->checkWithRetry([
'name' => 'Final Project - E-commerce Site',
'language' => 3, // PHP
'files' => [
'student1/index.php',
'student2/index.php',
'student3/index.php'
],
'check_web' => true,
'check_database' => true
]);
// Generate CSV report
$csvReport = $checker->generateReport($results['check_id'], 'csv');
file_put_contents('plagiarism_report.csv', $csvReport);
echo "Check completed and report saved!" . PHP_EOL;
} catch (Exception $e) {
error_log("Plagiarism check failed: " . $e->getMessage());
echo "Error: " . $e->getMessage() . PHP_EOL;
}