Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

False errors through example code in IDEs like Eclipse #61

Closed
rarog opened this issue Sep 24, 2023 · 3 comments
Closed

False errors through example code in IDEs like Eclipse #61

rarog opened this issue Sep 24, 2023 · 3 comments
Labels
Bug Something isn't working

Comments

@rarog
Copy link
Contributor

rarog commented Sep 24, 2023

Bug Report

It's not a bug per se, but working with IDEs like Eclipse seems to produce false positive errors, because it tries to resolve the class while it doesn't exist and is declared inline. as offered as example here: https://docs.laminas.dev/tutorials/getting-started/database-and-models/#using-servicemanager-to-configure-the-table-gateway-and-inject-into-the-albumtable

The class Album\Model\AlbumTableGateway is never declared anywhere in the code tree and while it's valid PHP code (https://www.php.net/manual/en/language.oop5.basic.php - "Example #16 Missing class name resolution") and it will compile and AlbumTableGateway is only referenced in the factory array, it leads to IDEs showing errors, as it's obviously not an existing class and just works without errors due to PHP implementation.

Wouldn't it be better to avoid this behaviour by using a string like 'Album\Model\AlbumTableGateway' and not piggyback the behaviour as obviously the factory could be referenced with any string and a string wouldn't lead to errors in class resolution.

Or to avoid reusage of strings and making refactoring easier doing something like this?

namespace Album;

// Add these import statements:
use Laminas\Db\Adapter\AdapterInterface;
use Laminas\Db\ResultSet\ResultSet;
use Laminas\Db\TableGateway\TableGateway;
use Laminas\ModuleManager\Feature\ConfigProviderInterface;

class Module implements ConfigProviderInterface
{
    // getConfig() method is here

    // Add this constant:
    private const ALBUM_TABLE_GATEWAY =  'Album\Model\AlbumTableGateway';

    // Add this method:
    public function getServiceConfig()
    {
        return [
            'factories' => [
                Model\AlbumTable::class => function($container) {
                    $tableGateway = $container->get(self::ALBUM_TABLE_GATEWAY);
                    return new Model\AlbumTable($tableGateway);
                },
                self::ALBUM_TABLE_GATEWAY => function ($container) {
                    $dbAdapter = $container->get(AdapterInterface::class);
                    $resultSetPrototype = new ResultSet();
                    $resultSetPrototype->setArrayObjectPrototype(new Model\Album());
                    return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
                },
            ],
        ];
    }
}
`
@rarog rarog added the Bug Something isn't working label Sep 24, 2023
@froschdesign
Copy link
Member

Wouldn't it be better to avoid this behaviour by using a string like 'Album\Model\AlbumTableGateway' and not piggyback the behaviour as obviously the factory could be referenced with any string and a string wouldn't lead to errors in class resolution.

It is better to avoid the whole construct and leave this out of the configuration completely. This is planned in the next revision of the tutorial.

@rarog
Copy link
Contributor Author

rarog commented Sep 26, 2023

@froschdesign Just asking what the way to go will be? A normal factory like this?

<?php

namespace Album\Factory\Model;

use Album\Model\Album;
use Album\Model\AlbumTable;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Laminas\Db\Adapter\AdapterInterface;
use Laminas\Db\ResultSet\ResultSet;
use Laminas\Db\TableGateway\TableGateway;

class AlbumTableFactory implements FactoryInterface
{
    /**
     * {@inheritDoc}
     * @see \Laminas\ServiceManager\Factory\FactoryInterface::__invoke()
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $dbAdapter = $container->get(AdapterInterface::class);
        $resultSetPrototype = new ResultSet();
        $resultSetPrototype->setArrayObjectPrototype(new Album());
        $tableGateway = new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
        return new AlbumTable($tableGateway);
    }
}

`

@froschdesign
Copy link
Member

@rarog

A normal factory like this?

For example but you can simplify the factory because there is no need to use the factory interface:

use Album\Model\AlbumTable;
use Psr\Container\ContainerInterface;

final class OrdersControllerListenerFactory
{
    public function __invoke(ContainerInterface $container): AlbumTable
    {
        // …
    }
}

But the laminas-db is not very helpful and feature-complete therefore I would avoid it. See also: #41

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants