diff --git a/.vitepress/data/guides.ts b/.vitepress/data/guides.ts index c5628c89..0aee4827 100644 --- a/.vitepress/data/guides.ts +++ b/.vitepress/data/guides.ts @@ -10,7 +10,11 @@ export const guidesSidebar = computed(() => { { text: 'Installation', link: `/${guideRoutePrefix}/start/` - } + }, + { + text: 'Debugging', + link: `/${guideRoutePrefix}/start/debugging` + }, ] }, { @@ -18,8 +22,12 @@ export const guidesSidebar = computed(() => { items: [ { text: 'Getting Started', - link: `/${guideRoutePrefix}/mvc/` - } + link: `/${guideRoutePrefix}/mvc/getting-started` + }, + { + text: 'Modeling', + link: `/${guideRoutePrefix}/mvc/modeling` + }, ] } ]; diff --git a/documentation/guides/mvc/getting-started.md b/documentation/guides/mvc/getting-started.md new file mode 100644 index 00000000..061a9be0 --- /dev/null +++ b/documentation/guides/mvc/getting-started.md @@ -0,0 +1,207 @@ +--- +layout: doc +--- + +# Getting Started + +## Start a New MVC + +Run + +```shell +php windwalker g view Front/Sakura +``` + +This will create a `src/Front/Sakura/SakuraView` file and a series of files. + +Let's write something into the `prepare()` function. + +```php + + +@extends('global.body') + +@section('content') +

Sakura view

// [!code --] +
// [!code ++] +

{{ $title }}

// [!code ++] +
// [!code ++] +@stop + +``` + +Next, run the following command to create routing. + +```shell +php windwalker g route front/sakura +``` + +Edit the file to add the route settings. + +```php +group('sakura') + ->register(function (RouteCreator $router) { + // Add this // [!code focus] + $router->any('sakura', '/sakura') // [!code focus] + ->view(SakuraView::class); // [!code focus] + }); +``` + +Next, open the following URL in the browser to see the view we create. + +``` +http://localhost:8000/sakura +``` + +![sakura title](https://github.com/lyrasoft/ww4tut/assets/1639206/b6fef366-9f95-4144-a645-bba6881d0e13) + +## Modify CSS Styles + +Next, let's try modifying the assets/_sakura.scss in sakura. Add: + +```scss +// src/Module/Front/Sakura/assets/_sakura.scss + +// Limit to this view only +.view-sakura { + h2 { + color: red; + } +} + +``` + +Next, run + +``` +yarn build css +``` + +After completion, you will see the style take effect. + +![red title](https://github.com/lyrasoft/ww4tut/assets/1639206/93d0d2f7-82f9-449c-8b8a-af398761bef9) + +In Windwalker 4, CSS is distributed in different MVC folders and will be integrated together during fusion compile. + +## Modify JS + +Similar to CSS, JS is also distributed in the MVC folders corresponding to the view name. Let's modify `sakura.ts`. + +```ts +// src/Module/Front/Sakura/assets/sakura.ts + +console.log('Hello Sakura'); + +``` + +Then compile with fusion. + +``` +yarn build js +``` + +Refresh the page and open the browser console to see the result. + +![console](https://github.com/lyrasoft/ww4tut/assets/1639206/bd458e36-1560-4e4d-a513-966a7053f0d2) + +## Page Title + +Simply add this line to add title to browser: + +```php + // ... + + public function prepare(AppContext $app, View $view): array + { + $title = 'Sakura View Title'; + + $view->setTitle($title); // [!code ++] + + return compact('title'); + } +``` + +![title](https://github.com/windwalker-io/framework/assets/1639206/92ca07b3-88ce-4c47-97a5-2c34c3858df8) + +### Use `#[ViewMetadata]` Attribute + +If you want to set more metadata, try use `#[ViewMetadata]` with another method. You amy inject any service or view data into this method through declaring the arguments. + +The `HtmlFrame` is a useful object that help you configure HTML header and body. See [HtmlFrame Service](../../services/html-frame.md) + +```php +use Windwalker\Core\Attributes\ViewMetadata; // [!code ++] +use Windwalker\Core\Html\HtmlFrame; // [!code ++] + + // ... + + public function prepare(AppContext $app, View $view): array + { + $title = 'Sakura View Title'; + + $view->setTitle($title); // [!code --] + // Inject title to view // [!code ++] + $view['title'] = $title; // [!code ++] + + return compact('title'); + } + + #[ViewMetadata] // [!code ++] + public function prepareMetadata(HtmlFrame $htmlFrame, string $title): void // [!code ++] + { // [!code ++] + $htmlFrame->setTitle($title); // [!code ++] + $htmlFrame->setDescription('Sakura Description'); // [!code ++] + } // [!code ++] +``` + +## Debug Mode + +If you need to enter debug mode, such as viewing DB Queries, complete error messages, or want to prevent CSS/JS caching, you can enter debug mode. + +The simplest way is to add /dev.php at the end of the website URL. + +For example: +- The URL: http://localhost/hello/www/sakura/list +- Change to: http://localhost/hello/www/dev.php/sakura/list. + +In this case, we are using PHP server: `http://localhost:8000`, we can simply add `dev.php` after ths host: `http://localhost:8000/dev.php` + +This will enter debug mode. + +![debug console](https://github.com/lyrasoft/ww4tut/assets/1639206/13a93c09-eba2-4d65-80c1-944ccdcc6bf7) + +When an error occurs, it can also display complete error messages. + +![error page](https://github.com/lyrasoft/ww4tut/assets/1639206/3e89efcb-a6b1-4594-85b6-4107632d00ee) + +More details please see [Debugging](../start/debugging.html) diff --git a/documentation/guides/mvc/index.md b/documentation/guides/mvc/index.md deleted file mode 100644 index 581b213b..00000000 --- a/documentation/guides/mvc/index.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -layout: doc ---- - -# Getting Started - -## Start a New MVC - -Run - -``` -php windwalker g view Front/Sakura -``` - -This will create a `src/Front/Sakura/SakuraView` file and a series of files. - -Let's write something into the `prepare()` function. - -```php - - -@extends('global.body') - -@section('content') -
-

{{ $title }}

-
-@stop - -``` - -Next, run the following command to create routing. - -```shell -php windwalker g route front/sakura -``` - -Edit the file to add the route settings. - -```php -group('sakura') - ->register(function (RouteCreator $router) { - // Add this - $router->any('sakura', '/sakura') - ->view(SakuraView::class); - - }); -``` - -Next, open the following URL in the browser to see the view we create. - -``` -http://{site}/www/sakura -``` - -{image} - -## Modify CSS Styles - -Next, let's try modifying the assets/_sakura.scss in sakura. Add: - -```scss -// src/Module/Front/Sakura/assets/_sakura.scss - -// Limit to this view only -.view-sakura { - h2 { - color: red; - } -} - -``` - -Next, run - -``` -yarn build css -``` - -After completion, you will see the style take effect. - -{image} - -In Windwalker 4, CSS is distributed in different MVC folders and will be integrated together during fusion compile. - -## Modify JS - -Similar to CSS, JS is also distributed in the MVC folders corresponding to the view name. Let's modify `sakura.ts`. - -```ts -// src/Module/Front/Sakura/assets/sakura.ts - -console.log('Hello Sakura'); - -``` - -Then compile with fusion. - -``` -yarn build js -``` - -Refresh the page and open the browser console to see the result. - -{image} - -## Debug Mode - -If you need to enter debug mode, such as viewing DB Queries, complete error messages, or want to prevent CSS/JS caching, you can enter debug mode. - -The simplest way is to add /dev.php at the end of the website URL. - -For example: -- The URL: http://localhost/hello/www/sakura/list -- Change to: http://localhost/hello/www/dev.php/sakura/list. - -This will enter debug mode. - -```adf -{"type":"mediaSingle","attrs":{"layout":"center"},"content":[{"type":"media","attrs":{"width":1497,"id":"a82763dc-4800-48b0-a3f6-0728099aff46","collection":"contentId-1455685784","type":"file","height":768}}]} -``` - -When an error occurs, it can also display complete error messages. - -```adf -{"type":"mediaSingle","attrs":{"layout":"center"},"content":[{"type":"media","attrs":{"width":1444,"id":"0195949a-bb89-464a-a05e-4335e51479cc","collection":"contentId-1455685784","type":"file","height":739}}]} -``` - - diff --git a/documentation/guides/mvc/modeling.md b/documentation/guides/mvc/modeling.md new file mode 100644 index 00000000..d79707f1 --- /dev/null +++ b/documentation/guides/mvc/modeling.md @@ -0,0 +1,441 @@ +--- +layout: doc +--- + +# Modeling + +For the actual tutorial process, we will use a blog system as practice. + +To have test data first, we start by following the steps below to create the database structure. + +## Create Entity + +We will first create a basic Article table, starting from Entity. Every table must have a corresponding entity. + +Run: + +```shell +php windwalker g entity Article +``` + +This will create `src/Entity/Article.php`, with content similar to this: + +```php +up( + static function () use ($mig) { + $mig->createTable( + Article::class, + function (Schema $schema) { + $schema->primary('id'); + $schema->integer('category_id'); + $schema->varchar('title'); + $schema->varchar('image'); + $schema->longtext('content'); + $schema->datetime('created'); + $schema->integer('created_by'); + $schema->json('params'); + + $schema->addIndex('category_id'); + $schema->addIndex('created_by'); + } + ); + } +); + +/** + * Migration DOWN. + */ +$mig->down( + static function () use ($mig) { + $mig->dropTable(Article::class); + } +); + + +``` + +We use the `App\Entity\Article::class` as the table name and create some common columns for article. The `down()` function below sets up the downgrade logic to remove this table. + +Next, run the following command to upgrade the migration version and create the table. + +```shell +php windwalker mig:go -f +``` + +If success, will show the following message: + +```shell +Backing up SQL... +SQL backup to: ... + + +Migration start... +================== + +2024060909320001 ArticleInit UP... Success + +``` + +We can run the following command to check the migration status: + +```shell +$ php windwalker mig:status + ++--------+---- Migration Status -------------+ +| Status | Version | Migration Name | ++--------+------------------+----------------+ +| up | 2021061915530001 | AcmeInit | +| up | 2024060909320001 | ArticleInit | ++--------+------------------+----------------+ + +``` + +## Create Entity Properties + +Since all future database auto-mapping will be handled by Entity, we need to set up the Entity first. + +While the table is already created, we can run the following command to generate Entity properties: + +```php +php windwalker build:entity Article +``` + +> [!note] +> If you have set up the auto-completion of console, you may type first some letters and press tab to auto-complete entity name. + +Result: + +```shell +Handling: App\Entity\Article + + Added columns: + - id (id) + - categoryId (category_id) + - title (title) + - image (image) + - content (content) + - created (created) + - createdBy (created_by) + - params (params) + +``` + +The Windwalker will generate the corresponding properties based on the table. Let's open the file and take a look, by default, the auto-generated code may be stuck together and not fit the `PSR-12` or any common code styles, you can re-format it by your IDE before next action. + +```php +import( + static function () use ($seeder, $orm, $db) { + $faker = $seeder->faker('en_US'); + + /** @var EntityMapper
$mapper */ + $mapper = $orm->mapper(Article::class); + + foreach (range(1, 50) as $i) { + $item = $mapper->createEntity(); + $item->setTitle($faker->sentence(2)); + $item->setImage($faker->imageUrl(800, 600)); + $item->setContent($faker->paragraph(40)); + $item->setState(random_int(0, 1)); + $item->setCreatedBy(1); // Currently no User, set to 1 + $item->setCategoryId(1); // Currently no User, set to 1 + $item->setCreated($faker->dateTimeThisYear()); + $item->setImage($faker->imageUrl()); + $item->setParams( + [ + 'show_date' => true, + 'show_author' => false, + ] + ); + + $article = $mapper->createOne($item); + + $seeder->outCounting(); + } + } +); + +$seeder->clear( + static function () use ($seeder, $orm, $db) { + $seeder->truncate(Article::class); + } +); + +``` + +With the help of Entity Methods, we can be reminded of what content needs to be input and can check the input types. + +Among them, `setCreated()` was automatically generated earlier because the setter can accept multiple types. + +```php +public function setCreated(\DateTimeInterface|string|null $created) : static +{ + $this->created = Chronos::tryWrap($created); + return $this; +} +``` + +So it can convert various contents into `Chronos` objects. If needed, you can modify any property or method at any time to perform various type checks or conversions. The ultimate goal is to make database access more convenient and strictly check type issues. + +Now, run again: + +```shell +php windwalker mig:reset -fs + +``` + +to refresh all migrations/seeders. + +You will see: + +```shell +Backing up SQL... +SQL backup to: ... + + +Rollback to 0 version... +======================== + +2024060909320001 ArticleInit DOWN... Success +2021061915530001 AcmeInit DOWN... Success + + +Migrating to latest version... +============================== + +2021061915530001 AcmeInit UP... Success +2024060909320001 ArticleInit UP... Success + + +Seeding... +========== + +Import seeder: Acme Seeder (/acme-seeder.php) + (15) ◒ + Import completed... +Import seeder: Article Seeder (/article-seeder.php) + (50) ◑ + Import completed... + +Completed. +``` diff --git a/documentation/guides/start/debugging.md b/documentation/guides/start/debugging.md new file mode 100644 index 00000000..86eb789c --- /dev/null +++ b/documentation/guides/start/debugging.md @@ -0,0 +1,90 @@ +--- +layout: doc +--- + +# Debugging + +## Enter Debug Mode + +If you need to enter debug mode, such as viewing DB Queries, complete error messages, or want to prevent CSS/JS caching, you can enter debug mode. + +The simplest way is to add /dev.php at the end of the website URL. + +For example: +- The URL: http://localhost/hello/www/sakura/list +- Change to: http://localhost/hello/www/dev.php/sakura/list. + +In this case, we are using PHP server: `http://localhost:8000`, we can simply add `dev.php` after ths host: `http://localhost:8000/dev.php` + +This will enter debug mode. + +![debug console](https://github.com/lyrasoft/ww4tut/assets/1639206/13a93c09-eba2-4d65-80c1-944ccdcc6bf7) + +When an error occurs, it can also display complete error messages. + +![error page](https://github.com/lyrasoft/ww4tut/assets/1639206/3e89efcb-a6b1-4594-85b6-4107632d00ee) + +### Force Debug Mode + +Add `APP_DEBUG=1` to `.env` file to force enable debug mode without accessing `dev.php`. + +## Web Profiler + +Click the debug console at the bottom of page. You will enter the Windwalker Debugger interface. + +![system](https://github.com/lyrasoft/ww4tut/assets/1639206/d3d03b2b-17f6-4053-95a2-eb1531692ea3) + +You can see many profiler data which is collected from Windwalker process, to help you debug or inspect system issues. If you want to see the data from previous actions, go to `Dashboard` and choose the page data you want. + +![dashboard](https://github.com/lyrasoft/ww4tut/assets/1639206/d18f00cc-da6f-4a5d-b1b3-01800bf3dfac) + +## Debugger Configuration + +### THe Core Debugger + +Open `etc/packages/debugger.php` to configure debug system, this debug system is provided by `windwalker/core` package. + +#### `profiler_disabled` + +Set to `true` to force disable debug profiler. + +#### `cache.max_files` + +To configure how many collected profiler data caches at this project, default is `100`. + +### The Whoops + +Windwalker use [flip/whoops](https://github.com/filp/whoops) package to render error page. You can configure whoops through `etc/conf/whoops.php`: + +#### `editor` + +To configure the editor/IDE software that can open file when you click the file path in error page, you can simply add `WHOOPS_EDITOR` to `.env` to override this config. + +![editor](https://github.com/lyrasoft/ww4tut/assets/1639206/b3a91c40-2d4e-4874-b169-1ccdcf3c477a) + +Default is `phpstorm`, you may change it to `vscode` or any editor which supports open by `{editor}://` URL scheme. + +#### `hidden_list` + +Whoops will display some sensitive data from your `$_SERVER` super global variables. This config provides a list to hide these sensitive data. + +```php + // ... + + 'hidden_list' => [ + '_ENV' => array_keys($_ENV ?? []), + '_SERVER' => array_merge( + [ + 'PATH', + 'SERVER_SOFTWARE', + 'DOCUMENT_ROOT', + 'CONTEXT_DOCUMENT_ROOT', + 'SERVER_ADMIN', + 'SCRIPT_FILENAME', + 'REMOTE_PORT', + ], + array_keys($_ENV ?? []) + ) + ], +``` + diff --git a/documentation/guides/start/index.md b/documentation/guides/start/index.md index 02129048..3f9dffd3 100644 --- a/documentation/guides/start/index.md +++ b/documentation/guides/start/index.md @@ -74,6 +74,13 @@ php windwalker server:start Then open `http://localhost:8000` to see the homepage. +![home](https://github.com/lyrasoft/ww4tut/assets/1639206/2134e4b7-6caa-41b0-ac2b-cc69f3944b0e) + +Go to: `http://localhost:8000/admin` to see a simple fake dashboard. + +![dashboard](https://github.com/lyrasoft/ww4tut/assets/1639206/9ad6fa6a-8466-4332-b34e-aeab916e45e7) + + ### Install Default Database Files If you want to use database, please install `windwalker/database` and `windwalker/orm` first: @@ -126,7 +133,7 @@ Import seeder: Acme Seeder (/acme-seeder.php) Open the project URL `http://{site}/www/admin/acme`, and if you see the following list, it means success. -{image} +![acme](https://github.com/lyrasoft/ww4tut/assets/1639206/60bd49ec-454d-44b3-ae35-6554d318807e) ## Directory Structures diff --git a/documentation/services/html-frame.md b/documentation/services/html-frame.md new file mode 100644 index 00000000..e6e9651f --- /dev/null +++ b/documentation/services/html-frame.md @@ -0,0 +1,7 @@ +--- +layout: doc +--- + +# HtmlFrame + +