Selaa lähdekoodia

Fomo framework for PHP (#9584)

* added fomo framework

* added some .keep files

* corrected readme

* Update .env remove APP_WORKER_COUNT

* Test with PHP8.4

* Revert to PHP8.3

Work but with deprecated errrors.

* Remove unnece

* Remove unnecessary services configs

---------

Co-authored-by: Joan Miquel <[email protected]>
n0nag0n 5 kuukautta sitten
vanhempi
commit
756600eaa2

+ 21 - 0
frameworks/PHP/fomo/.env

@@ -0,0 +1,21 @@
+APP_NAME=Fomo
+APP_TIMEZONE=UTC
+APP_ENV=local
+APP_SSL=false
+APP_DEBUG=false
+APP_URL=http://localhost
+
+DB_HOST=tfb-database
+DB_PORT=3306
+DB_DATABASE=hello_world
+DB_USERNAME=benchmarkdbuser
+DB_PASSWORD=benchmarkdbpass
+DB_CHARSET=utf8mb4
+DB_COLLATION=utf8mb4_unicode_ci
+
+REDIS_HOST=127.0.0.1
+REDIS_PASSWORD=null
+REDIS_USERNAME=null
+REDIS_PORT=6379
+REDIS_DATABASE=0
+

+ 12 - 0
frameworks/PHP/fomo/.gitignore

@@ -0,0 +1,12 @@
+.buildpath
+.settings/
+.project
+*.patch
+.idea/
+.git/
+runtime/
+vendor/
+.phpintel/
+.DS_Store
+*.lock
+.phpunit*

+ 26 - 0
frameworks/PHP/fomo/README.md

@@ -0,0 +1,26 @@
+# Introduction
+
+Fomo is a web application framework based.
+
+We tried to implement Fomo in the simplest possible way so that anyone can use it.
+
+Fomo supports the following:
+
+- Simple, fast routing engine.
+- Processing work in the background.
+- Queued job processing.
+- And more...
+
+Fomo is very fast, simple and for use in large scale projects.
+
+# Original intention
+
+Here's 3 reason why you should use Fomo:
+
+- Fomo is very simple (less to learn and train others on).
+- Fomo is very fast (uses fewer resources to do the same thing).
+- Fomo is another tool that developers can use to solve their complex problems in a simple way.
+
+# Documentation
+
+[https://fomo-framework.github.io/docs/](https://fomo-framework.github.io/docs/)

+ 30 - 0
frameworks/PHP/fomo/app/Exceptions/Handler.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Exceptions;
+
+use Fomo\Request\Request;
+use Throwable;
+
+class Handler
+{
+    public function notFoundHttpException(Request $request): string
+    {
+        return response()->json([
+            'message' => 'not found'
+        ] , 404);
+    }
+
+    public function notAllowedHttpException(Request $request): string
+    {
+        return response()->json([
+            'message' => "this is route supported {$request->method()} method"
+        ] , 405);
+    }
+
+    public function InternalErrorException(Request $request, Throwable $error): string
+    {     
+        return response()->json([
+            'message' => 'internal error'
+        ] , 500);
+    }
+}

+ 31 - 0
frameworks/PHP/fomo/benchmark_config.json

@@ -0,0 +1,31 @@
+{
+	"framework": "fomo",
+	"tests": [
+	  {
+		"default": {
+		  "json_url": "/json",
+		  "plaintext_url": "/plaintext",
+		  "db_url": "/db",
+		  "fortune_url": "/fortunes",
+		  "query_url": "/query?queries=",
+		  "update_url": "/update?queries=",
+		  "port": 9000,
+		  "approach": "Realistic",
+		  "classification": "Micro",
+		  "database": "mysql",
+		  "framework": "Fomo",
+		  "language": "PHP",
+		  "flavor": "None",
+		  "orm": "Full",
+		  "platform": "swoole",
+		  "webserver": "None",
+		  "os": "Linux",
+		  "database_os": "Linux",
+		  "display_name": "Fomo",
+		  "notes": "",
+		  "versus": "swoole"
+		}
+	  }
+	]
+  }
+  

+ 45 - 0
frameworks/PHP/fomo/composer.json

@@ -0,0 +1,45 @@
+{
+    "name": "fomo/fomo",
+    "description": "The Fomo Framework",
+    "keywords": ["framework", "fomo" , "high performance"],
+    "type": "project",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Amir",
+            "email": "[email protected]"
+        }
+    ],
+    "require": {
+        "php" : ">=8.1",
+        "fomo/framework": "^2.0"
+    },
+    "autoload": {
+        "psr-4": {
+            "App\\" : "app/" ,
+            "Database\\" : "database/",
+            "Storage\\Routes\\" : "storage/routes/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Tests\\": "tests/"
+        }
+    },
+    "scripts": {
+        "post-root-package-install": [
+            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
+        ]
+    },
+    "minimum-stability": "dev",
+    "prefer-stable": true,
+    "require-dev": {
+        "fakerphp/faker": "^1.15",
+        "phpunit/phpunit": "^9.5"
+    },
+    "config": {
+        "allow-plugins": {
+            "php-http/discovery": true
+        }
+    }
+}

+ 19 - 0
frameworks/PHP/fomo/config.toml

@@ -0,0 +1,19 @@
+[framework]
+name = "fomo"
+
+[main]
+urls.plaintext = "/plaintext"
+urls.json = "/json"
+urls.db = "/db"
+urls.query = "/queries/"
+urls.update = "/updates/"
+urls.fortune = "/fortunes"
+approach = "Realistic"
+classification = "Fullstack"
+database = "MySQL"
+database_os = "Linux"
+os = "Linux"
+orm = "Full"
+platform = "swoole"
+webserver = "None"
+versus = "swoole"

+ 8 - 0
frameworks/PHP/fomo/config/app.php

@@ -0,0 +1,8 @@
+<?php
+
+return [
+    'name'                 => env('APP_NAME' , 'Fomo'),
+    'timezone'             => env('APP_TIMEZONE' , 'UTC'),
+    'faker_locale'         => 'en_US' ,
+    'locale'               => 'en' ,
+];

+ 67 - 0
frameworks/PHP/fomo/config/database.php

@@ -0,0 +1,67 @@
+<?php
+
+return [
+    'default' => env('DB_CONNECTION', 'mysql'),
+
+    'connections' => [
+
+        'sqlite' => [
+            'driver' => 'sqlite',
+            'url' => env('DATABASE_URL'),
+            'database' => env('DB_DATABASE', databasePath('database.sqlite')),
+            'prefix' => '',
+            'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
+        ],
+
+        'mysql' => [
+            'driver' => 'mysql',
+            'url' => env('DATABASE_URL'),
+            'host' => env('DB_HOST', '127.0.0.1'),
+            'port' => env('DB_PORT', '3306'),
+            'database' => env('DB_DATABASE', 'forge'),
+            'username' => env('DB_USERNAME', 'forge'),
+            'password' => env('DB_PASSWORD', ''),
+            'unix_socket' => env('DB_SOCKET', ''),
+            'charset' => 'utf8mb4',
+            'collation' => 'utf8mb4_unicode_ci',
+            'prefix' => '',
+            'prefix_indexes' => true,
+            'strict' => true,
+            'engine' => null,
+            'options' => extension_loaded('pdo_mysql') ? array_filter([
+                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
+            ]) : [],
+        ],
+
+        'pgsql' => [
+            'driver' => 'pgsql',
+            'url' => env('DATABASE_URL'),
+            'host' => env('DB_HOST', '127.0.0.1'),
+            'port' => env('DB_PORT', '5432'),
+            'database' => env('DB_DATABASE', 'forge'),
+            'username' => env('DB_USERNAME', 'forge'),
+            'password' => env('DB_PASSWORD', ''),
+            'charset' => 'utf8',
+            'prefix' => '',
+            'prefix_indexes' => true,
+            'search_path' => 'public',
+            'sslmode' => 'prefer',
+        ],
+
+        'sqlsrv' => [
+            'driver' => 'sqlsrv',
+            'url' => env('DATABASE_URL'),
+            'host' => env('DB_HOST', 'localhost'),
+            'port' => env('DB_PORT', '1433'),
+            'database' => env('DB_DATABASE', 'forge'),
+            'username' => env('DB_USERNAME', 'forge'),
+            'password' => env('DB_PASSWORD', ''),
+            'charset' => 'utf8',
+            'prefix' => '',
+            'prefix_indexes' => true,
+            // 'encrypt' => env('DB_ENCRYPT', 'yes'),
+            // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
+        ],
+
+    ]
+];

+ 82 - 0
frameworks/PHP/fomo/config/server.php

@@ -0,0 +1,82 @@
+<?php
+
+return [
+    /*
+     * mode
+     * SWOOLE_BASE ,
+     * SWOOLE_PROCESS
+     */
+    'mode' => SWOOLE_BASE ,
+    'host' => '0.0.0.0',
+    'port' => 9000 ,
+    'sockType' => SWOOLE_SOCK_TCP ,
+    'additional' => [
+        'worker_num' => env('APP_WORKER_COUNT' , cpuCount() * 2) ,
+        /*
+         * log level
+         * SWOOLE_LOG_DEBUG (default)
+         * SWOOLE_LOG_TRACE
+         * SWOOLE_LOG_INFO
+         * SWOOLE_LOG_NOTICE
+         * SWOOLE_LOG_WARNING
+         * SWOOLE_LOG_ERROR
+         */
+        'log_level' => SWOOLE_LOG_DEBUG ,
+        'log_file' => storagePath('logs/fomo.log') ,
+    
+        /*
+        This key causes Fomo to receive a complete HTTP data packet and prevents it from receiving incomplete HTTP packets.
+        */
+        'open_http_protocol' => true,
+    ],
+
+    'ssl' => [
+        'ssl_cert_file' => null ,
+        'ssl_key_file' => null ,
+    ] ,
+
+    /*
+     * The following services are created for better performance in the program, only one object is created from them and they can be used throughout the program
+     */
+    'services' => [
+        Fomo\Services\Cache::class ,
+        Fomo\Services\Database::class ,
+        Fomo\Services\Language::class ,
+        Fomo\Services\Response::class ,
+        Fomo\Services\Validation::class ,
+    ] ,
+
+    /*
+     * Files and folders that must be changed in real time
+     */
+    'watcher' => [
+        'app',
+        'config',
+        'database',
+        'language',
+        'routes',
+        'composer.lock',
+        '.env',
+    ] ,
+
+    /*
+     * Each of the following causes changes to the performance of the desired class. (so be careful in using them)
+     */
+    'advanceMode' => [
+        /*
+         * advanced mode in Fomo\Request\Request class
+         *
+         * By activating the advanced mode in this class, you can access the data you want in an advanced way
+         * For example, consider that the user has sent you a array of the information of several customers.
+         * If the advanced mode is not active, you can only access an array of all customer information
+         *
+         * For example, the:
+         * $request->get('customers')
+         *
+         * But if the advanced mode is active, you can access any data you need from customers
+         * For example, the:
+         * $request->get('customers.*.name')
+         */
+        'request' => DISABLE
+    ]
+];

+ 13 - 0
frameworks/PHP/fomo/deploy/php-async.ini

@@ -0,0 +1,13 @@
+opcache.enable=1
+opcache.enable_cli=1
+opcache.validate_timestamps=0
+opcache.save_comments=0
+opcache.enable_file_override=1
+opcache.memory_consumption=256
+opcache.interned_strings_buffer=16
+opcache.max_accelerated_files=7963
+opcache.preload_user=www-data
+
+mysqlnd.collect_statistics = Off
+
+memory_limit = 512M

+ 98 - 0
frameworks/PHP/fomo/engineer

@@ -0,0 +1,98 @@
+<?php
+
+require __DIR__.'/vendor/autoload.php';
+
+use Dotenv\Dotenv;
+use Symfony\Component\Console\Application;
+use Fomo\Commands\Server\Start as StartServerCommand;
+use Fomo\Commands\Server\Reload as ReloadServerCommand;
+use Fomo\Commands\Server\Status as StatusServerCommand;
+use Fomo\Commands\Server\Stop as StopServerCommand;
+use Fomo\Commands\Build\Controller as BuildControllerCommand;
+use Fomo\Commands\Build\Exception as BuildExceptionCommand;
+use Fomo\Commands\Build\Middleware as BuildMiddlewareCommand;
+use Fomo\Commands\Build\Resource as BuildResourceCommand;
+use Fomo\Commands\Build\Test as BuildTestCommand;
+use Fomo\Commands\Build\Job as BuildJobCommand;
+use Fomo\Commands\Build\Task as BuildTaskCommand;
+use Fomo\Commands\Build\Service as BuildServiceCommand;
+use Fomo\Commands\Tests\Run as TestsRunCommand;
+use Fomo\Commands\Factory\Start as FactoryStartCommand;
+use Fomo\Commands\Queue\Start as QueueStartCommand;
+use Fomo\Commands\Queue\Status as QueueStatusCommand;
+use Fomo\Commands\Queue\Stop as QueueStopCommand;
+use Fomo\Commands\Scheduling\Start as SchedulerStartCommand;
+use Fomo\Commands\Scheduling\Status as SchedulerStatusCommand;
+use Fomo\Commands\Scheduling\Stop as SchedulerStopCommand;
+
+/*
+ * create const's and definitions
+ */
+define('PROJECT_PATH' , realpath('./'));
+const FOMO_VERSION = '2.4.3';
+const ENABLE = true;
+const DISABLE = false;
+
+/*
+ * load .env file
+ */
+Dotenv::createImmutable(basePath())->load();
+
+/*
+ * set timezone
+ */
+date_default_timezone_set(config('app.timezone'));
+
+/*
+ * create console
+ */
+$application = new Application();
+
+/*
+ * server commands
+ */
+$application->add(new StartServerCommand());
+$application->add(new ReloadServerCommand());
+$application->add(new StatusServerCommand());
+$application->add(new StopServerCommand());
+
+/*
+ * build commands
+ */
+$application->add(new BuildControllerCommand());
+$application->add(new BuildExceptionCommand());
+$application->add(new BuildMiddlewareCommand());
+$application->add(new BuildResourceCommand());
+$application->add(new BuildTestCommand());
+$application->add(new BuildJobCommand());
+$application->add(new BuildTaskCommand());
+$application->add(new BuildServiceCommand());
+
+/*
+ * tests commands
+ */
+$application->add(new TestsRunCommand());
+
+/*
+ * factory commands
+ */
+$application->add(new FactoryStartCommand());
+
+/*
+ * queue commands
+ */
+$application->add(new QueueStartCommand());
+$application->add(new QueueStatusCommand());
+$application->add(new QueueStopCommand());
+
+/*
+ * scheduler commands
+ */
+$application->add(new SchedulerStartCommand());
+$application->add(new SchedulerStatusCommand());
+$application->add(new SchedulerStopCommand());
+
+/*
+ * run console
+ */
+$application->run();

+ 22 - 0
frameworks/PHP/fomo/fomo.dockerfile

@@ -0,0 +1,22 @@
+FROM phpswoole/swoole:5.1.3-php8.3
+
+RUN docker-php-ext-install pcntl opcache > /dev/null
+
+# RUN pecl install --force redis
+
+COPY deploy/php-async.ini /usr/local/etc/php/php.ini
+
+COPY . /fomo
+
+WORKDIR /fomo
+
+RUN composer install --no-dev --quiet
+RUN composer dump-autoload --optimize --quiet
+
+RUN chmod -R 777 /fomo/storage
+
+# USER www-data
+
+EXPOSE 9000
+
+ENTRYPOINT [ "php", "engineer", "server:start" ]

+ 30 - 0
frameworks/PHP/fomo/language/validation/en/errors.php

@@ -0,0 +1,30 @@
+<?php
+
+return [
+    'message' => [
+        'required'      => 'The :attribute is mandatory' ,
+        'string'        => 'The :attribute must be a string' ,
+        'integer'       => 'The :attribute must be a number' ,
+        'boolean'       => 'The :attribute must be true or false' ,
+        'array'         => 'The :attribute must be an array' ,
+        'email'         => 'The :attribute must be the email address' ,
+        'regex'         => 'The template :attribute is wrong' ,
+        'notRegex'      => 'The template :attribute is wrong' ,
+        'max'           => 'The :attribute field should not be greater than :value' ,
+        'min'           => 'The :attribute field should not be less than :value' ,
+        'size'          => 'The field :attribute must be equal to :value' ,
+        'after'         => 'The :attribute field must be larger than the :value field' ,
+        'before'        => 'The :attribute field must be smaller than the :value field' ,
+        'in'            => 'The field :attribute must be equal to one of the values :value' ,
+        'date'          => 'The :attribute must be of date type' ,
+        'exists'        => 'Such :attribute does not exist' ,
+        'unique'        => 'Such :attribute exists' ,
+        'nationalCode'  => 'The national code entered in the :attribute field is incorrect'
+    ],
+
+    'attribute' => [
+        'firstName'     => 'first name' ,
+        'lastName'      => 'last name' ,
+        'phone'         => 'phone'
+    ]
+];

+ 100 - 0
frameworks/PHP/fomo/routes/api.php

@@ -0,0 +1,100 @@
+<?php
+
+/** @var Fomo\Router\Router $router */
+
+use Fomo\Database\DB;
+use Fomo\Request\Request;
+
+$router->get('/plaintext' , function () {
+    return response()->withHeaders([
+		'Server' => 'Fomo',
+		'Date' => date('D, d M Y H:i:s T'),
+	])->plainText('Hello, World!');
+});
+
+$router->get('/json' , function () {
+    return response()->withHeaders([
+		'Server' => 'Fomo',
+		'Date' => date('D, d M Y H:i:s T'),
+	])->json(['message' => 'Hello, World!']);
+});
+
+$router->get('/db' , function () {
+	$id = mt_rand(1, 10000);
+	// need to pull back a single record from the World table by an $id.
+	$world = (array) DB::table('World')->where('id', '=', $id)->get()->toArray()[0];
+	return response()->withHeaders([
+		'Server' => 'Fomo',
+		'Date' => date('D, d M Y H:i:s T'),
+	])->json($world);
+});
+
+$router->get('/fortunes' , function () {
+	
+	//$table = DB::table('World');
+	$fortunes = DB::table('Fortune')->get()->toArray();
+
+	$fortune = new \stdClass();
+	$fortune->id = 0;
+	$fortune->message = 'Additional fortune added at request time.';
+	array_unshift($fortunes, $fortune);
+
+	// sort the fortunes by message
+	usort($fortunes, function($a, $b) {
+		return $a->message <=> $b->message;
+	});
+
+	ob_start();
+	include(storagePath('view/fortunes.php'));
+	$html = ob_get_clean();
+
+	return response()->withHeaders([
+		'Server' => 'Fomo',
+		'Date' => date('D, d M Y H:i:s T'),
+	])->html($html);
+});
+
+$router->get('/query' , function () {
+	$request = Request::getInstance();
+	$queries = $request->get('queries');
+    if (is_numeric($queries)) {
+        $queries = max(1, min($queries, 500));
+    } else {
+        $queries = 1;
+    }
+
+    $worlds = [];
+    for ($i = 0; $i < $queries; ++$i) {
+		$random_id = mt_rand(1, 10000);
+        $world = (array) DB::table('World')->where('id', '=', $random_id)->get()->toArray()[0];
+        $worlds[] = $world;
+    }
+	return response()->withHeaders([
+		'Server' => 'Fomo',
+		'Date' => date('D, d M Y H:i:s T'),
+	])->json($worlds);
+});
+
+$router->get('/update' , function () {
+	$request = Request::getInstance();
+	$queries = $request->get('queries');
+    if (is_numeric($queries)) {
+        $queries = max(1, min($queries, 500));
+    } else {
+        $queries = 1;
+    }
+
+    $worlds = [];
+    for ($i = 0; $i < $queries; ++$i) {
+		$random_id = mt_rand(1, 10000);
+		$random_number = mt_rand(1, 10000);
+		$world = (array) DB::table('World')->where('id', '=', $random_id)->get()->toArray()[0];
+		DB::table('World')->where('id', '=', $world['id'])->update(['randomNumber' => $random_number]);
+		$world['randomNumber'] = $random_number;
+        $worlds[] = $world;
+    }
+	return response()->withHeaders([
+		'Server' => 'Fomo',
+		'Date' => date('D, d M Y H:i:s T'),
+	])->json($worlds);
+});

+ 0 - 0
frameworks/PHP/fomo/storage/logs/.keep


+ 0 - 0
frameworks/PHP/fomo/storage/routes/.keep


+ 18 - 0
frameworks/PHP/fomo/storage/view/fortunes.php

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Fortunes</title></head>
+  <body>
+    <table>
+        <tr>
+            <th>id</th>
+            <th>message</th>
+        </tr>
+        <?php foreach($fortunes as $fortune) : ?>
+            <tr>
+                <td><?= $fortune->id ?></td>
+                <td><?= htmlspecialchars($fortune->message) ?></td>
+            </tr>
+        <?php endforeach ?>
+    </table>
+  </body>
+</html>