Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here

Countries, Cities, Geographical Objects

Premium
8 min read

The next thing we'll work on is adding real estate properties: houses/homes to rent. In this particular lesson, we will focus on adding the geographical data for city, country, and latitude/longitude.


Goals of This Lesson

  • Build a DB schema for countries, cities, and geographical objects, seeding a few of each
  • Build a first version of DB schema for properties, with geographical data
  • Automatically set property latitude/longitude based on the address, with Observer and Google Maps API
  • First version of API endpoint to create a property, covered by PHPUnit test

By the end of this lesson, we will see this in Postman:

The Full Lesson is Only for Premium Members

Want to access all of our courses? (29 h 14 min)

You also get:

54 courses
Premium tutorials
Access to repositories
Private Discord
Get Premium for $129/year or $29/month

Already a member? Login here

Comments & Discussion

RA
Richard A. Hoyle ✓ Link copied!

Like this very much; however we in the United States use states more than country. I see you used the United States and New York City bot you left out the states of New York. Country_id, State_id, and city_id then the address and zip code is used to mail a letter hear the country is only used if mailing from out side of the United States.

AG
Alex Gower ✓ Link copied!

I agree, but I think the main point of this scenario was to copy what he saw on bookings.com In either case you would be able to adapt what he has created to your specific case.

PK
Povilas Korop ✓ Link copied!

I know, and in other countries there's a different regional structure, too. But if I went that deep with every country, and other Booking.com features with all their possible details, I wouldn't release this course until 2026.

GK
Gavin Kimpson ✓ Link copied!

Not sure what to say about the OP lol

AA
Ali Al Qahtani ✓ Link copied!

In (test_property_owner_can_add_property) (PropertiesTest)

You should add assignRole in: $owner = User::factory()->create(['role_id' => Role::ROLE_OWNER])

It will be like this: $owner = User::factory()->create(['role_id' => Role::ROLE_OWNER])->assignRole(Role::ROLE_OWNER);

I think you forget to add

PK
Povilas Korop ✓ Link copied!

Thanks for the comment. If you mean I should assign it with Spatie package, then getting back to the earlier lesson, I used Spatie only as a separate demo example in a separate branch, but I won't use that example for the other course lessons.

NS
Ngozi Stephen Onyemauche ✓ Link copied!

it is actually $owner = User::factory()->create()->assignRole(Role::ROLE_OWNER); not $owner = User::factory()->create(['role_id' => Role::ROLE_OWNER])->assignRole(Role::ROLE_OWNER); it will still throw an error

LA
Luis Alberto Oliveira ✓ Link copied!

At this section I got an error when I tried to do composer require toin0u/geocoder-laravel.

ERROR -> Your requirements could not be resolved to an installable set of packages.

I've been using PHP 8.1.16 and the project it was created with Laravel 10.8...

PK
Povilas Korop ✓ Link copied!

Not sure, the composer.json of that package shows PHP 8.0+ and Laravel 10 supported.

Are you sure you're on PHP 8.1? Have you tried to run phpinfo() function in your webpage? Because sometimes there are different PHP versions for CLI and websites.

NS
Ngozi Stephen Onyemauche ✓ Link copied!

I got thesame error while installing the toin0u/geocoder-laravel in my project PHP 8.1.13

NS
Ngozi Stephen Onyemauche ✓ Link copied!

Pls Have your solved our own error and how did you solve

PK
Povilas Korop ✓ Link copied!

Ok I can confirm that the underlying package doesn't support PHP 8 yet. It's very weird, so how could it work for me when preparing for this course just a few months ago...

Anyway, you can wait for them to update, or use some alternative like Spatie Geocoder, or skip that geocoding part of the course, for now.

H
haritjahjo ✓ Link copied!

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.

composer require toin0u/geocoder-laravel -W

ED
Emre Dikmen ✓ Link copied!

@haritjahjo I was getting the same error, it loaded when I added the -W parameter, thank you.

NS
Ngozi Stephen Onyemauche ✓ Link copied!

Hi, everyone pls i have been getting 500 error message; showing this General error: 1364 Field 'owner_id' doesn't have a default value (Connection: mysql, SQL: insert into properties (name, city_id, address_street, address_postcode, lat, long, updated_at, created_at) values (Central Hotel, 4, 16-18, Argyle Street Camden, WC1H 8EG, 51.529145, -0.1239401, 2023-05-21 23:08:59, 2023-05-21 23:08:59)) And why this is in property table $table->foreignId('owner_id')->constrained('users');

PK
Povilas Korop ✓ Link copied!

Hi, I replied to you via email. The field owner_id is auto-set in the creating() method of the Observer.

NS
Ngozi Stephen Onyemauche ✓ Link copied!

yes i thank you i have seen it

HH
Hasan Hatem ✓ Link copied!

Hello, I have 1 question. What if I allow the owner to select property location on google map api market. and get the lat, long from the api. Is google will give me the city, country names and address ?! Because I fill in some casese the user will not know what is the full address name, so mayble google will give us wrong lat & long. What u think?

Thanks

PK
Povilas Korop ✓ Link copied!

Yes it is possible with Google Maps API but it's not free. We have an article about it: Laravel: Find Addresses with Coordinates via Google Maps API

HH
Hasan Hatem ✓ Link copied!

Thanks yeah i know its paid API, but it's powerful api. The tutorial awesome.

HH
Hasan Hatem ✓ Link copied!

Sorry but I have a long question here,

If I wanna scale the website to Chalets, Cars, Appartement with Yachts, as you know i will have too much duplicated columns if i wanna create table for each one.

So your Property Model will fix this issue, but here you created Appartement model with hasOne relationship. what if I want to create Chalet and Yacht Models and the Parent Model is Property. It will be very useful because all the models is rental base.

How to make the relationship here.

PK
Povilas Korop ✓ Link copied!

It's a personal preference how to structure, as only you know how many columns will be the same or different how often you would query them, etc.

Wouldn't it be better to still use Apartment for chalets/cars/yachts, just with different Apartment Type?

HH
Hasan Hatem ✓ Link copied!

Yes it's possible, i will see thanks.

CS
Cesar Schefer ✓ Link copied!

The Postman screenshot shows the property record inserted, but also the city details. This should be added in order to see it: return Property::create($request->validated())->load("city");

V
vpinti ✓ Link copied!

I change the PropertyObserver for Spatie Geocoder:

use Spatie\Geocoder\Facades\Geocoder;

...

$result = Geocoder::getCoordinatesForAddress($fullAddress);

if (!empty($result)) {
		$property->lat = $result['lat'];
		$property->long = $result['lng'];
}
DS
Dmytro Sakharuk ✓ Link copied!

It would probably be better to ignore the 'eloquent.creating: App\Models\Property' event in the test than to add redundant conditions to the PropertyObserver. We will be frank: altering the code being tested for the needs of the test is a bad practice.

public function test_property_owner_can_add_property()
{
	\Illuminate\Support\Facades\Event::fake([
		'eloquent.creating: App\Models\Property',
	]);

	// ...
}