Skip to content

Instantly share code, notes, and snippets.

@Shahinyanm
Created April 7, 2025 17:30
Show Gist options
  • Select an option

  • Save Shahinyanm/19dd78a0143b43af8205edb748ea3a83 to your computer and use it in GitHub Desktop.

Select an option

Save Shahinyanm/19dd78a0143b43af8205edb748ea3a83 to your computer and use it in GitHub Desktop.
ARPM.php
4. Task - Collection
use Illuminate\Support\Collection;
$employees = collect([
['name' => 'John', 'city' => 'Dallas'],
['name' => 'Jane', 'city' => 'Austin'],
['name' => 'Jake', 'city' => 'Dallas'],
['name' => 'Jill', 'city' => 'Dallas'],
]);
$offices = collect([
['office' => 'Dallas HQ', 'city' => 'Dallas'],
['office' => 'Dallas South', 'city' => 'Dallas'],
['office' => 'Austin Branch', 'city' => 'Austin'],
]);
$output = $offices
->groupBy('city')
->mapWithKeys(function ($cityOffices, $city) use ($employees) {
$names = $employees
->where('city', $city)
->pluck('name')
->values();
$offices = $cityOffices->pluck('office')->mapWithKeys(function ($office) use ($names) {
return [$office => $names->all()];
});
return [$city => $offices->all()];
})
->toArray();
1 . And Task communication
namespace App\Services;
use Google_Client;
use Google_Service_Sheets;
use Google_Service_Sheets_BatchUpdateSpreadsheetRequest;
use Google_Service_Sheets_ChartSpec;
use Google_Service_Sheets_EmbeddedChart;
use Google_Service_Sheets_EmbeddedObjectPosition;
use Google_Service_Sheets_GridCoordinate;
use Google_Service_Sheets_AddChartRequest;
use Google_Service_Sheets_Spreadsheet;
use Google_Service_Sheets_ValueRange;
class CumulativeSumChartService
{
public function generateAndUpload(): string
{
$data = $this->generateData();
$sheetId = 0;
$client = new Google_Client();
$client->setAuthConfig(storage_path('app/google/credentials.json'));
$client->addScope(Google_Service_Sheets::SPREADSHEETS);
$service = new Google_Service_Sheets($client);
$spreadsheet = new Google_Service_Sheets_Spreadsheet([
'properties' => ['title' => 'Cumulative Sum Chart'],
]);
$spreadsheet = $service->spreadsheets->create($spreadsheet);
$spreadsheetId = $spreadsheet->spreadsheetId;
$values = collect($data)->map(function ($row, $index) {
return array_merge(["Individual " . ($index + 1)], $row);
})->prepend(array_merge(["Name"], range(1, 52)))
->toArray();
$body = new Google_Service_Sheets_ValueRange([
'values' => $values
]);
$service->spreadsheets_values->update(
$spreadsheetId,
'A1',
$body,
['valueInputOption' => 'RAW']
);
$this->addChart($service, $spreadsheetId, $sheetId);
return "https://docs.google.com/spreadsheets/d/{$spreadsheetId}/edit";
}
private function generateData(): array
{
return collect(range(1, 10))->map(function () {
$row = [];
$sum = 0;
for ($i = 0; $i < 52; $i++) {
$rand = mt_rand() / mt_getrandmax();
$sum += $rand;
$row[] = round($sum, 4);
}
return $row;
})->toArray();
}
private function addChart(Google_Service_Sheets $service, string $spreadsheetId, int $sheetId): void
{
$chart = new Google_Service_Sheets_EmbeddedChart([
'spec' => new Google_Service_Sheets_ChartSpec([
'title' => 'Cumulative Sum over Weeks',
'basicChart' => [
'chartType' => 'LINE',
'legendPosition' => 'RIGHT_LEGEND',
'axis' => [
['position' => 'BOTTOM_AXIS', 'title' => 'Week'],
['position' => 'LEFT_AXIS', 'title' => 'Cumulative sum'],
],
'domains' => [[
'domain' => [
'sourceRange' => [
'sources' => [[
'sheetId' => $sheetId,
'startRowIndex' => 0,
'endRowIndex' => 1,
'startColumnIndex' => 1,
'endColumnIndex' => 53,
]],
],
],
]],
'series' => collect(range(0, 9))->map(function ($i) use ($sheetId) {
return [
'series' => [
'sourceRange' => [
'sources' => [[
'sheetId' => $sheetId,
'startRowIndex' => $i + 1,
'endRowIndex' => $i + 2,
'startColumnIndex' => 1,
'endColumnIndex' => 53,
]],
],
],
];
})->toArray()
],
]),
'position' => new Google_Service_Sheets_EmbeddedObjectPosition([
'overlayPosition' => [
'anchorCell' => new Google_Service_Sheets_GridCoordinate([
'sheetId' => $sheetId,
'rowIndex' => 15,
'columnIndex' => 0,
]),
],
]),
]);
$request = new Google_Service_Sheets_BatchUpdateSpreadsheetRequest([
'requests' => [
new Google_Service_Sheets_AddChartRequest(['chart' => $chart]),
]
]);
$service->spreadsheets->batchUpdate($spreadsheetId, $request);
}
}
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Services\CumulativeSumChartService;
class GenerateCumulativeChart extends Command
{
protected $signature = 'cumulative:generate-chart';
protected $description = 'Generate and upload cumulative sum chart to Google Sheets';
public function handle()
{
$url = app(CumulativeSumChartService::class)->generateAndUpload();
}
}
5. Explanation
command('app:example-command') - > Command Name, will run as php artisan app:example-command
withoutOverlapping() => Don't run the next until current is not finished
hourly() => working each hour
onOneServer() => If project running on a few servers (for example kubernetes)command will run only in one server
runInBackground() => running async => don't blocks other commands
a) Cache - > Laravel standard Facade, using Redis or other driver to keep cached data, caching for example result of query, configs and etc...
Context=> Custom cache, keeping data in runtime through one request, using for keep for example timing variables or dependency injections
b)$query->update() => doing multiple(batch) updating, don't triggering saving, saved events, but triggering updated, updating, working fast
$model->update() => working thorough eloquent model and triggering, updating, updated, saving,saved
$model->updateQuietly() => Like $query->update() without triggring updated and updating events
Second task
use Illuminate\Support\Facades\DB;
class OrderController extends Controller
{
public function index()
{
// 1. Eager load customer, items, and item.product
$orders = Order::with(['customer', 'items.product'])
->withCount(['items as items_count']) // optimized count
->get();
// 2. Load all cart items (latest) in 1 query
$cartItems = CartItem::select('order_id', DB::raw('MAX(created_at) as last_added_to_cart'))
->groupBy('order_id')
->pluck('last_added_to_cart', 'order_id');
// 3. Load completed orders once
$completedOrders = Order::where('status', 'completed')
->get(['id', 'completed_at'])
->keyBy('id');
$orderData = $orders->map(function ($order) use ($cartItems, $completedOrders) {
$totalAmount = $order->items->reduce(function ($sum, $item) {
return $sum + $item->price * $item->quantity;
}, 0);
$completedOrder = $completedOrders->get($order->id);
return [
'order_id' => $order->id,
'customer_name' => $order->customer->name ?? 'N/A',
'total_amount' => $totalAmount,
'items_count' => $order->items_count,
'last_added_to_cart' => $cartItems[$order->id] ?? null,
'completed_order_exists' => $completedOrder !== null,
'created_at' => $order->created_at,
'completed_at' => $completedOrder->completed_at ?? null,
];
});
// 4. Sort in memory
$sorted = $orderData->sortByDesc('completed_at')->values();
return view('orders.index', ['orders' => $sorted]);
}
}
3. Third task - testing
<?php
namespace Tests\Unit\Services;
use App\Jobs\ProcessProductImage;
use App\Models\Product;
use App\Services\SpreadsheetService;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Validator;
use Tests\TestCase;
use Mockery;
class SpreadsheetServiceTest extends TestCase
{
public function test_process_spreadsheet_creates_valid_products_and_dispatches_jobs()
{
Queue::fake();
$mockImporter = Mockery::mock();
$this->app->instance('importer', $mockImporter);
$mockImporter->shouldReceive('import')
->once()
->andReturn([
['product_code' => 'ABC123', 'quantity' => 10],
['product_code' => '', 'quantity' => 5], // Invalid: missing code
['product_code' => 'XYZ789', 'quantity' => 0], // Invalid: quantity < 1
]);
$service = new SpreadsheetService();
$service->processSpreadsheet('dummy/path/to/file.xlsx');
$this->assertDatabaseHas('products', [
'code' => 'ABC123',
'quantity' => 10,
]);
$this->assertDatabaseMissing('products', [
'code' => 'XYZ789',
]);
$this->assertEquals(1, Product::count());
Queue::assertPushed(ProcessProductImage::class, 1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment