jn-devops/property
A Laravel/PHP package for working with property data, providing structure for models, migrations, and common property-related tasks so you can integrate real-estate records into your application with less boilerplate.
Install the package via Composer and let Laravel auto-discover the service provider:
composer require jn-devops/property
Before writing any code, inspect three things in the installed package:
src/ directory — look for the models (Property, Project, Unit, likely Address), enums (property type, status, tenure), and any traits like HasProperty or InteractsWithProperty. These are the public API you'll live in daily.config/property.php — table names, polymorphic/morph-map settings, and any model-resolution bindings. This is where you'd override models later.database/migrations/ — check publishable tags and the schema before running migrations against an existing database.Publish and migrate:
php artisan vendor:publish --tag="property-config"
php artisan vendor:publish --tag="property-migrations"
php artisan migrate
First use case: create a property tied to a project and query it back with its address and units:
use JnDevops\Property\Models\Project;
$project = Project::create(['name' => 'Riverbend']);
$property = $project->properties()->create([
'name' => 'Lot 12',
'status' => 'available',
]);
$property->load('address', 'units');
If the package ships factories, seed a few records (php artisan db:seed --class=PropertySeeder) before wiring anything into your domain — it's the fastest way to see how the relationships are wired.
Model-centric usage. This package is almost certainly an Eloquent domain layer, so most day-to-day work is Property/Project/Unit model calls, not service classes. Treat the package models as aggregates you extend or compose, not as DTOs.
Composing with traits. When the package exposes traits (e.g., HasAddress, Propertyable), prefer applying them to your own models over subclassing package models. That keeps upgrades painless:
class Listing extends Model
{
use \JnDevops\Property\Concerns\HasProperty;
}
Polymorphic owners. Property packages lean heavily on morphTo/morphMany for addresses, media, and owners. If you attach your own models to a property, register a morph map in AppServiceProvider::boot() so stored type strings stay stable:
Relation::enforceMorphMap([
'listing' => \App\Models\Listing::class,
]);
Enum-driven state. Property status/type enums are the safest integration point. Cast columns to the package's enum classes and use match or enum methods for transitions rather than raw strings — that keeps query scopes and validation in sync with the package's expectations.
Query through relationships, not IDs. Prefer $project->properties()->where('status', ...) over constructing raw Property::where('project_id', ...) joins. The package's scopes (e.g., available(), active()) encode business rules you'd otherwise duplicate.
Container bindings for services. If there's a PropertyService or repository interface in the provider, resolve it via constructor injection rather than instantiating models directly — that's the seam for swapping implementations in tests.
properties table is extremely common. Before migrating, check config/property.php for a table prefix or override and confirm nothing in your app already owns that name. Silent schema conflicts here are painful.{type} columns will contain full class names and break. Register mappings before any records exist, or backfill.config/property.php require php artisan config:clear in local dev and a deploy step in production. A stale config is the most common cause of "the package is ignoring my override."->toArray() on an enum model attribute yields the enum's value only if the casting is configured as Enum::class; otherwise you get a string and your TypeScript types drift. Test one API response early.load() returns empty unexpectedly, dump ->getMorphClass() on the parent and check it matches the stored morph type. This catches 80% of "relationship not working" issues in polymorphic packages.composer.json, read the source when in doubt, and write integration tests around the relationships you depend on — future package changes won't announce themselves.How can I help you explore Laravel packages today?