Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Framework V2 #102

Merged
merged 90 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
e817592
adapters and refactor request and response
lohanidamodar Jul 6, 2023
ee75d8a
Merge remote-tracking branch 'origin/feat-routing-v2' into feat-v2
lohanidamodar Jul 11, 2023
02006b2
update test and fix
lohanidamodar Jul 11, 2023
151434c
fix lint
lohanidamodar Jul 11, 2023
af83713
fix tests
lohanidamodar Jul 11, 2023
4260458
fixes
lohanidamodar Jul 11, 2023
4355dfa
fix param reference
lohanidamodar Jul 11, 2023
29909da
downgrade symfony console
lohanidamodar Jul 11, 2023
63121c8
downgrade phpbench
lohanidamodar Jul 11, 2023
b6d83d5
remove leftover code
lohanidamodar Jul 11, 2023
9fbb075
move namespace
lohanidamodar Jul 11, 2023
f23bbe8
fix formatting
lohanidamodar Jul 11, 2023
45beee6
update constructor
lohanidamodar Jul 11, 2023
d8350d1
Update src/Adapter/Swoole/Server.php
lohanidamodar Jul 11, 2023
415a236
Merge branch 'feat-v2' of https://github.com/utopia-php/framework int…
lohanidamodar Jul 11, 2023
146ae35
fix test
lohanidamodar Jul 11, 2023
4eeddf7
update readme
lohanidamodar Jul 11, 2023
803dddc
file loading support in servers
lohanidamodar Jul 11, 2023
1876af8
fix and update test for both server adapters
lohanidamodar Jul 11, 2023
cbe0901
fix test flow
lohanidamodar Jul 12, 2023
c2e70ab
fix parameter name
lohanidamodar Jul 12, 2023
136c318
Update src/Adapter.php
lohanidamodar Jul 12, 2023
a3bdb49
Update src/Adapter.php
lohanidamodar Jul 12, 2023
ab04d15
update dockerfile name
lohanidamodar Jul 12, 2023
8b448f6
update readme
lohanidamodar Jul 12, 2023
eaf63bd
abstract away app start
lohanidamodar Jul 12, 2023
bd9ff87
rename dockerfile
lohanidamodar Jul 12, 2023
c8de4cc
rename App -> Http
lohanidamodar Jul 12, 2023
644687b
fix formatting
lohanidamodar Jul 12, 2023
4bcf458
update namespace
lohanidamodar Jul 12, 2023
31bd350
static file handling
lohanidamodar Jul 12, 2023
97f9320
fix formatting
lohanidamodar Jul 12, 2023
dc96765
upate php version for test - dev dependencies now require 8.1
lohanidamodar Jul 13, 2023
73d8f0b
more server related callbacks
lohanidamodar Jul 13, 2023
a912fab
start hook
lohanidamodar Jul 13, 2023
ab4544a
worker start hooks
lohanidamodar Jul 13, 2023
db4ae13
fix setting resource
lohanidamodar Jul 13, 2023
4eb0583
fix reset
lohanidamodar Jul 16, 2023
5a6d171
swoole beforeShutdown callback
lohanidamodar Jul 18, 2023
22bd6d6
support request hooks
lohanidamodar Jul 18, 2023
f5a483a
add getter for swoole internal request
lohanidamodar Jul 18, 2023
0e67327
getter for swoole response
lohanidamodar Jul 18, 2023
c2cc0f2
Merge remote-tracking branch 'origin/feat-routing-v2' into feat-v2
lohanidamodar Jul 20, 2023
552bccd
get fresh resource each time by default
lohanidamodar Jul 20, 2023
50d4cd5
enable context
lohanidamodar Aug 6, 2023
c0b5d73
fresh is now false by default
lohanidamodar Aug 6, 2023
33698fc
fix resource for context null
lohanidamodar Aug 6, 2023
cd3c30a
unused code
lohanidamodar Aug 6, 2023
0e4281d
add swoole test
lohanidamodar Aug 6, 2023
0f69480
update tests
lohanidamodar Aug 6, 2023
6dcef9a
fix test with resource reset
lohanidamodar Aug 6, 2023
242a20f
fix lint
lohanidamodar Aug 6, 2023
be16910
Merge remote-tracking branch 'origin' into feat-v2
lohanidamodar Aug 6, 2023
54074b9
set a default context and make context string
lohanidamodar Aug 6, 2023
11488b1
make utopia default context
lohanidamodar Aug 8, 2023
d2909e7
upgrade callback
lohanidamodar Aug 8, 2023
52c1a06
fix callback reset type
lohanidamodar Aug 8, 2023
7466616
Merge branch 'master' of https://github.com/utopia-php/framework into…
lohanidamodar Aug 9, 2023
b7ff4de
fix check and lint
lohanidamodar Aug 9, 2023
1105527
fixes after merge
lohanidamodar Aug 9, 2023
f3cb041
update missing resource
lohanidamodar Aug 10, 2023
daba6a7
Merge remote-tracking branch 'origin/master' into feat-v2
lohanidamodar Sep 7, 2023
d714fcb
remove view from framework
lohanidamodar Sep 10, 2023
6c8ffb0
Fix Swoole coroutine http server
Meldiron Oct 2, 2023
a4916b4
Disable forced type on onRequest
Meldiron Oct 2, 2023
69b83a3
Add route resource
Meldiron Oct 2, 2023
2213a3c
Fix tests
Meldiron Oct 3, 2023
96e1f58
Tests fix
Meldiron Oct 3, 2023
c9ea90e
Add swoole resources
Meldiron Oct 3, 2023
e34ed9c
Add default context to getResources
Meldiron Oct 4, 2023
c68f74e
Fix memory leak
Meldiron Oct 11, 2023
a73f0a0
Linter fix
Meldiron Oct 16, 2023
7405c1f
Improve Assoc validator with length param
Meldiron Oct 17, 2023
55792e0
Add multiple validator
vermakhushboo Dec 27, 2023
d81dd2a
Merge pull request #109 from utopia-php/fix-v2-swoole-coroutines
Meldiron Jan 3, 2024
399c89e
Merge remote-tracking branch 'origin/master' into feat-v2
Meldiron Jan 3, 2024
dff85bd
CI/CD fixes
Meldiron Jan 3, 2024
e44076b
Update README
Meldiron Jan 3, 2024
8dfe731
Auto-add context to swoole
Meldiron Jan 3, 2024
6cd3232
Update swoole README
Meldiron Jan 3, 2024
ceae30f
Improve readme, add example
Meldiron Jan 3, 2024
3ba0cd1
Grammar fixes
Meldiron Jan 3, 2024
ecf9791
Update README.md
Meldiron Jan 3, 2024
569428c
Update README.md
Meldiron Jan 3, 2024
f5e2ac0
Add fpm resources
Meldiron Jan 3, 2024
8ef5482
Fix formatting
Meldiron Jan 3, 2024
23dedb9
Merge pull request #113 from utopia-php/feat-add-multiple-validator-t…
eldadfux Jan 3, 2024
d8ef76a
PR review changes
Meldiron Jan 4, 2024
d5e2929
Improve swoole constructor
Meldiron Jan 4, 2024
ee4fc6d
Remove worker concept
Meldiron Jan 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
php-version: '8.1'

- name: Setup Docker
run: docker-compose up -d --build

- name: Wait for Server to be ready
run: sleep 10

- name: Run Tests
run: docker compose exec web vendor/bin/phpunit --configuration phpunit.xml
- name: Run FPM Tests
run: docker compose exec fpm vendor/bin/phpunit --configuration phpunit.xml

- name: Run Swoole Tests
run: docker compose exec swoole vendor/bin/phpunit --configuration phpunit.xml
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ $ git push origin [name_of_your_new_branch]
8. After approval, merge your PR
9. GitHub will automatically delete the branch after the merge is done. (they can still be restored).

### Testing

- `docker-compose up -d`
- `docker-compose exec web vendor/bin/phpunit --configuration phpunit.xml`
- `docker-compose exec web vendor/bin/psalm --show-info=true`

## Introducing New Features

We would 💖 you to contribute to Framework, but we would also like to make sure Framework is as great as possible and loyal to its vision and mission statement 🙏.
Expand Down
File renamed without changes.
29 changes: 29 additions & 0 deletions Dockerfile.swoole
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM composer:2.0 AS step0
Meldiron marked this conversation as resolved.
Show resolved Hide resolved


ARG TESTING=true

ENV TESTING=$TESTING

WORKDIR /usr/local/src/

COPY composer.* /usr/local/src/

RUN composer install --ignore-platform-reqs --optimize-autoloader \
--no-plugins --no-scripts --prefer-dist \
`if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi`

FROM appwrite/base:0.4.3 as final
LABEL maintainer="team@appwrite.io"

WORKDIR /usr/src/code

COPY ./src /usr/src/code/src
COPY ./tests /usr/src/code/tests
COPY ./phpunit.xml /usr/src/code/phpunit.xml
COPY ./phpbench.json /usr/src/code/phpbench.json
COPY --from=step0 /usr/local/src/vendor /usr/src/code/vendor

EXPOSE 80

CMD ["php", "tests/e2e/server-swoole.php"]
250 changes: 189 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Utopia Framework is a PHP MVC based framework with minimal must-have features for professional, simple, advanced and secure web development. This library is maintained by the [Appwrite team](https://appwrite.io).

Utopia Framework is dependency free. Any extra features such as authentication, caching will be available as standalone models in order to keep the framework core as clean, light and easy to learn.
Utopia Framework is dependency-free. Any extra features, such as authentication or caching, will be available as standalone models in order to keep the framework core clean, light, and easy to learn.

## Getting Started

Expand All @@ -17,19 +17,21 @@ Install using composer:
composer require utopia-php/framework
```

Init your first application:
Init your first application in `src/server.php`:

```php
require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__.'/../vendor/autoload.php';

use Utopia\App;
use Utopia\Request;
use Utopia\Response;
use Utopia\Http\Http;
use Utopia\Http\Request;
use Utopia\Http\Response;
use Utopia\Http\Adapter\FPM\Server;

App::get('/hello-world') // Define Route
Http::get('/hello-world') // Define Route
->inject('request')
->inject('response')
->action(
function($request, $response) {
function(Request $request, Response $response) {
$response
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
->addHeader('Expires', '0')
Expand All @@ -38,90 +40,222 @@ App::get('/hello-world') // Define Route
}
);

App::setMode(App::MODE_TYPE_PRODUCTION); // Define Mode
Http::setMode(Http::MODE_TYPE_PRODUCTION);

$http = new Http(new Server(), 'America/New_York');
$http->start();
```

$app = new App('America/New_York');
$request = new Request();
$response = new Response();
Run HTTP server:

$app->run($request, $response);
```bash
php -S localhost:8000 src/server2.php
```

### Hooks
Send HTTP request:

```bash
curl http://localhost:8000/hello-world
```

### Server Adapters

The library supports server adapters to be able to run on any PHP setup. For instance, you could use the FPM server or the Swoole server.

#### Use PHP FPM server

```php
use Utopia\Http\Http;
use Utopia\Http\Response;
use Utopia\Http\Adapter\FPM\Server;

Http::get('/')
->inject('response')
->action(
function(Response $response) {
$response->send('Hello from PHP FPM');
}
);

There are three types of hooks, init hooks, shutdown hooks and error hooks. Init hooks are executed before the route action is executed. Shutdown hook is executed after route action is executed before application shuts down. Finally error hooks are executed whenever there's an error in the application lifecycle. You can provide multiple hooks for each stage. If you do not assign groups to the hook, by default the hook will be executed for every route.
$http = new Http(new Server(), 'America/New_York');
$http->start();
```

> When using PHP FPM, you can use the command `php -S localhost:80 src/server.php` to run the HTTP server locally

#### Using Swoole server

```php
require_once __DIR__ . '/../../vendor/autoload.php';
use Utopia\Http\Http;
use Utopia\Http\Request;
use Utopia\Http\Response;
use Utopia\Http\Adapter\Swoole\Server;

Http::get('/')
->inject('request')
->inject('response')
->action(
function(Request $request, Response $response) {
$response->send('Hello from Swoole');
}
);

$http = new Http(new Server('0.0.0.0', '80'), 'America/New_York');
$http->start();
```

> When using Swoole, you can use the command `php src/server.php` to run the HTTP server locally, but you need Swoole installed. For setup with Docker, check out our [example application](/example)

### Parameters

Parameters are used to receive input into endpoint action from the HTTP request. Parameters could be defined as URL parameters or in a body with a structure such as JSON.

Every parameter must have a validator defined. Validators are simple classes that verify the input and ensure the security of inputs. You can define your own validators or use some of [built-in validators](/src/Http/Validator).

Define an endpoint with params:

```php
Http::get('/')
->param('name', 'World', new Text(256), 'Name to greet. Optional, max length 256.', true)
->inject('response')
->action(function(string $name, Response $response) {
$response->send('Hello ' . $name);
});
```

Send HTTP requests to ensure the parameter works:

```bash
curl http://localhost:8000/hello-world
curl http://localhost:8000/hello-world?name=Utopia
curl http://localhost:8000/hello-world?name=Appwrite
```

It's always recommended to use params instead of getting params or body directly from the request resource. If you do that intentionally, always make sure to run validation right after fetching such a raw input.

### Hooks

There are three types of hooks:

use Utopia\App;
use Utopia\Request;
use Utopia\Response;
- **Init hooks** are executed before the route action is executed
- **Shutdown hooks** are executed after route action is finished, but before application shuts down
- **Error hooks** are executed whenever there's an error in the application lifecycle.

App::init()
You can provide multiple hooks for each stage. If you do not assign groups to the hook, by default, the hook will be executed for every route. If a group is defined on a hook, it will only run during the lifecycle of a request with the same group name on the action.

```php
Http::init()
->inject('request')
->action(function(Request $request) {
\var_dump("Recieved: " . $request->getMethod() . ' ' . $request->getURI());
});

Http::shutdown()
->inject('response')
->action(function($response) {
$response->addHeader('content-type', 'application/json');
->action(function(Response $response) {
\var_dump('Responding with status code: ' . $response->getStatusCode());
});

App::error()
Http::error()
->inject('error')
->inject('response')
->action(function($error, $response) {
->action(function(\Throwable $error, Response $response) {
$response
->setStatusCode(500)
->send('Error occurred ' . $error);
});
```

App::get('/hello-world') // Define Route
->inject('request')
Hooks are designed to be actions that run during the lifecycle of requests. Hooks should include functional logic. Hooks are not designed to prepare dependencies or context for the request. For such a use case, you should use resources.

### Groups

Groups allow you to define common behavior for multiple endpoints.

You can start by defining a group on an endpoint. Keep in mind you can also define multiple groups on a single endpoint.

```php
Http::get('/v1/health')
->groups(['api', 'public'])
->inject('response')
->action(
function($request, $response) {
$response
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
->addHeader('Expires', '0')
->addHeader('Pragma', 'no-cache')
->json(['Hello' => 'World']);
function(Response $response) {
$response->send('OK');
}
);
```

App::setMode(App::MODE_TYPE_PRODUCTION); // Define Mode
Now you can define hooks that would apply only to specific groups. Remember, hooks can also be assigned to multiple groups.

$app = new App('America/New_York');
eldadfux marked this conversation as resolved.
Show resolved Hide resolved
$request = new Request();
$response = new Response();
```php
Http::init()
->groups(['api'])
->inject('request')
->inject('response')
->action(function(Request $request, Response $response) {
$apiKey = $request->getHeader('x-api-key', '');

$app->run($request, $response);
if(empty($apiKey)) {
$response
->setStatusCode(Response::STATUS_CODE_UNAUTHORIZED)
->send('API key missing.');
}
});
```

Groups are designed to be actions that run during the lifecycle of requests to endpoints that have some logic in common. Groups allow you to prevent code duplication and are designed to be defined anywhere in your source code to allow flexibility.

### Resources

Resources allow you to prepare dependencies for requests such as database connection or the user who sent the request. A new instance of a resource is created for every request.

Define a resource:

```php
Http::setResource('timing', function() {
return \microtime(true);
});
```

Inject resource into endpoint action:

```php
Http::get('/')
->inject('timing')
->inject('response')
->action(function(float $timing, Response $response) {
$response->send('Request Unix timestamp: ' . \strval($timing));
});
```

Inject resource into a hook:

```php
Http::shutdown()
->inject('timing')
->action(function(float $timing) {
$difference = \microtime(true) - $timing;
\var_dump("Request took: " . $difference . " seconds");
});
```

In advanced scenarios, resources can also be injected into other resources or endpoint parameters.

Resources are designed to prepare dependencies or context for the request. Resources are not meant to do functional logic or return callbacks. For such a use case, you should use hooks.

To learn more about Framework architecture and features, check out more in-depth [Getting started guide](/docs/Getting-Starting-Guide.md).

## System Requirements

Utopia Framework requires PHP 8.0 or later. We recommend using the latest PHP version whenever possible.

## More from Utopia

Our ecosystem support other thin PHP projects aiming to extend the core PHP Utopia framework.
Our ecosystem supports other thin PHP projects aiming to extend the core PHP Utopia framework.

Each project is focused on solving a single, very simple problem and you can use composer to include any of them in your next project.

Library | Description
--- | ---
**[Utopia AB](https://github.com/utopia-php/ab)** | Simple PHP library for managing AB testing on the server side.
**[Utopia Abuse](https://github.com/utopia-php/abuse)** | Simple PHP library for rate limiting usage of different features in your app or API.
**[Utopia Analytics](https://github.com/utopia-php/analytics)** | Simple PHP library to send information about events or pageviews to Google Analytics.
**[Utopia Audit](https://github.com/utopia-php/audit)** | Simple PHP library for audit logging users actions and system events
**[Utopia Cache](https://github.com/utopia-php/cache)** | Simple PHP library for managing cache with different storage adapters.
**[Utopia CLI](https://github.com/utopia-php/cli)** | Simple PHP library for for building simple command line tools.
**[Utopia Config](https://github.com/utopia-php/config)** | Simple PHP library for managing your app configuration.
**[Utopia Database](https://github.com/utopia-php/database)** | Simple PHP library for managing application persistency. It supports multiple database adapters.
**[Utopia Domains](https://github.com/utopia-php/domains)** | Simple PHP library for parsing domain names.
**[Utopia Image](https://github.com/utopia-php/image)** | Simple PHP library for creating common image manipulations that is easy to use.
**[Utopia Locale](https://github.com/utopia-php/locale)** | Simple PHP library for adding support to multiple locales in your app or API.
**[Utopia Preloader](https://github.com/utopia-php/preloader)** | Simple PHP library for managing PHP preloading configuration.
**[Utopia Registry](https://github.com/utopia-php/registry)** | Simple PHP library for dependency injection and lazy loading of objects or resources.
**[Utopia System](https://github.com/utopia-php/system)** | Simple PHP library for obtaining information about the host's system.
**[Utopia Storage](https://github.com/utopia-php/storage)** | Simple and lite PHP library for managing application storage. It supports multiple storage adapters.
You can find all libraries in [GitHub Utopia organization](https://github.com/utopia-php).

## Contributing

Expand All @@ -133,12 +267,6 @@ You can refer to the [Contributing Guide](https://github.com/utopia-php/framewor

For security issues, please email security@appwrite.io instead of posting a public issue in GitHub.

### Testing

- `docker-compose up -d`
- `docker-compose exec web vendor/bin/phpunit --configuration phpunit.xml`
- `docker-compose exec web vendor/bin/psalm --show-info=true`

## Copyright and license

The MIT License (MIT) [http://www.opensource.org/licenses/mit-license.php](http://www.opensource.org/licenses/mit-license.php)
Loading