)
+ - '#Call to an undefined static method Tutorial\\Models\\[A-Za-z]+::(find|findFirst)By[A-Za-z]+\(\)#'
+ # Phalcon\Mvc\Model is generic (@template T) in the v6 source; the loaded v5
+ # runtime model is not, so the model does not parametrize it.
+ - '#extends generic class Phalcon\\Mvc\\Model but does not specify its types#'
+ # MetaData\Stream: v6 source needs lowercase 'Metadata'; a loaded v5 extension
+ # reports 'MetaData'. Both resolve at runtime (class names are case-insensitive).
+ - '#Class Phalcon\\Mvc\\Model\\MetaData\\Stream referenced with incorrect case#'
diff --git a/resources/phpunit.xml.dist b/resources/phpunit.xml.dist
new file mode 100644
index 0000000..e2acff9
--- /dev/null
+++ b/resources/phpunit.xml.dist
@@ -0,0 +1,15 @@
+
+
+
+
+ ../tests/Functional
+
+
+
+
+ ../src
+
+
+
diff --git a/resources/schemas/tutorial.sql b/resources/schemas/tutorial.sql
index 4f8cede..061681c 100644
--- a/resources/schemas/tutorial.sql
+++ b/resources/schemas/tutorial.sql
@@ -1,41 +1,14 @@
-CREATE DATABASE IF NOT EXISTS `tutorial` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
-USE `tutorial`;
-
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
-/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
-/*!40101 SET NAMES utf8mb4 */;
-/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
-/*!40103 SET TIME_ZONE='+00:00' */;
-/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-
---
--- Table structure for table `users`
---
-
-/*!40101 SET @saved_cs_client = @@character_set_client */;
-/*!40101 SET character_set_client = utf8mb4 */;
-CREATE TABLE `users`
+CREATE TABLE IF NOT EXISTS `users`
(
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'Record ID',
`name` varchar(255) NOT NULL COMMENT 'User Name',
`email` varchar(255) NOT NULL COMMENT 'User Email Address',
PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
-/*!40101 SET character_set_client = @saved_cs_client */;
-
-/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
-/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
-/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
-/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+) ENGINE = InnoDB
+ DEFAULT CHARSET = utf8mb4;
INSERT INTO `users` (`name`, `email`)
-VALUES ('Phalcon Team', 'team@phalcon.io');
+VALUES ('Sarah Connor', 'sarah.connor@skynet.dev'),
+ ('John Connor', 'john.connor@skynet.dev'),
+ ('Miles Dyson', 'miles.dyson@cyberdyne.dev'),
+ ('Tarissa Dyson', 'tarissa.dyson@cyberdyne.dev');
diff --git a/src/controllers/IndexController.php b/src/Controllers/IndexController.php
similarity index 59%
rename from src/controllers/IndexController.php
rename to src/Controllers/IndexController.php
index af1d3f7..b78f473 100644
--- a/src/controllers/IndexController.php
+++ b/src/Controllers/IndexController.php
@@ -1,13 +1,18 @@
view->users = Users::find();
}
diff --git a/src/controllers/SignupController.php b/src/Controllers/SignupController.php
similarity index 54%
rename from src/controllers/SignupController.php
rename to src/Controllers/SignupController.php
index 31f5e41..dda1c5b 100644
--- a/src/controllers/SignupController.php
+++ b/src/Controllers/SignupController.php
@@ -1,41 +1,43 @@
request->getPost();
- // Store and check for errors
$user = new Users();
$user->name = $post['name'];
$user->email = $post['email'];
- // Store and check for errors
+
$success = $user->save();
- // passing the result to the view
$this->view->success = $success;
if ($success) {
- $message = "Thanks for registering!";
+ $message = 'Thanks for registering!';
} else {
- $message = "Sorry, the following problems were generated:
"
+ $message = 'Sorry, the following problems were generated:
'
. implode('
', $user->getMessages());
}
- // passing a message to the view
$this->view->message = $message;
}
}
diff --git a/src/Models/Users.php b/src/Models/Users.php
new file mode 100644
index 0000000..d929a6e
--- /dev/null
+++ b/src/Models/Users.php
@@ -0,0 +1,19 @@
+set('dispatcher', function () {
+ $dispatcher = new Dispatcher();
+ $dispatcher->setDefaultNamespace('Tutorial\\Controllers');
+
+ return $dispatcher;
+ });
+
+ // Views
+ $container->set('view', function () use ($viewsDir) {
+ $view = new View();
+ $view->setViewsDir($viewsDir);
+
+ return $view;
+ });
+
+ // Base URI
+ $container->set('url', function () {
+ $url = new Url();
+ $url->setBaseUri('/');
+
+ return $url;
+ });
+
+ // Database — reads env vars (set by docker-compose / CI) with local defaults
+ $container->set('db', function () {
+ return new Mysql(
+ [
+ 'host' => getenv('DB_HOST') ?: '127.0.0.1',
+ 'username' => getenv('DB_USERNAME') ?: 'root',
+ 'password' => getenv('DB_PASSWORD') ?: 'secret',
+ 'dbname' => getenv('DB_NAME') ?: 'tutorial',
+ ]
+ );
+ });
+
+ return new Application($container);
+};
diff --git a/src/models/Users.php b/src/models/Users.php
deleted file mode 100644
index 4081bf7..0000000
--- a/src/models/Users.php
+++ /dev/null
@@ -1,10 +0,0 @@
-
Phalcon Tutorial
-
+
diff --git a/tests/Functional/SmokeTest.php b/tests/Functional/SmokeTest.php
new file mode 100644
index 0000000..4e3b171
--- /dev/null
+++ b/tests/Functional/SmokeTest.php
@@ -0,0 +1,39 @@
+dispatch('/');
+
+ $content = $this->getContent();
+
+ $this->assertStringContainsString('Hello', $content);
+ $this->assertStringContainsString('Sarah Connor', $content);
+ }
+
+ public function testSignupPageRenders(): void
+ {
+ $this->dispatch('/signup');
+
+ $content = $this->getContent();
+
+ $this->assertStringContainsString('