Laminas skeleton 101

This project aims to be a standard method of deliver php programmed artefacts.

Programming best practices

Laminas project

Create and setup

podman run -it --rm --entrypoint=bash -w /workspace -v `pwd`:/workspace:z \
  docker.io/bitnami/php-fpm:8.0.25 \
   -c 'composer create-project -s stable laminas/laminas-mvc-skeleton'

mv laminas-mvc-skeleton/public . 
mv laminas-mvc-skeleton app
sed -i public/index.php -e 's#^chdir.*#chdir(dirname(__DIR__,1)."/app");#' \
  -e 's#/../vendor/autoload.php#/../app/vendor/autoload.php#'
mv public/index.php public/ini.php
# remove cache
sed -i  app/config/application.config.php \
  -e "s/'config_cache_enabled'.*/'config_cache_enabled' => false,/"

# dont push ide files
cat > .gitignore << 'eof'
nbproject
.idea
eof

Composer

# composer install ( usa el composer.lock )
# composer update (actualiza las versiones de acuerdo a lo que el composer.json tiene >= )
https://getcomposer.org/doc/03-cli.md#install-i vs
https://getcomposer.org/doc/03-cli.md#update-u-upgrade

# new dependency:
# composer require <library>/<dependencia>


app/module/Application/config/module.config.php
-- rest vs action controllers

Routes 101

index 83d619b..5381f11 100644
--- app/module/Application/config/module.config.php
+++ app/module/Application/config/module.config.php
@@ -11,20 +11,46 @@ use Laminas\ServiceManager\Factory\InvokableFactory;
 return [
     'router' => [
         'routes' => [
-            'home' => [
-                'type'    => Literal::class,
-                'options' => [
-                    'route'    => '/',
-                    'defaults' => [
-                        'controller' => Controller\IndexController::class,
+            /* parent route*/
+            'v1-routes' => [
+              'type' => Segment::class,
+              'options' => [
+                'route' => '/v1',
+                'defaults' => [
+                  /* always use triling commas */
+                  'controller' => Controller\IndexController::class,
+                ],
+              ],
+              'may_terminate' => true,
+              /**/
+              'child_routes' => [
+                'documentation' => [
+                  'type'    => Literal::class,
+                  'options' => [
+                      'route'    => '/documentation',
+                      'defaults' => [
+                        'controller' => Controller\DocumentationController::class,
                         'action'     => 'index',
+                      ],
+                  ],
+                ],
+                'documentation-yaml' => [
+                  'type'    => Literal::class,
+                  'options' => [
+                    'route'    => '/documentation-yaml',
+                    'defaults' => [
+                      'controller' => Controller\DocumentationYamlController::class,
+                      'action'     => 'index',
                     ],
+                  ],
                 ],
+              ],
+              /**/
             ],
-            'application' => [
-                'type'    => Segment::class,
+            'home' => [
+                'type'    => Literal::class,
                 'options' => [
-                    'route'    => '/application[/:action]',
+                    'route'    => '/',
                     'defaults' => [
                         'controller' => Controller\IndexController::class,
                         'action'     => 'index',
patch -Nau app/module/Application/config/module.config.php < patch 
rm -f patch

mkdir module/Application/Controller/Documentation
# add Controllers and Factories () 
Add controller and Factory to module.config.php

Controllers 101

app/module/Application/src/Controller/

ActionController

class IndexController extends AbstractActionController
    public function indexAction() // Action suffix

RestfulController

class IndexController extends AbstractRestfulController
    // GET
    public function getList() 
    public function get(id)
    // POST
    public function create()
    // DELETE
    public function delete()
    // PUT
    public function update()
class ClassNameController extends AbstractRestfulController
class ClassNameController extends AbstractActionController

Views and Layouts 101

Template

// setTemplate starts at app/view
$view_model->setTemplate('application/documentation/openapi-reader.phtml');
$view_model->setVariables(array(
   'urlYaml' => $this->url()->fromRoute('v1-routes/documentation-yaml'),
   'title' => $this->local_config['docs']['title'],
   ),
);

Layout

app/module/Application/config/module.config.php

'view_manager' => [
    'template_map' => [
        'layout/bare'             => __DIR__ . '/../view/layout/bare.phtml',
 public function xxxxxxAction(): ViewModel
 {
      // ...
      $this->layout('layout/bare');
      // ...

Config object

composer require laminas/laminas-config

app/config/autoload/local.php

return [
    'docs' => [
        'title' => 'Open API Example',
    ],
];
$this->local_config = new Laminas\Config\Config($local_config);
$host = $config->docs->get('title', 'localhost');