...
This commit is contained in:
parent
1e22d28754
commit
6b926d3afe
126 changed files with 128562 additions and 104297 deletions
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
|
||||
Source:
|
||||
|
||||
[Setup CodeIgniter — Devilbox 1.0 documentation](https://devilbox.readthedocs.io/en/latest/examples/setup-codeigniter.html?highlight=CodeIgniter)
|
||||
|
||||
|
||||
Prerequisites: Have correct docker compose installed:
|
||||
```bash
|
||||
sudo apt install docker-compose-v2
|
||||
```
|
||||
|
||||
Download Devilbox
|
||||
|
||||
Remove unwanted hosts from docker-compose.yml file
|
||||
|
||||
copy env file to .env
|
||||
|
||||
Set TLD_SUFFIX=local
|
||||
|
||||
|
||||
In /etc/hosts, add 127.0.01 with application URL:
|
||||
|
||||
127.0.0.1 verleihapp.local
|
||||
|
||||
|
||||
Start docker container: sudo docker compose up -d
|
||||
|
||||
Enter Container: ./shell.sh
|
||||
|
||||
|
||||
Install CodeIgniter4 and create htdocs link:
|
||||
```bash
|
||||
mkdir myproject
|
||||
cd myproject
|
||||
composer create-project codeigniter4/appstarter myprojectapp
|
||||
ln -s myprojectapp/public htdocs
|
||||
```
|
||||
|
||||
.env settings
|
||||
```php
|
||||
|
||||
CI_ENVIRONMENT = development (instead of production)
|
||||
|
||||
app.baseURL = 'http://myproject.local'
|
||||
|
||||
database.default.hostname = myproject.local
|
||||
database.default.database = myproject
|
||||
database.default.username = root
|
||||
database.default.password =
|
||||
database.default.DBDriver = MySQLi
|
||||
database.default.DBPrefix =
|
||||
database.default.port = 3306
|
||||
```
|
||||
|
||||
|
||||
Access mysql from inside container
|
||||
```bash
|
||||
./shell.sh
|
||||
|
||||
mysql -h 127.0.0.1 -u root
|
||||
|
||||
CREATE DATABASE godotweb;
|
||||
```
|
||||
|
||||
|
||||
|
||||
https://shield.codeigniter.com/getting_started/install/
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
docker-compose up -d
|
||||
./shell.sh
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
```bash
|
||||
$ grep -R CI_VERSION|grep const
|
||||
framework/system/CodeIgniter.php: public const CI_VERSION = '4.5.5';
|
||||
|
||||
```
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
Inside Devilbox container:
|
||||
```bash
|
||||
devilbox@php-8.1.14 in /shared/httpd $ pwd
|
||||
/shared/httpd
|
||||
|
||||
|
||||
mkdir myproject
|
||||
cd myproject
|
||||
composer create-project codeigniter4/appstarter myprojectapp
|
||||
ln -s myprojectapp/public htdocs
|
||||
```
|
||||
|
||||
|
||||
Setup db settings in .env:
|
||||
```txt
|
||||
CI_ENVIRONMENT = development
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# APP
|
||||
#--------------------------------------------------------------------
|
||||
app.baseURL = 'http://godotweb.local'
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# DATABASE
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
database.default.hostname = godotweb.local
|
||||
database.default.database = godotweb
|
||||
database.default.username = root
|
||||
database.default.password =
|
||||
database.default.DBDriver = MySQLi
|
||||
database.default.DBPrefix =
|
||||
database.default.port = 3306
|
||||
```
|
||||
|
||||
Add shield:
|
||||
```bash
|
||||
composer require codeigniter4/shield
|
||||
```
|
||||
|
||||
In case of issues, see installation.
|
||||
```bash
|
||||
composer config minimum-stability dev
|
||||
composer config prefer-stable true
|
||||
```
|
||||
|
||||
```bash
|
||||
php spark shield:setup
|
||||
```
|
||||
|
||||
####
|
||||
|
||||
SET DEFAULT LOCALE
|
||||
|
||||
|
||||
Config/App.php
|
||||
```php
|
||||
|
||||
public bool $negotiateLocale = true;
|
||||
public string $defaultLocale = 'en';
|
||||
public array $supportedLocales = ['en', 'de'];
|
||||
```
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
```bash
|
||||
php spark make:controller Api/Auth --suffix --restful
|
||||
```
|
||||
|
||||
|
||||
Routes.php
|
||||
```php
|
||||
//Get
|
||||
$routes->get("logout", "AuthController::logout", ["filter" => "apiauth"]);
|
||||
```
|
||||
|
||||
|
||||
Api/AuthController.php
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Controllers\Api;
|
||||
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\RESTful\ResourceController;
|
||||
use CodeIgniter\Shield\Models\UserModel;
|
||||
use CodeIgniter\Shield\Entities\User;
|
||||
|
||||
class AuthController extends ResourceController
|
||||
{
|
||||
//Post
|
||||
public function register()
|
||||
{
|
||||
$rules = [
|
||||
"username" => "required|is_unique[users.username]",
|
||||
"email" => "required|valid_email|is_unique[auth_identities.secret]", // gets written to secret field in user table
|
||||
"password" => "required" // gets written to secret 2 field in user table
|
||||
];
|
||||
|
||||
if (!$this->validate($rules))
|
||||
{
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => $this->validator->getErrors(),
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
|
||||
$um = new UserModel(); // coming from Shield
|
||||
$userEntity = new User([
|
||||
"username" => $this->request->getVar("username"),
|
||||
"email" => $this->request->getVar("email"),
|
||||
"password" => $this->request->getVar("password")
|
||||
]);
|
||||
|
||||
$um->save($userEntity);
|
||||
|
||||
return $this->respondCreated( [
|
||||
"status" => true,
|
||||
"message" => "User saved successfully",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// Post
|
||||
public function login()
|
||||
{
|
||||
if(auth()->loggedIn()) {
|
||||
auth()->logout();
|
||||
}
|
||||
|
||||
$rules = [
|
||||
"email" => "required|valid_email",
|
||||
"password" => "required"
|
||||
];
|
||||
|
||||
if (!$this->validate($rules)) {
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => $this->validator->getErrors(),
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
|
||||
// success
|
||||
$credentials = [
|
||||
"email" => $this->request->getVar("email"),
|
||||
"password" => $this->request->getVar("password")
|
||||
];
|
||||
|
||||
$loginAttempt = auth()->attempt($credentials);
|
||||
|
||||
if (!$loginAttempt->isOK()) {
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => "Invalid login details",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
|
||||
// We have a valid data set
|
||||
|
||||
$um = new UserModel();
|
||||
$userData = $um->findById(auth()->id());
|
||||
$token = $userData->generateAccessToken("thisismysecretkey");
|
||||
$auth_token = $token->raw_token; // Only available after generation
|
||||
|
||||
return $this->respondCreated( [
|
||||
"status" => true,
|
||||
"message" => "User logged in successfully",
|
||||
"data" => [
|
||||
"token" => $auth_token
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
|
||||
public function logout()
|
||||
{
|
||||
auth()->logout();
|
||||
auth()->user()->revokeAllAccessTokens();
|
||||
return $this->respondCreated([
|
||||
"status" => true,
|
||||
"message" => "User logged out successfully",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
|
||||
//Get
|
||||
public function profile()
|
||||
{
|
||||
$userId = auth()->id();
|
||||
return $this->respondCreated([
|
||||
"status" => true,
|
||||
"message" => "Profile api called",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
|
||||
public function accessDenied()
|
||||
{
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => "Invalid access",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
https://www.youtube.com/watch?v=_ZRHt-fWJpc&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=29
|
||||
|
||||
app/Config/Routes.php
|
||||
|
||||
Remember: Shield added =>
|
||||
```php
|
||||
service('auth')->routes($routes)
|
||||
```
|
||||
|
||||
```php
|
||||
// API routes (put below service('auth'))
|
||||
$routes->group("api", ["namespace" => "App\Controller\Api"], function($routes) {
|
||||
$routes->post("register", "AuthController::register");
|
||||
$routes->post("login", "AuthController::login");
|
||||
$routes->get("profile", "AuthController::profile");
|
||||
$routes->get("logout", "AuthController::logout", ["filter"=>"apiauth"]);
|
||||
|
||||
//$routes->post("add-project", "ProjectController::addProject");
|
||||
//$routes->get("list-projects", "ProjectController::listProjects");
|
||||
//$routes->delete("delete-project/(:num)", "ProjectController::deleteProject/$1");
|
||||
});
|
||||
```
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
https://www.youtube.com/watch?v=USqOc-GCA4s&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=32
|
||||
|
||||
Create AuthFilter.php
|
||||
```bash
|
||||
php spark make:filter Auth --suffix
|
||||
```
|
||||
|
||||
Define before method in AuthFilter.php
|
||||
```php
|
||||
public function before(RequestInterface $request, $arguments = null)
|
||||
{
|
||||
helper("auth");
|
||||
|
||||
if (!auth("tokens")->loggedIn()) {
|
||||
return redirect()->to(base_url("api/ invalid-access")); // need to create invalid-access route
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Routes.php
|
||||
```php
|
||||
// API ROUTES
|
||||
$routes->group("api",["namespace]=> "App\Controllers\Api"], function($routes) {
|
||||
...
|
||||
$routes->get("invalid-access", "AuthController::accessDenied");
|
||||
§routes->get('demo-method", "AuthController::demoMethod",["filter" => "apiauth"]); // Filter Name is defined in aliases array in Filters.php below.
|
||||
...
|
||||
```
|
||||
|
||||
Add filter to app/Config/Filters.php
|
||||
```php
|
||||
use App\Filters\AuthFilter;
|
||||
|
||||
|
||||
public array $aliases = [
|
||||
'csrf' => CSRF::class,
|
||||
'toolbar' => DebugToolbar::class,
|
||||
'honeypot' => Honeypot::class,
|
||||
'invalidchars' => InvalidChars::class,
|
||||
'secureheaders' => SecureHeaders::class,
|
||||
'apiauth' => AuthFilter::class
|
||||
]
|
||||
```
|
||||
|
||||
Authorize request by adding field "Authorization" with value "Bearer xxxxxx" in Request Header:
|
||||
![[Pasted image 20241127140801.png]]
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
![[Pasted image 20241214094809.png]]
|
||||
|
||||
![[Pasted image 20241214094906.png]]
|
||||
600933326ac42a7f1669bfcaceb4bf1f973c8f64f54dccff9d6c424a9c2c0e5d
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
```bash
|
||||
php spark make:model Board --suffix
|
||||
php spark make:controller Api/Board --suffix --restful
|
||||
```
|
||||
|
||||
|
||||
Add allowed fields to model:
|
||||
(BoardModel.php)
|
||||
```php
|
||||
$allowedFields = ["name"];
|
||||
```
|
||||
|
||||
|
||||
|
||||
```php
|
||||
php spark make:migration create_boards
|
||||
```
|
||||
|
||||
Migration file:
|
||||
|
||||
```php
|
||||
//up:
|
||||
$this->forge->addField([
|
||||
"id" => [ "type"=>"INT", "constraint"=>5, "auto increment" => true, "unsigned" => true ],
|
||||
"name" => [ "type"=>"VARCHAR", "constraint" => 120, "null" => false ]
|
||||
]);
|
||||
$this->forge->addPrimaryKey("id);
|
||||
$this->forge->createTable("boards");
|
||||
|
||||
//down:
|
||||
$this->forge->dropTable("boards");
|
||||
```
|
||||
|
||||
|
||||
```bash
|
||||
php spark migrate:status
|
||||
|
||||
php spark migrate
|
||||
```
|
||||
|
||||
Create seeder ?
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
Inside Devilbox container:
|
||||
```bash
|
||||
devilbox@php-8.1.14 in /shared/httpd $ pwd
|
||||
/shared/httpd
|
||||
|
||||
|
||||
mkdir myproject
|
||||
cd myproject
|
||||
composer create-project codeigniter4/appstarter myprojectapp
|
||||
ln -s myprojectapp/public htdocs
|
||||
```
|
||||
|
||||
|
||||
Add shield:
|
||||
```bash
|
||||
composer require codeigniter4/shield
|
||||
```
|
||||
|
||||
In case of issues, see installation.
|
||||
```bash
|
||||
composer config minimum-stability dev
|
||||
composer config prefer-stable true
|
||||
```
|
||||
|
||||
```bash
|
||||
php spark shield:setup
|
||||
```
|
||||
|
||||
####
|
||||
|
||||
SET DEFAULT LOCALE
|
||||
|
||||
|
||||
Config/App.php
|
||||
```php
|
||||
|
||||
public bool $negotiateLocale = true;
|
||||
public string $defaultLocale = 'en';
|
||||
public array $supportedLocales = ['en', 'de'];
|
||||
```
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
```bash
|
||||
php spark make:scaffold Product
|
||||
```
|
||||
Creates Controller, Model, Migration, Seeder
|
||||
|
||||
```php
|
||||
//up:
|
||||
$this->forge->addField((["id"=>
|
||||
["type"=>"INT",
|
||||
"constraint"=>5,
|
||||
"auto increment" => true,
|
||||
"unsigned" => true
|
||||
],
|
||||
"name" => ["type"=>"VARCHAR".
|
||||
"constraint" => 120,
|
||||
"null" => false
|
||||
]
|
||||
]
|
||||
));
|
||||
$this->forge->addPrimaryKey("id);
|
||||
$this->forge->createTable("students");
|
||||
|
||||
//down:
|
||||
$this->forge->dropTable("students");
|
||||
```
|
||||
|
||||
|
||||
```bash
|
||||
php spark migrate:status
|
||||
|
||||
php spark migrate
|
||||
```
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
https://www.youtube.com/watch?v=QaNGT-hj0so&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=8
|
||||
|
||||
![[Pasted image 20241112083749.png]]
|
||||
![[Pasted image 20241112084116.png]]
|
||||
|
||||
Add route to Controller+method in Config/Routes.php:
|
||||
|
||||
![[Pasted image 20241112084252.png]]
|
||||
|
||||
Example for using where clause ( second parameter in update method ):
|
||||
![[Pasted image 20241112084920.png]]
|
||||
|
||||
Delete:
|
||||
|
||||
![[Pasted image 20241112085347.png]]
|
||||
Select all:
|
||||
![[Pasted image 20241112090019.png]]
|
||||
|
||||
|
||||
![[Pasted image 20241112090048.png]]
|
||||
|
||||
Select with where clause
|
||||
|
||||
![[Pasted image 20241112090400.png]]
|
||||
|
||||
For single row result, we directly load into Array ( instead of Array of Array)
|
||||
![[Pasted image 20241112090526.png]]
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
https://www.youtube.com/watch?v=4_MdtVqfH1o&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=9
|
||||
|
||||
```bash
|
||||
php spark make:model Student --suffix
|
||||
```
|
||||
Creates StudentModel.php in app/Models
|
||||
|
||||
|
||||
Add allowedFields
|
||||
![[Pasted image 20241113082554.png]]
|
||||
|
||||
Add Model to Controller
|
||||
![[Pasted image 20241113082703.png]]
|
||||
![[Pasted image 20241113083139.png]]
|
||||
|
||||
|
||||
add to routes
|
||||
```php
|
||||
$routes->get("add-student", "StudentController::insertStudent");
|
||||
```
|
||||
|
||||
|
||||
update example (condition, data):
|
||||
|
||||
![[Pasted image 20241113083603.png]]
|
||||
|
||||
delete:
|
||||
|
||||
![[Pasted image 20241113083823.png]]
|
||||
get all :
|
||||
![[Pasted image 20241113084056.png]]
|
||||
|
||||
get single with generic condition:
|
||||
|
||||
![[Pasted image 20241113084645.png]]
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
For creating dummy data
|
||||
|
||||
Seeder files go into app/Database/Seeds
|
||||
|
||||
```bash
|
||||
php spark make:seeder Student --suffix
|
||||
```
|
||||
|
||||
fill run method
|
||||
|
||||
![[Pasted image 20241113085432.png]]
|
||||
|
||||
Run seeder file
|
||||
|
||||
```bash
|
||||
php spark db:seed StudentSeeder
|
||||
```
|
||||
|
||||
Mass dummy data using Factory / Faker
|
||||
|
||||
![[Pasted image 20241113085948.png]]
|
||||
|
||||
![[Pasted image 20241113090300.png]]
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
https://www.youtube.com/watch?v=WGtj1Ihlf10&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=11
|
||||
get, post, put/patch, delete
|
||||
|
||||
![[Pasted image 20241114084652.png]]
|
||||
![[Pasted image 20241114084843.png]]
|
||||
|
||||
|
||||
|
||||
![[Pasted image 20241114084916.png]]
|
||||
|
||||
|
||||
|
||||
![[Pasted image 20241114084945.png]]
|
||||
|
||||
|
||||
|
||||
|
||||
Routes.php
|
||||
|
||||
![[Pasted image 20241114085118.png]]
|
||||
|
||||
Test using postman
|
||||
![[Pasted image 20241114085726.png]]
|
||||
|
||||
![[Pasted image 20241114085814.png]]
|
||||
![[Pasted image 20241114085826.png]]
|
||||
Remove debugging noise in payload by switching to production environment in .env
|
||||
|
||||
Method spoofing ( changing POST into DELETE request )
|
||||
![[Pasted image 20241114090303.png]]
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
https://www.youtube.com/watch?v=4neOZhzn-qI&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=12
|
||||
![[Pasted image 20241115082725.png]]
|
||||
|
||||
|
||||
app/Config/Routes.php
|
||||
![[Pasted image 20241115082852.png]]
|
||||
|
||||
http://godotweb.local/product/add
|
||||
http://godotweb.local/product/list
|
||||
http://godotweb.local/category/add
|
||||
http://godotweb.local/category/list
|
||||
|
||||
|
||||
**ROUTE NAMESPACE**
|
||||
Create subfolder in Controllers directory
|
||||
```bash
|
||||
php spark make:controller Admin/Admin --suffix
|
||||
```
|
||||
|
||||
![[Pasted image 20241115084552.png]]
|
||||
|
||||
```bash
|
||||
php spark make:controller Seller/Seller --suffix
|
||||
```
|
||||
|
||||
![[Pasted image 20241115084636.png]]
|
||||
|
||||
Access Controller in subfolder using namespace parameter in routes group method:
|
||||
![[Pasted image 20241115085338.png]]
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
https://www.youtube.com/watch?v=rlIKHZ5Nq2U&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=14
|
||||
|
||||
app/Filters
|
||||
app/Config/Filters.php
|
||||
|
||||
![[Pasted image 20241116111944.png]]
|
||||
|
||||
```bash
|
||||
php spark make:filter Auth --suffix
|
||||
```
|
||||
![[Pasted image 20241116113439.png]]
|
||||
![[Pasted image 20241116113532.png]]
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
```bash
|
||||
php spark make:controller Api/Api --suffix --restful
|
||||
```
|
||||
|
||||
#17/38
|
||||
|
||||
== > Created controller ApiController (in Controlles subfolder Api) will have 9 methods.
|
||||
( WHich the tutorial doesnt use, basically only difference to standard Controllers is usage of ResourceController)
|
||||
|
||||
![[Pasted image 20241117112106.png]]
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
Routes.php
|
||||
![[Pasted image 20241117113037.png]]
|
||||
|
||||
Route parameter
|
||||
![[Pasted image 20241117113342.png]]
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
![[Pasted image 20241117113802.png]]
|
||||
|
||||
```php
|
||||
$studentObject = new StudentModel();
|
||||
|
||||
$imageFile = $this->request->getFile("profile_image");
|
||||
|
||||
// only go through image storing logic if image actually exists in payload
|
||||
if (isset($imageFile) && !empty($imageFile)) { // with image
|
||||
|
||||
$imageName = $imageFile->getName();
|
||||
$tempArray = explode(".", $imageName);
|
||||
$newImageName = round(microtime(true)) . "" . end($tempArray);
|
||||
|
||||
if($imageFile->move("images/" . $newImageName)) { // move automatically creates images folder if not exists
|
||||
$data = [
|
||||
"name" => $this->request->getVar("name"),
|
||||
"email" => $this->request->getVar("email"),
|
||||
"profile_image" => "images/" . $newImageName
|
||||
];
|
||||
}
|
||||
else {
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => "Image Upload failed",
|
||||
"data" => []
|
||||
];
|
||||
}
|
||||
}
|
||||
else { // without image
|
||||
$data = [
|
||||
"name" => $this->request->getVar("name"),
|
||||
"email" => $this->request->getVar("email"),
|
||||
];
|
||||
}
|
||||
|
||||
// store student
|
||||
if ($studentObject->insert($data)) {
|
||||
$response = [
|
||||
"status" => true,
|
||||
"message" => "Student saved successfully",
|
||||
"data" => []
|
||||
];
|
||||
} else {
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => "Failed to save student",
|
||||
"data" => []
|
||||
];
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
|
||||
![[Pasted image 20241118085649.png]]
|
||||
|
||||
**![[Pasted image 20241118090014.png]]
|
||||
|
||||
![[Pasted image 20241118090047.png]]
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
https://www.youtube.com/watch?v=0aBmb1aaj_Q&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=22
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
https://www.youtube.com/watch?v=hX612xp_Gtw&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=23
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
```bash
|
||||
php spark make:controller Api/Auth --suffix --restful
|
||||
php spark make:controller Api/Project --suffix --restful
|
||||
```
|
||||
|
||||
![[Pasted image 20241123100630.png]]
|
||||
![[Pasted image 20241123100706.png]]
|
||||
![[Pasted image 20241123100734.png]]
|
||||
![[Pasted image 20241123100756.png]]
|
||||
|
||||
|
||||
--- PROJECT CONTROLLER
|
||||
![[Pasted image 20241123100834.png]]
|
||||
![[Pasted image 20241123100851.png]]
|
||||
![[Pasted image 20241123100913.png]]
|
||||
ADD SHIELD USERMODEL
|
||||
|
||||
![[Pasted image 20241123101019.png]]
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
php spark make:model Project --suffix
|
||||
```
|
||||
|
||||
|
||||
extend allowedFields, e.g.
|
||||
```php
|
||||
$allowedFields = ["user_id","name"]
|
||||
```
|
||||
|
||||
Add Project Model to ProjectController
|
||||
```php
|
||||
use App\Models\ProjectModel;
|
||||
```
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
https://www.youtube.com/watch?v=_ZRHt-fWJpc&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=29
|
||||
|
||||
app/Config/Routes.php
|
||||
|
||||
Remember: Shield added =>
|
||||
```php
|
||||
service('auth')->routes($routes)
|
||||
```
|
||||
|
||||
```php
|
||||
// API routes (put below service('auth'))
|
||||
$routes->group("api", ["namespace" => "App\Controller\Api"], function($routes) {
|
||||
$routes->post("register", "AuthController::register");
|
||||
$routes->post("login", "AuthController::login");
|
||||
$routes->get("profile", "AuthController::profile");
|
||||
$routes->get("logout", "AuthController::logout");
|
||||
|
||||
$routes->post("add-project", "ProjectController::addProject");
|
||||
$routes->get("list-projects", "ProjectController::listProjects");
|
||||
$routes->delete("delete-project/(:num)", "ProjectController::deleteProject/$1");
|
||||
});
|
||||
```
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
|
||||
AuthController:
|
||||
|
||||
```php
|
||||
|
||||
use CodeIgniter\Restful\ResourceController;
|
||||
use CodeIgniter\Shield\Models\UserModel;
|
||||
use CodeIgniter\Shield\Entities\User;
|
||||
|
||||
class AuthController extends ResourceController
|
||||
{
|
||||
//Post
|
||||
public function register()
|
||||
{
|
||||
$rules = [
|
||||
"username" => "required|is_unique[users.username]",
|
||||
"email" => "required|valid_email|is_unique[auth_identities.secret]", // gets written to secret field in user table
|
||||
"password" => "required" // gets written to secret 2 field in user table
|
||||
];
|
||||
|
||||
if (!$this->validate($rules)) {
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => $this->validator->getErrors(),
|
||||
"data" => []
|
||||
];
|
||||
} else {
|
||||
$userObject = new UserModel(); // coming from Shield
|
||||
$userEntityObject = new User([
|
||||
"username" => $this->request->getVar("username"),
|
||||
"email" => $this->request->getVar("email"),
|
||||
"password" => $this->request->getVar("password")
|
||||
]);
|
||||
$userObject->save($userEntityObject);
|
||||
$response = [
|
||||
"status" => true,
|
||||
"message" => "User saved successfully",
|
||||
"data" => []
|
||||
]
|
||||
}
|
||||
return $this->respondCreated($response);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note: shield stores users in auth_identies. Email address should be stored in field secret.
|
||||
|
||||
https://onlinewebtutorblog.com/codeigniter-4-restful-api-using-shield-authentication/
|
||||
|
||||
|
||||
|
||||
My version:
|
||||
```php
|
||||
use CodeIgniter\Restful\ResourceController;
|
||||
use CodeIgniter\Shield\Models\UserModel;
|
||||
use CodeIgniter\Shield\Entities\User;
|
||||
|
||||
class AuthController extends ResourceController
|
||||
{
|
||||
//Post
|
||||
public function register()
|
||||
{
|
||||
$rules = [
|
||||
"username" => "required|is_unique[users.username]",
|
||||
"email" => "required|valid_email|is_unique[auth_identities.secret]", // gets written to secret field in user table
|
||||
"password" => "required" // gets written to secret 2 field in user table
|
||||
];
|
||||
|
||||
if (!$this->validate($rules)) {
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => $this->validator->getErrors(),
|
||||
"data" => []
|
||||
]
|
||||
);
|
||||
|
||||
$um = new UserModel(); // coming from Shield
|
||||
$userEntity = new User([
|
||||
"username" => $this->request->getVar("username"),
|
||||
"email" => $this->request->getVar("email"),
|
||||
"password" => $this->request->getVar("password")
|
||||
]);
|
||||
$um->save($userEntity);
|
||||
|
||||
return $this->respondCreated( [
|
||||
"status" => true,
|
||||
"message" => "User saved successfully",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
https://www.youtube.com/watch?v=XJHFtfQQmRs&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=31
|
||||
|
||||
https://onlinewebtutorblog.com/codeigniter-4-restful-api-using-shield-authentication/
|
||||
|
||||
In AuthController::login:
|
||||
|
||||
|
||||
|
||||
|
||||
```php
|
||||
// Post
|
||||
public function login()
|
||||
{
|
||||
|
||||
if(auth()->loggedIn()){
|
||||
auth()->logout();
|
||||
}
|
||||
|
||||
$rules = [
|
||||
"email" => "required|valid_email",
|
||||
"password" => "required"
|
||||
];
|
||||
|
||||
if (!$this->validate($rules)) {
|
||||
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => $this->validator->getErrors(),
|
||||
"data" => []
|
||||
];
|
||||
} else {
|
||||
|
||||
// success
|
||||
$credentials = [
|
||||
"email" => $this->request->getVar("email"),
|
||||
"password" => $this->request->getVar("password")
|
||||
];
|
||||
|
||||
$loginAttempt = auth()->attempt($credentials);
|
||||
|
||||
if (!$loginAttempt->isOK()) {
|
||||
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => "Invalid login details",
|
||||
"data" => []
|
||||
];
|
||||
} else {
|
||||
|
||||
// We have a valid data set
|
||||
$userObject = new UserModel();
|
||||
|
||||
$userData = $userObject->findById(auth()->id());
|
||||
|
||||
$token = $userData->generateAccessToken("thisismysecretkey");
|
||||
|
||||
$auth_token = $token->raw_token; // Only available after generation
|
||||
|
||||
$response = [
|
||||
"status" => true,
|
||||
"message" => "User logged in successfully",
|
||||
"data" => [
|
||||
"token" => $auth_token
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
return $this->respondCreated($response);
|
||||
}
|
||||
```
|
||||
https://shield.codeigniter.com/references/authentication/tokens/
|
||||
|
||||
|
||||
|
||||
My version:
|
||||
```php
|
||||
// Post
|
||||
public function login()
|
||||
{
|
||||
if(auth()->loggedIn()){
|
||||
auth()->logout();
|
||||
}
|
||||
|
||||
$rules = [
|
||||
"email" => "required|valid_email",
|
||||
"password" => "required"
|
||||
];
|
||||
|
||||
if (!$this->validate($rules)) {
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => $this->validator->getErrors(),
|
||||
"data" => []
|
||||
]);
|
||||
|
||||
// success
|
||||
$credentials = [
|
||||
"email" => $this->request->getVar("email"),
|
||||
"password" => $this->request->getVar("password")
|
||||
];
|
||||
|
||||
$loginAttempt = auth()->attempt($credentials);
|
||||
if (!$loginAttempt->isOK()) {
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => "Invalid login details",
|
||||
"data" => []
|
||||
]);
|
||||
|
||||
// We have a valid data set
|
||||
$um = new UserModel();
|
||||
$userData = $um->findById(auth()->id());
|
||||
$token = $userData->generateAccessToken("thisismysecretkey");
|
||||
$auth_token = $token->raw_token; // Only available after generation
|
||||
|
||||
return $this->respondCreated( [
|
||||
"status" => true,
|
||||
"message" => "User logged in successfully",
|
||||
"data" => [
|
||||
"token" => $auth_token
|
||||
] );
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
https://www.youtube.com/watch?v=USqOc-GCA4s&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=32
|
||||
|
||||
Create AuthFilter.php
|
||||
```bash
|
||||
php spark make:filter Auth --suffix
|
||||
```
|
||||
|
||||
Define before method in AuthFilter.php
|
||||
```php
|
||||
public function before(RequestInterface $request, $arguments = null)
|
||||
{
|
||||
helper("auth");
|
||||
|
||||
if (!auth("tokens")->loggedIn()) {
|
||||
return redirect()->to(base_url("api/ invalid-access")); // need to create invalid-access route
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Routes.php
|
||||
```php
|
||||
// API ROUTES
|
||||
$routes->group("api",["namespace]=> "App\Controllers\Api"], function($routes) {
|
||||
...
|
||||
$routes->get("invalid-access", "AuthController::accessDenied");
|
||||
§routes->get('demo-method", "AuthController::demoMethod",["filter" => "apiauth"]); // Filter Name is defined in aliases array in Filters.php below.
|
||||
...
|
||||
```
|
||||
|
||||
Define accessDenied method in app/Controllers/Api/AuthController.php
|
||||
```php
|
||||
...
|
||||
public function accessDenied()
|
||||
{
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => "Invalid access",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
Add filter to app/Config/Filters.php
|
||||
```php
|
||||
use App\Filters\AuthFilter;
|
||||
|
||||
|
||||
public array $aliases = [
|
||||
'csrf' => CSRF::class,
|
||||
'toolbar' => DebugToolbar::class,
|
||||
'honeypot' => Honeypot::class,
|
||||
'invalidchars' => InvalidChars::class,
|
||||
'secureheaders' => SecureHeaders::class,
|
||||
'apiauth' => AuthFilter::class
|
||||
]
|
||||
```
|
||||
|
||||
Authorize request by adding field "Authorization" with value "Bearer xxxxxx" in Request Header:
|
||||
![[Pasted image 20241127140801.png]]
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
https://www.youtube.com/watch?v=f0NifEgwh30&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=33
|
||||
|
||||
|
||||
```php
|
||||
auth()->user()
|
||||
```
|
||||
|
||||
|
||||
```php
|
||||
$userId = auth()->id();
|
||||
```
|
||||
|
||||
![[Pasted image 20241129092837.png]]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AuthController
|
||||
```php
|
||||
//...
|
||||
|
||||
// Post
|
||||
public function login()
|
||||
{
|
||||
|
||||
if(auth()->loggedIn()){
|
||||
auth()->logout();
|
||||
}
|
||||
|
||||
$rules = [
|
||||
"email" => "required|valid_email",
|
||||
"password" => "required"
|
||||
];
|
||||
|
||||
if (!$this->validate($rules)) {
|
||||
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => $this->validator->getErrors(),
|
||||
"data" => []
|
||||
];
|
||||
} else {
|
||||
|
||||
// success
|
||||
$credentials = [
|
||||
"email" => $this->request->getVar("email"),
|
||||
"password" => $this->request->getVar("password")
|
||||
];
|
||||
|
||||
$loginAttempt = auth()->attempt($credentials);
|
||||
|
||||
if (!$loginAttempt->isOK()) {
|
||||
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => "Invalid login details",
|
||||
"data" => []
|
||||
];
|
||||
} else {
|
||||
|
||||
// to test: directly getting $userObject via auth()->user()
|
||||
|
||||
// We have a valid data set
|
||||
$userObject = new UserModel();
|
||||
|
||||
$userData = $userObject->findById(auth()->id());
|
||||
|
||||
$token = $userData->generateAccessToken("thisismysecretkey");
|
||||
|
||||
$auth_token = $token->raw_token;
|
||||
|
||||
$response = [
|
||||
"status" => true,
|
||||
"message" => "User logged in successfully",
|
||||
"data" => [
|
||||
"token" => $auth_token
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->respondCreated($response);
|
||||
}
|
||||
|
||||
//...
|
||||
```
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
https://www.youtube.com/watch?v=H1KiXEsmsCs&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=34
|
||||
|
||||
Routes.php:
|
||||
```php
|
||||
//Get
|
||||
$routes->get("logout", "AuthController::logout", ["filter" => "apiauth"]);
|
||||
```
|
||||
|
||||
AuthController.php
|
||||
```php
|
||||
public function logout() {
|
||||
auth()->logout();
|
||||
auth()->user()->revokeAllAccessTokens();
|
||||
|
||||
return $this->respondCreated([
|
||||
"status" => true,
|
||||
"message" => "User logged out successfully",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
https://www.youtube.com/watch?v=104Q76g7DWA&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=36
|
||||
|
||||
ProjectController
|
||||
```php
|
||||
// Post
|
||||
public function addProject()
|
||||
{
|
||||
$rules = [
|
||||
"name" => "required",
|
||||
"budget" => "required"
|
||||
];
|
||||
|
||||
if(!$this->validate($rules)) {
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => $this->validator->getErrors(),
|
||||
"data" => []
|
||||
];
|
||||
}else {
|
||||
$user_id = auth()-id();
|
||||
$name = $this->request->getVar("name");
|
||||
$budget = $this->request->getVar("budget");
|
||||
$pm = new ProjectModel();
|
||||
$data= [
|
||||
"user_id" => $user_id,
|
||||
"name" => name,
|
||||
"budget" => budget
|
||||
];
|
||||
if($pm->insert($data)) {
|
||||
$response = [
|
||||
"status" => true,
|
||||
"message" => "project saved",
|
||||
"data" => []
|
||||
];
|
||||
}else{
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => "project save failed",
|
||||
"data" => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$return $this->respondCreated($response);
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1 @@
|
|||
https://www.youtube.com/watch?v=B5GafCSXj9U&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=37
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
https://www.youtube.com/watch?v=-NIoOj-FtHE&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=36
|
||||
|
||||
ProjectController.php
|
||||
```php
|
||||
public function listProjects()
|
||||
{
|
||||
$user_id = auth()->id();
|
||||
$pm = new ProjectModel();
|
||||
|
||||
$projectData = $pm->where([
|
||||
"user_id" => $user_id
|
||||
])->findAll();
|
||||
|
||||
if (count($projectData)>0) {
|
||||
$response = [
|
||||
"status" => true,
|
||||
"message" => "Project data",
|
||||
"data" => $projectData
|
||||
];
|
||||
}else {
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => "No Project data found",
|
||||
"data" => []
|
||||
];
|
||||
}
|
||||
|
||||
return $this->respondCreated($response);
|
||||
}
|
||||
```
|
||||
|
||||
Routes.php
|
||||
```php
|
||||
$routes->get("list-projects", "ProjectController::listProjects", ["filter" => "apiauth"]);
|
||||
```
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
https://www.youtube.com/watch?v=B5GafCSXj9U&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=37
|
||||
|
||||
ProjectController.php
|
||||
```php
|
||||
public function deleteProject($project_id)
|
||||
{
|
||||
$user_id = auth()->id();
|
||||
if(!empty($project_id)) {
|
||||
$pm = new ProjectModel();
|
||||
$projectData = $pm->where([
|
||||
"user_id" => $user_id,
|
||||
"id" => $project_id
|
||||
])->first();
|
||||
|
||||
if (!empty($projectData)) {
|
||||
if(pm->delete($project_id)) {
|
||||
$response = [
|
||||
"status" => true,
|
||||
"message" => "project deleted",
|
||||
"data" => []
|
||||
];
|
||||
}else {
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => "failed to delete project",
|
||||
"data" => []
|
||||
];
|
||||
}
|
||||
}else{
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => "project not found",
|
||||
"data" => []
|
||||
];
|
||||
}
|
||||
|
||||
}else{
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => "Project Id required",
|
||||
"data" => []
|
||||
];
|
||||
}
|
||||
|
||||
return $this->respondCreated($response);
|
||||
}
|
||||
```
|
||||
|
||||
Routes.php
|
||||
```php
|
||||
$routes->delete("delete-project/(:num)", "ProjectController::deleteProject/$1",["filter"=>"apiauth"]);
|
||||
```
|
||||
|
||||
|
||||
|
||||
Alternative version:
|
||||
```php
|
||||
public function deleteProject($project_id)
|
||||
{
|
||||
$user_id = auth()->id();
|
||||
|
||||
if(empty($project_id)) {
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => "project id required",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
|
||||
$pm = new ProjectModel();
|
||||
$projectData = $pm->where([
|
||||
"user_id" => $user_id,
|
||||
"id" => $project_id
|
||||
])->first();
|
||||
|
||||
if(empty($projectData)) {
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => "project not found",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
|
||||
if(!$pm->delete($project_id)) {
|
||||
return $this->respondCreated([
|
||||
"status" => false,
|
||||
"message" => "failed to delete project",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->respondCreated([
|
||||
"status" => true,
|
||||
"message" => "project deleted",
|
||||
"data" => []
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
https://www.youtube.com/watch?v=8GhfHZlEaEo&list=PLT9miexWCpPW6Z_OXNv2d78cqCrZaPrVG&index=41
|
||||
|
||||
|
||||
In case Web Server throws CORS errors when trying to access API.
|
||||
We add a filter that adds header with CORS info to define which kind of HTTP are allowed from foreign source.
|
||||
|
||||
|
||||
Create CorsFilter.php
|
||||
```bash
|
||||
php spark make:filter Cors --suffix
|
||||
```
|
||||
|
||||
Add to before method:
|
||||
```php
|
||||
public function before(RequestInterface $request, $arguments=null)
|
||||
{
|
||||
header("Access-Control-Allow-Origin: *");
|
||||
header("Access-Control-Allow-Headers: Authorization, Content-Type, Accept, API-KEY");
|
||||
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH");
|
||||
}
|
||||
```
|
||||
|
||||
Add in app/Config/Filters.php:
|
||||
![[Pasted image 20241202084231.png]]
|
||||
![[Pasted image 20241202084303.png]]
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
```bash
|
||||
python3 -m http.server 8000
|
||||
```
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
```php
|
||||
<?php
|
||||
|
||||
$DBUSER="user";
|
||||
$DBPASSWD="password";
|
||||
$DATABASE="user_db";
|
||||
|
||||
$filename = "backup-" . date("d-m-Y") . ".sql.gz";
|
||||
$mime = "application/x-gzip";
|
||||
|
||||
header( "Content-Type: " . $mime );
|
||||
header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
|
||||
|
||||
$cmd = "mysqldump -u $DBUSER --password=$DBPASSWD $DATABASE | gzip --best";
|
||||
|
||||
passthru( $cmd );
|
||||
|
||||
exit(0);
|
||||
?>
|
||||
```
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
developer.tomtom.com
|
||||
tschneider
|
||||
Supertomtom1!
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
```php
|
||||
<!-- test1.php -->
|
||||
|
||||
<?php
|
||||
|
||||
//The URL with parameters / query string.
|
||||
// Escape: $str = preg_replace('/[^a-z\d ]/i', '', $str);
|
||||
|
||||
$url='https://api.tomtom.com/search/2/search/Am%20Kapellchen%2021%2C%2041470%20Neuss.json?lat=37.337&lon=-121.89&minFuzzyLevel=1&maxFuzzyLevel=2&view=Unified&relatedPois=off&key=xcA6NjLwDPmayP6y56AoVoloz1iohbUV';
|
||||
|
||||
//we use file_get_contents to GET the URL in question.
|
||||
$contents = file_get_contents($url);
|
||||
|
||||
$result = json_decode($contents);
|
||||
$lat = $result->results[0]->position->lat;
|
||||
$lon = $result->results[0]->position->lon;
|
||||
|
||||
echo "Lat=" . $lat . ", Lon=" . $lon;
|
||||
|
||||
```
|
||||
|
||||
````php
|
||||
<?php
|
||||
|
||||
//The URL with parameters / query string.
|
||||
|
||||
$url='https://api.tomtom.com/search/2/search/Am%20Kapellchen%2021%2C%2041470%20Neuss.json?lat=37.337&lon=-121.89&minFuzzyLevel=1&maxFuzzyLevel=2&view=Unified&relatedPois=off&key=xcA6NjLwDPmayP6y56AoVoloz1iohbUV';
|
||||
|
||||
//we use file_get_contents to GET the URL in question.
|
||||
$contents = file_get_contents($url);
|
||||
|
||||
//If $contents is not a boolean FALSE value.
|
||||
if($contents !== false){
|
||||
//Print out the contents.
|
||||
echo $contents;
|
||||
}
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
````php
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class='use-all-space'>
|
||||
<head>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=Edge' />
|
||||
<meta charset='UTF-8'>
|
||||
<title>Maps SDK for Web - Static route</title>
|
||||
|
||||
<meta name='viewport'
|
||||
content='width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no'/>
|
||||
|
||||
<link rel='stylesheet' type='text/css' href='https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.20.0/maps/maps.css'>
|
||||
|
||||
<link rel='stylesheet' type='text/css' href='../test/assets/ui-library/icons-css/routing.css'/>
|
||||
|
||||
<link rel='stylesheet' type='text/css' href='../test/assets/ui-library/index.css'/>
|
||||
|
||||
</head>
|
||||
|
||||
<style>
|
||||
.icon {
|
||||
background-size: cover;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.route-marker {
|
||||
align-items: center;
|
||||
background-color: #4a90e2;
|
||||
border: solid 3px #2faaff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
height: 32px;
|
||||
justify-content: center;
|
||||
transition: width .1s, height .1s;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<div><h1>TEST KARTE</<h1></div>
|
||||
<div style="height: 90%" id='map' class='map'></div>
|
||||
<script src='https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.20.0/maps/maps-web.min.js'></script>
|
||||
|
||||
<script src='https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.20.0/services/services-web.min.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../test/assets/js/mobile-or-tablet.js'></script>
|
||||
|
||||
<script>
|
||||
var map = tt.map({
|
||||
key: 'xcA6NjLwDPmayP6y56AoVoloz1iohbUV',
|
||||
container: 'map',
|
||||
//dragPan: !isMobileOrTablet()
|
||||
dragPan: false
|
||||
});
|
||||
|
||||
map.scrollZoom.disable()
|
||||
//map.addControl(new tt.FullscreenControl());
|
||||
//map.addControl(new tt.NavigationControl());
|
||||
|
||||
|
||||
|
||||
function createMarkerElement(type) {
|
||||
var element = document.createElement('div');
|
||||
var innerElement = document.createElement('div');
|
||||
|
||||
|
||||
|
||||
element.className = 'route-marker';
|
||||
innerElement.className = 'icon tt-icon -white -' + type;
|
||||
element.appendChild(innerElement);
|
||||
return element;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function addMarkers(feature) {
|
||||
|
||||
var startPoint, endPoint;
|
||||
if (feature.geometry.type === 'MultiLineString') {
|
||||
startPoint = feature.geometry.coordinates[0][0]; //get first point from first line
|
||||
endPoint = feature.geometry.coordinates.slice(-1)[0].slice(-1)[0]; //get last point from last line
|
||||
} else {
|
||||
startPoint = feature.geometry.coordinates[0];
|
||||
endPoint = feature.geometry.coordinates.slice(-1)[0];
|
||||
}
|
||||
|
||||
|
||||
new tt.Marker({ element: createMarkerElement('start') }).setLngLat(startPoint).addTo(map);
|
||||
|
||||
new tt.Marker({ element: createMarkerElement('finish') }).setLngLat(endPoint).addTo(map);
|
||||
|
||||
}
|
||||
|
||||
function findFirstBuildingLayerId() {
|
||||
var layers = map.getStyle().layers;
|
||||
for (var index in layers) {
|
||||
if (layers[index].type === 'fill-extrusion') {
|
||||
return layers[index].id;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('Map style does not contain any layer with fill-extrusion type.');
|
||||
}
|
||||
|
||||
map.once('load', function() {
|
||||
tt.services.calculateRoute({
|
||||
key: 'xcA6NjLwDPmayP6y56AoVoloz1iohbUV',
|
||||
traffic: false,
|
||||
locations: '4.8786,52.3679:4.8798,52.3679'
|
||||
})
|
||||
.then(function(response) {
|
||||
var geojson = response.toGeoJson();
|
||||
map.addLayer({
|
||||
'id': 'route',
|
||||
'type': 'line',
|
||||
'source': {
|
||||
'type': 'geojson',
|
||||
'data': geojson
|
||||
},
|
||||
|
||||
'paint': {
|
||||
'line-color': '#4a90e2',
|
||||
'line-width': 8
|
||||
}
|
||||
}, findFirstBuildingLayerId());
|
||||
|
||||
addMarkers(geojson.features[0]);
|
||||
|
||||
var bounds = new tt.LngLatBounds();
|
||||
geojson.features[0].geometry.coordinates.forEach(function(point) {
|
||||
bounds.extend(tt.LngLat.convert(point));
|
||||
|
||||
});
|
||||
|
||||
map.fitBounds(bounds, { duration: 0, padding: 50 });
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue