Skip to content
ย 
ย 

Latest commit

ย 

History

79 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿš€ Post tracking system

Project consists of vanilla PHP api backend and React.js frontend

โš ๏ธ PHP API is responsible for all core logic, where key principles, design patterns, and techniques have been applied.
React is used only for the displaying and interacting with data, following a component-based principles.

Feel free to refactor either part as needed. Good luck!


๐Ÿ“š Table of Contents


๐Ÿงฉ Functionality

The core idea of this project revolves around a shipment management system with tracking used by both regular users and administrators.

  • ๐Ÿ”น Users can interact with their shipments (both sent and received), manage their profile, and create support tickets in case of issues.
  • ๐Ÿ”น Admins oversee all aspects of the system: managing users, shipments, post offices, and user support tickets.

๐Ÿ“„ Pages Overview

๐ŸŒ Generic

  • Login โ€“ Authenticate using email and password.
  • Registration โ€“ Register a new account with email and password.

๐Ÿ‘ค Regular User

  • Profile โ€“ View and update personal information.
  • Shipments โ€“ View all shipments sent by the user and create new shipments.
  • Receiving โ€“ Track shipments received from other users.
  • Tracking โ€“ Monitor the status, current location, departure and destination, and dates for all user-related shipments.
  • Support โ€“ Submit support tickets for any issues and review the status of existing tickets (open or closed).

๐Ÿ› ๏ธ Administrator

  • Profile โ€“ Same as regular user, with the ability to update personal information.
  • Tracking โ€“ Access and manage all usersโ€™ shipments, with controls to cancel or update shipment status and details.
  • Users โ€“ View all registered users and remove accounts if necessary.
  • Post Offices โ€“ Manage post office records, including creating new entries or updating existing ones.
  • Support Tickets โ€“ Oversee all support requests, including replying, closing, or reopening tickets as needed.

All the data is saved in mysql database managed by phpMyAdmin


๐Ÿ’ป How to Run

Follow the steps below to get the project running locally using Docker.


๐Ÿ“ฆ Prerequisites


๐Ÿ“‚ Clone the Repository

git clone https://github.com/merelythesame/post-tracking-system.git
cd post-tracking-system

๐Ÿš€ Start the Project with Docker

In the root of the project directory, run:

docker compose up -d --build

โš ๏ธ It may take a few minutes to download and build all the required images. Please be patient.


๐Ÿ“‹ Verify Running Containers

Check if all containers are up and running:

docker compose ps

You should see four containers with status Up:

  • php-backend
  • react-frontend
  • mysql-db
  • pma (phpMyAdmin)

๐Ÿ› ๏ธ Database Setup (Important)

Access phpMyAdmin at:
๐Ÿ‘‰ http://localhost:8080

The project is configured to auto-import the database on launch. If for some reason the tables are missing:

  1. Navigate to your database in phpMyAdmin. Database user is root and password is root
  2. Click the "Import" tab in the top menu.
  3. Select the file: ./db/project.sql
  4. Click "Import" to load the database schema and data.

You should now see all required tables.


๐ŸŒ Access the App

๐Ÿงช You can test API routes using Postman or any HTTP client. Here is documentation https://documenter.getpostman.com/view/41681143/2sB2qgdxhQ


๐ŸŽ‰ Thatโ€™s it! Your application should now be fully operational.


โš™๏ธ How does it work

When a request is made to PHP api, it goes to the index.php file which first initializes session handling and sets CORS headers to allow communication from a frontend.

Then, it includes the autoloader and instantiates controllers for users, shipments, tracking statuses, post offices, and support tickets.

Each controller is associated with various route strategies (GET, POST, PATCH, DELETE) that define the CRUD behavior.

These strategies are optionally wrapped in security decorators that enforce authorization checks (e.g., whether the user is authenticated, admin, or resource owner).

All routes are registered to a custom Router class, which matches the request URI and method to the appropriate strategy using regex patterns. Once matched, the router returns the strategy and any URI parameters.

A Dispatcher then wraps the request through middlewareโ€”specifically a BufferingMiddleware that manages output buffering and sets caching headers based on the response codeโ€”before invoking the strategy.

If no route matches, a 404 response is returned. Strategies like GetStrategy then delegate the request to for example UserController methods like getEntityById or getEntityByEmail, which in turn interact with a UserRepository class that runs raw SQL queries via PDO against a database.

The repository hydrates or persists user data using the User model, which implements JsonSerializable to standardize JSON responses.

The security layer uses decorators to check session-based roles and permissions using a Security class. The entire request-response cycle thus flows from HTTP input to controller logic, through repository/database interaction, and finally returns a JSON-encoded HTTP response.


๐Ÿ“ Programming Principles

Principle Implementation
Single Responsibility Principle (SRP) Controllers (e.g., UserController) handle request logic related to users.
Repositories (e.g., UserRepository) manage DB operations only.
Models (e.g., User) focus on structure and serialization.
Middleware (e.g., BufferingMiddleware) handles buffering and cache headers.
Security Decorators manage authorization separately.
Open/Closed Principle (OCP) The use of strategy patterns (GetStrategy, AddStrategy, etc.) allows new behaviors (e.g., new request types or logic) to be added without modifying existing logic.
Security decorators can wrap strategies without altering their internal implementation, extending behavior transparently.
Liskov Substitution Principle (LSP) Each strategy can be used interchangeably through a common interface (likely a RouterStrategyInterface), without breaking routing or dispatch logic.
All models implementing JsonSerializable can be serialized predictably, regardless of the specific model used.
Dependency Inversion Principle (DIP) Controllers depend on repositories, not raw SQL or PDO directlyโ€”they, keeping data access loosely coupled.
Routing and dispatching are handled by infrastructure-level classes, but controllers and strategies donโ€™t depend on their implementations.
Security checks are implemented via decorators, keeping business logic decoupled from authorization logic.
DRY Centralized Routing: All route handling is abstracted into a single Router class using regex mapping.
Middleware & Decorators: Cross-cutting concerns (e.g., caching, buffering, authentication) are handled in middleware and decorators, avoiding repetition in each strategy or controller.
Repository Layer: Shared SQL logic is isolated in repositories like UserRepository, so data access code isnโ€™t duplicated across controllers.
KISS Use of Strategy Pattern: Clean separation of logic for different HTTP methods (GET, POST, etc.) makes the codebase modular and understandable.
Minimal Controller Logic: Controllers delegate work to repositories and strategies, avoiding bloated methods.
Custom Router and Dispatcher: While powerful, they stay simple in purposeโ€”matching URIs and passing them onโ€”without becoming micro-frameworks.

๐Ÿ—๏ธ Design Patterns

Pattern Implementation Benefit
Strategy Pattern GetStrategy, AddStrategy, UpdateStrategy, etc., define behavior for each HTTP method. New HTTP behaviors can be added without altering existing code โ€” aligns with the Open/Closed Principle.
Decorator Pattern SecurityDecorator wraps strategy objects to enforce authentication/authorization rules (e.g., admin check, ownership check). Keeps security logic separate from core business logic and promotes reuse.
Chain of Responsibility BufferingMiddleware wraps responses to handle output buffering and cache headers. Decouples shared concerns like caching from route or controller logic.
Singleton Security and Database has only one instance and provides a global point of access Controlled Access to Instance
Repository Pattern UserRepository, ShipmentRepository, etc., interact with the database via SQL using PDO. Keeps controllers clean and business-focused; improves testability and abstraction over persistence.

๐Ÿ”ง Refactoring Techniques

Pattern Implementation
Extract Method Controllers for example UserController delegate tasks like retrieving a user by ID or email to separate methods like getEntityById() or getEntityByEmail().
Move Method Database logic is moved out of controllers and placed in UserRepository or other repositories.
Replace Conditional with Polymorphism Use of strategies like GetStrategy, AddStrategy, UpdateStrategy avoids large conditionals for request types.
Encapsulate Field All the models fields made private with added getters and setter for accessing and retrieving
Extract Interface Made repositories implement generic RepositoryInterface
Extract Superclass All controller extend AbstractController with generic logic

๐Ÿ“„ Line of code

lines

๐ŸŽฅ Demonstration


๐Ÿ” Authentication

  • Login
    Login

  • Registration
    SignUp


๐Ÿ‘ค User Dashboard

  • Profile
    Profile

  • Shipments
    UserShipments

  • Receiving
    UserReceiving

  • Tracking
    UserTracking

  • Support
    UserSupport


๐Ÿ› ๏ธ Administrator Panel

  • Tracking Management
    AdminTracking

  • User Management
    AdminUsers

  • Post Offices
    AdminPostOffices

  • Support Tickets
    AdminSupport

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages