Tobias Helbich
Tobias Helbich

Reputation: 457

TYPO3 9.2.1 Create ViewHelper in Composer Mode

I'm trying to create a ViewHelper with a TYPO3 which was installed in composer mode and a site package which was generated with the sitepackagebuilder.

The autoloading should be configured correctly, nevertheless the only thing I'm getting is an error message, that the ViewHelper cannot be found:

#1407060572: Fluid parse error in template Standard_action_Default_9cc8c1fca58b49310db5d43052e614cefdb1c728, line 5 at character 6. Error: The ViewHelper "<foobar:some>" could not be resolved. Based on your spelling, the system would load the class "Foo\Bar\ViewHelpers\SomeViewHelper", however this class does not exist. (error code 1407060572). Template source chunk: <foobar:some /> (More information)

TYPO3Fluid\Fluid\Core\Parser\Exception thrown in file
/var/www/html/vendor/typo3fluid/fluid/src/Core/Parser/TemplateParser.php in line 157.

Steps To Reproduce

  1. install TYPO3 in composer mode (newest version 9.2.1)
  2. create a site package with https://sitepackagebuilder.com - simple configuration, 'foo' as company name and 'bar' as extension key (see screenshot below)
  3. create a simple class SomeViewHelper under Classes/ViewHelpers/
  4. modify the template under Page/Default to contain the SomeViewHelper (following the example from docs.typo3.org)

    {namespace foobar=Foo\Bar\ViewHelpers} <foobar:some />

  5. create a new root page in TYPO3 with simple content and include the bar extension (Template > Includes)

The autoloading of the code should be handled by the composer.json/ext_emconf.php files which are generated by the sitepackagebuilder.

Screenshot

site package builder configuration

Code

SomeViewHelper.php

<?php
namespace Foo\Bar\ViewHelpers;


use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;

class SomeViewHelper extends AbstractViewHelper
{
    public function render() {
        return 'Hello World';
    }
}

Page/Default.html

<f:layout name="Default" />
<f:section name="Main">

    {namespace foobar=Foo\Bar\ViewHelpers}
    <foobar:some />

    <f:cObject typoscriptObjectPath="lib.dynamicContent" data="{colPos: '0'}" />

</f:section>

also declaring the namespace at the top of the document did not help

<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
      xmlns:foobar="http://typo3.org/ns/Foo/Bar/ViewHelpers">
<f:layout name="Default" />
<f:section name="Main">

    <foobar:some />

    <f:cObject typoscriptObjectPath="lib.dynamicContent" data="{colPos: '0'}" />

</f:section>
</html>

composer.json

{
    "name": "foo/bar",
    "type": "typo3-cms-extension",
    "description": "",
    "homepage": "https://www.foo.com",
    "license": ["GPL-2.0-or-later"],
    "keywords": ["TYPO3 CMS"],
    "version": "1.0.0",
    "require": {
        "typo3/cms-core": "^8.7 || ^9.0",
        "typo3/cms-rte-ckeditor": "^8.7 || ^9.0",
        "typo3/cms-fluid-styled-content": "^8.7 || ^9.0"
    },
    "autoload": {
        "psr-4": {
            "Foo\\Bar\\": "Classes/"
        }
    }
}

ext_emconf.php

<?php

/**
 * Extension Manager/Repository config file for ext "bar".
 */
$EM_CONF[$_EXTKEY] = [
    'title' => 'Bar',
    'description' => '',
    'category' => 'templates',
    'constraints' => [
        'depends' => [
            'typo3' => '8.7.0-9.5.99',
            'fluid_styled_content' => '8.7.0-9.5.99',
            'rte_ckeditor' => '8.7.0-9.5.99'
        ],
        'conflicts' => [
        ],
    ],
    'autoload' => [
        'psr-4' => [
            'Foo\\Bar\\' => 'Classes'
        ],
    ],
    'state' => 'stable',
    'uploadfolder' => 0,
    'createDirs' => '',
    'clearCacheOnLoad' => 1,
    'author' => 'John Doe',
    'author_email' => '[email protected]',
    'author_company' => 'foo',
    'version' => '1.0.0',
];

Upvotes: 1

Views: 1520

Answers (4)

Robert Wildling
Robert Wildling

Reputation: 1186

My answer concerns TYPO3 9.5.+ (composer mode): Extensions that are not installed via composer (like a sitepackage) are not recognised. Therefore a local repo should be created and added to composer-json. Here is what I did:

  1. In the root directory I created a folder "packages"

  2. I moved my sitepackage extension into that folder ("packages/my-sitepackage")

  3. In the root-composer.json (the one which setup TYPO3), I added a "path" repository to my existing ones:

    "repositories": [ { "type": "composer", "url": "https://composer.typo3.org/" }, { "type": "vcs", "url": "[some path to github or bitbucket]" }, { "type": "path", "url": "packages/my-sitepackage", "options": { "symlink": true } } ], [...]

(Instead of "packages/my-sitepackage" it should also be possible to use "packages/*"; and symlink could be set to false, too.)

  1. Eventually, the extension is required like this:

    "require": { "my-sitepackage": "@dev" }

The composer docu lists examples using "*", but in my case i had to use "@dev" to make it work.

Some links that helped me:

Hope that helps those, who come a little later to the game then the question was asked. :-)

Upvotes: 0

Sybille Peters
Sybille Peters

Reputation: 3230

Your site is installed with Composer as stated in the question.

There are basically 2 ways to make an extension available via Composer (there are more but we simplify here):

  1. Installed it with Composer from a remote source (such as Packagist), e.g. like composer require myvendor/myextension? This way the autoloading should work. You can also do composer dump-autoload at any point.
  2. Do not require the extension but configure the autoloading directly.

I assume you want the latter for your sitepackage. You do not wish to install your sitepackage via Composer from a source such as Packagist on your development machine, because you are currently developing it.

For the autoloading to work, you can add the following to your composer.json file (replace myvendor, myextension):

"autoload": {
    "psr-4": {
        "Myvendor\\Myextension\\": "typo3/sysext/myextension/Classes/",
        ...
    }
} 

Do not do this for all your extensions, just the ones you do not want to install via Composer!

After you added the autoload configuration, you should run

composer dumpautoload

See

Upvotes: 0

Tobias Helbich
Tobias Helbich

Reputation: 457

Assuming that you started with the sitepackagegenerator provided by Benjamin Kott and installed Typo3 in composer mode the following happens:


The sitepackage's TypoScript part is configured via the Typo3 backend so the loading of the TypoScript as well as templates is independent of the php autoloading.

The autoload configuration specified under public/typo3conf/ext/<extension> in composer.json and ext_emconf.php is ignored by composer because composer does not know about these extensions, but composer will still show your extension in the list of extensions:

The following extensions have been added to the generated PackageStates.php file: core, extbase, fluid, frontend, fluid_styled_content, install, setup, rte_ckeditor, about, adminpanel, backend, belog, beuser, documentation, extensionmanager, felogin, filelist, form, impexp, info, recordlist, redirects, reports, saltedpasswords, scheduler, sys_note, t3editor, tstemplate, viewpage, <extension>

Even if the autoloading is configured correctly composer cannot show any informatiom about your extension:

composer info foo/bar

  [InvalidArgumentException]  
  Package foo/bar not found   

So while this is confusing all you have to do is include individual extensions like sitepackages (add the following to the end of your root composer.json - where you also specified things like "require": { "typo3/minimal": "^9.3" }):

,
"autoload": {
  "psr-4": {
    "Foo\\Bar\\": "public/typo3conf/ext/<extension>/Classes/"
  }
}

After that the example posted in the question should work as expected and the result of <foobar:some /> should be Hello World.

<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
      xmlns:foobar="http://typo3.org/ns/Foo/Bar/ViewHelpers">
<f:layout name="Default" />
<f:section name="Main">

    <foobar:some />

    <f:cObject typoscriptObjectPath="lib.dynamicContent" data="{colPos: '0'}" />

</f:section>
</html>

Upvotes: 0

David
David

Reputation: 6084

Classes are recognized by the autoloader. If you create a new class you've to refresh the autoloading information by deleting the autoload information.
This information can be deleted with the installtool or manually by removing all files in the folder typo3conf/autoload.
Autoload information for TYPO3 will be created new then.

Edit:
Depending on the version the autoload-directory might be in typo3temp which seems being the case here. Sorry for confusion.

It's probably advisable and perhaps even required to include the viewHelper in the template- or layout-file in the top of the file. That's at least what I saw in all fluid-templates I opened. I never saw yet that a viewhelper is included inside the template.

Upvotes: 1

Related Questions