Skip to content

Commit d2ba705

Browse files
committed
chore: init commit
0 parents  commit d2ba705

File tree

10 files changed

+490
-0
lines changed

10 files changed

+490
-0
lines changed

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# The MIT License (MIT)
2+
3+
Copyright (c) 2025 Sadegh Barzegar
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Iran Provinces and Cities for Laravel
2+
3+
A Laravel package for Iran provinces and cities seeder and models.
4+
5+
_Supports Laravel 8 to 12._
6+
7+
## Installation
8+
9+
You can install the package via composer:
10+
11+
```bash
12+
composer require sadegh19b/laravel-iran-cities
13+
```
14+
15+
## Quick Start
16+
17+
1. Generate models, migrations, and seeder:
18+
```bash
19+
php artisan iran-cities:generate --all
20+
```
21+
22+
2. Run migrations:
23+
```bash
24+
php artisan migrate
25+
```
26+
27+
3. Run the seeder:
28+
```bash
29+
php artisan db:seed --class="Database\Seeders\IranProvincesAndCitiesSeeder"
30+
```
31+
32+
4. Use the models:
33+
```php
34+
use App\Models\Province;
35+
use App\Models\City;
36+
37+
// Get all provinces
38+
$provinces = Province::all();
39+
40+
// Get cities of a province
41+
$province = Province::find(1);
42+
$cities = $province->cities;
43+
```
44+
45+
## Generate Stubs
46+
47+
### Generate All
48+
49+
To generate models, migrations, and seeder:
50+
51+
```bash
52+
php artisan iran-cities:generate --all
53+
```
54+
55+
### Generate Specific
56+
57+
You can also generate specific files:
58+
59+
```bash
60+
php artisan iran-cities:generate --models
61+
php artisan iran-cities:generate --migrations
62+
php artisan iran-cities:generate --seeder
63+
```
64+
65+
## Usage
66+
67+
### Get All Provinces or Cities
68+
69+
```php
70+
use App\Models\Province;
71+
72+
$provinces = Province::all();
73+
$cities = City::all();
74+
```
75+
76+
### Get Cities of a Province
77+
78+
```php
79+
use App\Models\Province;
80+
81+
$province = Province::find(1);
82+
$cities = $province->cities;
83+
```
84+
85+
### Get Province of a City
86+
87+
```php
88+
use App\Models\City;
89+
90+
$city = City::find(1);
91+
$province = $city->province;
92+
```
93+
94+
## License
95+
96+
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

composer.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "sadegh19b/laravel-iran-cities",
3+
"description": "A Laravel package for Iran provinces and cities seeder and models",
4+
"type": "library",
5+
"license": "MIT",
6+
"authors": [
7+
{
8+
"name": "Sadegh Barzegar",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"minimum-stability": "dev",
13+
"autoload": {
14+
"psr-4": {
15+
"Sadegh19b\\LaravelIranCities\\": "src/"
16+
}
17+
},
18+
"require": {
19+
"php": "^8.0",
20+
"illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0"
21+
},
22+
"extra": {
23+
"laravel": {
24+
"providers": [
25+
"Sadegh19b\\LaravelIranCities\\LaravelIranCitiesServiceProvider"
26+
]
27+
}
28+
}
29+
}

src/Commands/GenerateCommand.php

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
<?php
2+
3+
namespace Sadegh19b\LaravelIranCities\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Illuminate\Support\Facades\File;
7+
8+
class GenerateCommand extends Command
9+
{
10+
/**
11+
* The name and signature of the console command.
12+
*
13+
* @var string
14+
*/
15+
protected $signature = 'iran-cities:generate
16+
{--models : Generate Province and City models}
17+
{--migrations : Generate migrations for provinces and cities tables}
18+
{--seeder : Generate Iran Provinces and Cities seeder}
19+
{--all : Generate all files (models, migrations, and seeders)}';
20+
21+
/**
22+
* The console command description.
23+
*
24+
* @var string
25+
*/
26+
protected $description = 'Generate Iran Provinces and Cities models, migrations, and seeders';
27+
28+
private $modelNamespace = 'App\\Models';
29+
30+
/**
31+
* Execute the console command.
32+
*/
33+
public function handle()
34+
{
35+
if ($this->option('all')) {
36+
$this->makeModels();
37+
$this->makeMigrations();
38+
$this->makeSeeder();
39+
40+
$this->info('All Province City files have been generated.');
41+
return;
42+
}
43+
44+
if ($this->option('models')) {
45+
$this->makeModels();
46+
}
47+
48+
if ($this->option('migrations')) {
49+
$this->makeMigrations();
50+
}
51+
52+
if ($this->option('seeder')) {
53+
$this->makeSeeder();
54+
}
55+
56+
if (!$this->option('models') && !$this->option('migrations') && !$this->option('seeder')) {
57+
$this->error('Please specify what to generate (--model, --migration, --seeder, or --all)');
58+
}
59+
}
60+
61+
/**
62+
* Generate models from stubs.
63+
*
64+
* @return void
65+
*/
66+
protected function makeModels(): void
67+
{
68+
$this->info('Generating Province and City models...');
69+
70+
// Generate Province model
71+
$this->generateFromStub(
72+
$this->findStub('models/Province.stub'),
73+
app_path('Models/Province.php'),
74+
['{{ namespace }}' => $this->modelNamespace]
75+
);
76+
77+
// Generate City model
78+
$this->generateFromStub(
79+
$this->findStub('models/City.stub'),
80+
app_path('Models/City.php'),
81+
['{{ namespace }}' => $this->modelNamespace]
82+
);
83+
84+
$this->info('Models generated successfully.');
85+
}
86+
87+
/**
88+
* Generate migrations from stubs.
89+
*
90+
* @return void
91+
*/
92+
protected function makeMigrations(): void
93+
{
94+
$this->info('Generating migrations...');
95+
96+
// Generate provinces migration
97+
$provincesTimestamp = date('Y_m_d_His');
98+
$this->generateFromStub(
99+
$this->findStub('migrations/create_provinces_table.stub'),
100+
database_path("migrations/{$provincesTimestamp}_create_provinces_table.php"),
101+
['{{ model_namespace }}' => $this->modelNamespace]
102+
);
103+
104+
// Generate cities migration with a timestamp 1 second later
105+
sleep(1);
106+
$citiesTimestamp = date('Y_m_d_His');
107+
$this->generateFromStub(
108+
$this->findStub('migrations/create_cities_table.stub'),
109+
database_path("migrations/{$citiesTimestamp}_create_cities_table.php"),
110+
['{{ model_namespace }}' => $this->modelNamespace]
111+
);
112+
113+
$this->info('Migrations generated successfully.');
114+
}
115+
116+
/**
117+
* Generate seeder from stub.
118+
*
119+
* @return void
120+
*/
121+
protected function makeSeeder(): void
122+
{
123+
$this->info('Generating IranProvincesAndCitiesSeeder...');
124+
125+
$this->generateFromStub(
126+
$this->findStub('seeders/IranProvincesAndCitiesSeeder.stub'),
127+
database_path('seeders/IranProvincesAndCitiesSeeder.php'),
128+
[
129+
'{{ model_namespace }}' => $this->modelNamespace
130+
]
131+
);
132+
133+
$this->info('Seeder generated successfully.');
134+
}
135+
136+
/**
137+
* Find the stub file path.
138+
*
139+
* @param string $stubName
140+
* @return string
141+
*/
142+
protected function findStub(string $stubName): string
143+
{
144+
$customPath = base_path("stubs/vendor/sadegh19b/laravel-iran-cities/src/stubs/{$stubName}");
145+
146+
if (File::exists($customPath)) {
147+
return $customPath;
148+
}
149+
150+
return __DIR__ . "/../stubs/{$stubName}";
151+
}
152+
153+
/**
154+
* Generate a file from a stub.
155+
*
156+
* @param string $stubPath
157+
* @param string $targetPath
158+
* @param array $replacements
159+
* @return void
160+
*/
161+
protected function generateFromStub(string $stubPath, string $targetPath, array $replacements): void
162+
{
163+
$content = File::get($stubPath);
164+
165+
foreach ($replacements as $search => $replace) {
166+
$content = str_replace($search, $replace, $content);
167+
}
168+
169+
File::put($targetPath, $content);
170+
171+
$this->line("Created: " . $targetPath);
172+
}
173+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Sadegh19b\LaravelIranCities;
4+
5+
use Illuminate\Support\ServiceProvider;
6+
use Sadegh19b\LaravelIranCities\Commands\GenerateCommand;
7+
8+
class LaravelIranCitiesServiceProvider extends ServiceProvider
9+
{
10+
/**
11+
* Register services.
12+
*/
13+
public function register(): void
14+
{
15+
//
16+
}
17+
18+
/**
19+
* Bootstrap services.
20+
*/
21+
public function boot(): void
22+
{
23+
// Register commands
24+
if ($this->app->runningInConsole()) {
25+
$this->commands([
26+
GenerateCommand::class,
27+
]);
28+
}
29+
}
30+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration {
8+
public function up(): void
9+
{
10+
Schema::create('cities', function (Blueprint $table): void {
11+
$table->id();
12+
$table->string('name');
13+
$table->foreignId('province_id')->constrained()->cascadeOnDelete();
14+
$table->timestamps();
15+
});
16+
}
17+
18+
public function down(): void
19+
{
20+
Schema::dropIfExists('cities');
21+
}
22+
};

0 commit comments

Comments
 (0)