I am creating an extension to list job offers, and when I try to see the view, I have this error message :
The default controller for extension "Offerjob" and plugin "JobList" can not be determined. Please check for
TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin() in your ext_localconf.php.
I checked the namespaces of all my files, I tried some solutions and I can't resolve my issue, someone have an idea ?
let check my files :
ext/offerjob/Classes/Controller/OfferjobController.php
namespace Vendor\Offerjob\Controller;
use Vendor\Offerjob\Domain\Repository\JobRepository;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
/**
* Class OfferjobController
*
* #package Vendor\Offerjob\Controller
*/
class OfferjobController extends ActionController
{
/**
* #var JobRepository
*/
private $jobRepository;
/**
* Inject the job repository
*
* #param \Vendor\Offerjob\Domain\Repository\JobRepository $jobRepository
*/
public function injectJobRepository(JobRepository $jobRepository)
{
$this->jobRepository = $jobRepository;
}
/**
* List Action
*
* #return void
*/
public function listAction()
{
$jobs = $this->jobRepository->findAll();
$this->view->assign('jobs', $jobs);
}
}
public/typo3conf/ext/offerjob/ext_localconf.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'Vendor.Offerjob',
'JobList',
[
\Vendor\Offerjob\Controller\OfferjobController::class => 'list',
],
// non-cacheable actions
[
\Vendor\Offerjob\Controller\OfferjobController::class => '',
]
);
public/typo3conf/ext/offerjob/Configuration/TCA/Overrides/tt_content.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
'Vendor.Offerjob',
'JobList',
'Job list',
'EXT:offerjob/Resources/Public/Icons/Extension.svg'
);
Is all the naming of plugins, namespace right? Is there something I'm doing wrong?
I'm Using TYPO3 10.4.21 and I followed this tutorial to make my extension : https://docs.typo3.org/m/typo3/book-extbasefluid/10.4/en-us/4-FirstExtension/2-create-folder-structure-and-configuration-files.html
Remove the vendor part of the extension name as this is deprecated in v10 and will be removed in v11:
Vendor.Offerjob => Offerjob
Documentation: https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/10.1/Deprecation-88995-CallingRegisterPluginWithVendorName.html
Related
I have a problem when using CLI command In codeigniter 4. I want to call or execute controller from CLI codeigniter 4.
I have a controller file and folder structure :
Edit :
mywebapp\app\Controllers\ExportAlert.php
And this is the Code inside ExportAlert.php :
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
class ExportAlert extends Controller
{
function __construct()
{
}
public function index()
{
}
public function ExportAlert() {
if ($this->request->isCLI()) {
echo "Ok"; }
else {
echo "Not allowed";
}
}
}
And My Folder Structure :
I try to execute the CLI command :
E:\Codeigniter4\mywebapp>php public/index.php ExportAlert ExportAlert
And it return :
ERROR: 404 Controller or its method is not found: ExportAlert::ExportAlert
What I have missing in here ? How is the correct way to use CLI command to call a controller in codeigniter 4 ?
Thank You
first:
remove index.php in url
go to app/config/app.php
public $indexPage = '';
second:
app/confi/authload.php
call you modules like me
<?php
namespace Config;
use CodeIgniter\Config\AutoloadConfig;
/**
* -------------------------------------------------------------------
* AUTOLOADER CONFIGURATION
* -------------------------------------------------------------------
*
* This file defines the namespaces and class maps so the Autoloader
* can find the files as needed.
*
* NOTE: If you use an identical key in $psr4 or $classmap, then
* the values in this file will overwrite the framework's values.
*/
class Autoload extends AutoloadConfig
{
/**
* -------------------------------------------------------------------
* Namespaces
* -------------------------------------------------------------------
* This maps the locations of any namespaces in your application to
* their location on the file system. These are used by the autoloader
* to locate files the first time they have been instantiated.
*
* The '/app' and '/system' directories are already mapped for you.
* you may change the name of the 'App' namespace if you wish,
* but this should be done prior to creating any namespaced classes,
* else you will need to modify all of those classes for this to work.
*
* Prototype:
*```
* $psr4 = [
* 'CodeIgniter' => SYSTEMPATH,
* 'App' => APPPATH
* ];
*```
* #var array<string, string>
*/
public $psr4 = [
APP_NAMESPACE => APPPATH, // For custom app namespace
'Config' => APPPATH . 'Config',
'Modules\Shared' => ROOTPATH . 'module/shared',
'Modules\Common' => ROOTPATH . 'module/common',
'Modules\Auth' => ROOTPATH . 'module/auth',
'Modules\Home' => ROOTPATH . 'module/home',
'Modules\Payment' => ROOTPATH . 'module/payment',
];
/**
* -------------------------------------------------------------------
* Class Map
* -------------------------------------------------------------------
* The class map provides a map of class names and their exact
* location on the drive. Classes loaded in this manner will have
* slightly faster performance because they will not have to be
* searched for within one or more directories as they would if they
* were being autoloaded through a namespace.
*
* Prototype:
*```
* $classmap = [
* 'MyClass' => '/path/to/class/file.php'
* ];
*```
* #var array<string, string>
*/
public $classmap = [];
/**
* -------------------------------------------------------------------
* Files
* -------------------------------------------------------------------
* The files array provides a list of paths to __non-class__ files
* that will be autoloaded. This can be useful for bootstrap operations
* or for loading functions.
*
* Prototype:
* ```
* $files = [
* '/path/to/my/file.php',
* ];
* ```
* #var array<int, string>
*/
public $files = [];
}
There are few changes you need to make here:
First, it extends to Controller and Not BaseController.
So replace BaseController use statement with use CodeIgniter\Controller;
Second, you do not need routes defined for this. So remove them.
php index.php ExportAlert ExportAlert
should be
php public/index.php ExportAlert ExportAlert
Also, you haven't defined anything in the body so for testing try to enter some data on CLI using CLI's write method.
could you help me with a problem that I have? I have created a command with php artisan make:command to generate repository type classes from existing models. The problem is that I need that instead of generating a single file from a stub, I need to generate 2 or more files. I can't find documentation regarding the subject. Currently what I have achieved is that I only generate a single file from a template.
<?php
namespace App\Console\Commands;
use Illuminate\Console\GeneratorCommand;
use Symfony\Component\Console\Input\InputArgument;
class MakeRepository extends GeneratorCommand
{
/**
* The console command name.
*
* #var string
*/
protected $name = 'make:repository';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Create a new repository';
/**
* The type of class being generated.
*
* #var string
*/
protected $type = 'Repository';
/**
* #inheritDoc
*/
protected function getStub()
{
return __DIR__ . '/stubs/MakeRepository/ModelRepositoryInterface.stub';
}
/**
* Get the console command arguments.
*
* #return array
*/
protected function getArguments()
{
return [
['name', InputArgument::REQUIRED, 'The name of the model to which the repository will be generated'],
];
}
/**
* Get the default namespace for the class.
*
* #param string $rootNamespace
* #return string
*/
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\Repositories';
}
}
EDIT #1
I have 2 stub files inside the directory:
app/Console/Commands/stubs/MakeRepository
ModelRepository.stub
ModelRepositoryInterface.stub
I want that when you execute the command...ex: php artisan make:repository Blog, these 2 files are created in the following directory:
/app/Repositories/Blog/BlogRepository.php
/app/Repositories/Blog/BlogRepositoryInterface.php
You can write a new command to create repository interface, and then call it in MakeRepository.
I think this method is in line with SRP.
// In MakeRepository.php
// Override handle method
public function handle()
{
if (parent::handle() === false && ! $this->option('force')) {
return false;
}
if ($this->option('interface')) {
$this->call('make:repository-interface', ['name' => $this->getNameInput() . 'Interface']);
}
}
/**
* Get the console command arguments.
*
* #return array
*/
protected function getArguments()
{
return [
['name', InputArgument::REQUIRED, 'The name of the model to which the repository will be generated'],
['interface', 'i', InputOption::VALUE_NONE, 'Create a new interface for the repository'],
];
}
You can also refer to the code of make model of official.
https://github.com/laravel/framework/blob/6.x/src/Illuminate/Foundation/Console/ModelMakeCommand.php
you can use glob to get your stubs in array then loop over them to create the multiple files
foreach(glob(stubs_path('stubs/Repository/*.stub') as $stub){
copy(stubs_path('stubs/Repository/'.$stub), $repositoryLocation . 'Repository.php');
}
I'm using Typo3 9.5.5 and I extended the extension tx_news with some custom fields.
Everything works fine in front-end and back-end, but sometimes the custom content disappears in front-end and is not shown. Also the debug doesn't show the content. In my opinion it could be a caching problem, because after clearing the complete cache, the custom content is shown again.
How can I fix this issue?
I tried to put the needed templates into my custom extension, but the result is the same.
<?php
namespace myName\NewsExtend\Domain\Model;
/**
* News model for default news
*
* #package TYPO3
* #subpackage tx_news
*/
class NewsExtend extends \GeorgRinger\News\Domain\Model\News {
/**
* #var string
*/
protected $categoryHeader;
/**
* #var string
*/
protected $issue;
/**
* Get categoryHeader
*
* #return string
*/
public function getCategoryHeader()
{
return $this->categoryHeader;
}
/**
* Set categoryHeader
*
* #param string $categoryHeader categoryHeader
*/
public function setCategoryHeader($categoryHeader)
{
$this->categoryHeader = $categoryHeader;
}
/**
* Get issue
*
* #return string
*/
public function getIssue()
{
return $this->issue;
}
/**
* Set issue
*
* #param string $issue issue
*/
public function setIssue($issue)
{
$this->issue = $issue;
}
}
Complete Tutorial to extend TYPO3 tx_news with new fields:
TypoScript Setup
plugin.tx_news {
persistence {
classes {
GeorgRinger\News\Domain\Model\News {
subclasses {
0 = Yourvendor\Yourext\Domain\Model\NewsDefault
}
}
Yourvendor\\Domain\Model\NewsDefault {
mapping {
tableName = tx_news_domain_model_news
recordType = 0
}
}
}
}
}
ext_tables.sql
CREATE TABLE tx_news_domain_model_news (
new_field varchar(255) DEFAULT '' NOT NULL
);
TCA - typo3conf/ext/yourext/Configuration/TCA/Overrides/tx_news_domain_model_news.php
defined('TYPO3_MODE') or die();
/**
* Add new fields to news table
*/
$tmpNewsColumns = [
'new_field' => [
'exclude' => 1,
'label' => 'label or use localang file',
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim'
],
],
];
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('tx_news_domain_model_news', $tmpNewsColumns, true);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('tx_news_domain_model_news', 'new_field', '', 'after:teaser');
Add model - typo3conf/ext/yourext/Classes/Domain/Model/NewsDefault.php
namespace Yourvendor\Yourext\Domain\Model;
use GeorgRinger\News\Domain\Model\NewsDefault as NewsFields;
class NewsDefault extends NewsFields {
/**
* the new_field
* #var string
*/
protected $newField;
/**
* Returns an array of orderings created from a given demand object.
*
* #param string $newField
* #return void
*/
public function setNewField($newField) {
$this->newField = $newField;
}
/**
* Get newField
*
* #return string
*/
public function getNewField() {
return $this->newField;
}
}
Locate and use new fields in template, to check <f:debug>{newsItem}</f:debug> in typo3conf/ext/yourext/Resources/Private/Extensions/News/Partials/List/Item.html
Do you sometimes clear typo3temp which would trigger that as well
I've ran into the same issue. I used the implementation from the linked documentation entry "ProxyClass generator" and when I return to the page after some hours or so the subtitle didn't get rendered anymore. Only a system cache clear brings it back.
A little bit late, but my problem was inside the Typoscript Setup. One tutorial described that it has to be:
config.tx_extbase {
persistence {
classes {
GeorgRinger\News\Domain\Model\News {
....
}
}
}
but it must be "plugin.tx_news" not "config.tx_extbase":
plugin.tx_news {
...
}
I have a problem. I use a RequestBehavior.php (a modified AccessBehavior.php created by Artem Voitko) created in common\components, but I don't know how to redirect guests to frontend/web/index.php?r=site%2Flogin.
This is the code for RequestBehavior.php:
<?php
/*
* In configuration file
* ...
* 'as AccessBehavior' => [
* 'class' => '\app\components\AccessBehavior'
* ]
* ...
* (c) Artem Voitko <r3verser#gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace common\components;
use yii\base\Behavior;
use yii\console\Controller;
use yii\helpers\Url;
use yii\web\Application;
/**
* Redirects all users to login page if not logged in
*
* Class AccessBehavior
* #package app\components
* #author Artem Voitko <r3verser#gmail.com>
*/
class RequestBehavior extends Behavior
{
/**
* Subscribe for events
* #return array
*/
public function events()
{
return [
Application::EVENT_BEFORE_REQUEST => 'beforeRequest'
];
}
/**
* On event callback
*/
public function beforeRequest()
{
if (\Yii::$app->getUser()->isGuest &&
\Yii::$app->getRequest()->url !== Url::to(\Yii::$app->getUser()->loginUrl)
) {
\Yii::$app->getResponse()->redirect(\Yii::$app->getUser()->loginUrl);
}
}
}
?>
And using it, shows this error:
Unable to resolve the relative route: site/login. No active controller is available.
I tried using beforeAccess, but I need to redirect before a request. I need help, please.
So I am not sure what the issue is here, or how this class even gets loaded. But my model (or as their actually called, entity) looks like this:
<?php
namespace ImageUploader\Models;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* #ORM\Entity
* #ORM\Table(name="users")
* #UniqueEntity(fields="userName")
* #UniqueEntity(fields="email")
*/
class User {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/**
* #ORM\Column(type="string", length=32, nullable=false)
* #Assert\NotBlank()
*/
protected $firstName;
/**
* #ORM\Column(type="string", length=32, nullable=false)
* #Assert\NotBlank()
*/
protected $lastName;
/**
* #ORM\Column(type="string", length=100, unique=true, nullable=false)
* #Assert\NotBlank(
* message = "Username cannot be blank"
* )
*/
protected $userName;
/**
* #ORM\Column(type="string", length=100, unique=true, nullable=false)
* #Assert\NotBlank()
* #Assert\Email(
* message = "The email you entered is invalid.",
* checkMX = true
* )
*/
protected $email;
/**
* #ORM\Column(type="string", length=500, nullable=false)
* #Assert\NotBlank(
* message = "The password field cannot be empty."
* )
*/
protected $password;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
protected $created_at;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
protected $updated_at;
}
In my I have an action called createAction that gets called when a user attempts to sign up. It looks like this:
public static function createAction($params){
$postParams = $params->request()->post();
if ($postParams['password'] !== $postParams['repassword']) {
$flash = new Flash();
$flash->createFlash('error', 'Your passwords do not match.');
$params->redirect('/signup/error');
}
$user = new User();
$user->setFirstName($postParams['firstname'])
->setLastName($postParams['lastname'])
->setUserName($postParams['username'])
->setEmail($postParams['email'])
->setPassword($postParams['password'])
->setCreatedAtTimeStamp();
$validator = Validator::createValidatorBuilder();
$validator->enableAnnotationMapping();
$errors = $validator->getValidator()->validate($user);
var_dump($errors);
}
When this action is called I get the following error:
Fatal error: Class 'doctrine.orm.validator.unique' not found in /var/www/html/image_upload_app/vendor/symfony/validator/ConstraintValidatorFactory.php on line 47
I am not sure how to resolve this issue. My composer file is as such:
{
"require": {
"doctrine/orm": "2.4.*",
"doctrine/migrations": "1.0.*#dev",
"symfony/validator": "2.8.*#dev",
"symfony/doctrine-bridge": "2.8.*#dev",
"slim/slim": "~2.6",
"freya/freya-exception": "0.0.7",
"freya/freya-loader": "0.2.2",
"freya/freya-templates": "0.1.2",
"freya/freya-factory": "0.0.8",
"freya/freya-flash": "0.0.1"
},
"autoload": {
"psr-4": {"": ""}
}
}
So I am not sure if I am missing a package or if I am doing something wrong ....
My bootstrap.php file has the following contents in it:
require_once 'vendor/autoload.php';
$loader = require 'vendor/autoload.php';
\Doctrine\Common\Annotations\AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
/**
* Set up Doctrine.
*/
class DoctrineSetup {
/**
* #var array $paths - where the entities live.
*/
protected $paths = array(APP_MODELS);
/**
* #var bool $isDevMode - Are we considered "in development."
*/
protected $isDevMode = false;
/**
* #var array $dbParams - The database paramters.
*/
protected $dbParams = null;
/**
* Constructor to set some core values.
*/
public function __construct(){
if (!file_exists('db_config.ini')) {
throw new \Exception(
'Missing db_config.ini. You can create this from the db_config_sample.ini'
);
}
$this->dbParams = array(
'driver' => 'pdo_mysql',
'user' => parse_ini_file('db_config.ini')['DB_USER'],
'password' => parse_ini_file('db_config.ini')['DB_PASSWORD'],
'dbname' => parse_ini_file('db_config.ini')['DB_NAME']
);
}
/**
* Get the entity manager for use through out the app.
*
* #return EntityManager
*/
public function getEntityManager() {
$config = Setup::createAnnotationMetadataConfiguration($this->paths, $this->isDevMode, null, null, false);
return EntityManager::create($this->dbParams, $config);
}
}
/**
* Function that can be called through out the app.
*
* #return EntityManager
*/
function getEntityManager() {
$ds = new DoctrineSetup();
return $ds->getEntityManager();
}
/**
* Function that returns the conection to the database.
*/
function getConnection() {
$ds = new DoctrineSetup();
return $ds->getEntityManager()->getConnection();
}
Do I need to add something else to it to get this error to go away?
Update 1
So I went ahead and set up the AppKernel as I didn't have one before, and because I don't believe I need a config.yml (at least not yet). Everything seems to be working - kernel wise, but the error still persists.
namespace ImageUploader;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel {
public function registerBundles() {
$bundles = array(
new \Doctrine\Bundle\DoctrineBundle\DoctrineBundle()
);
return $bundles;
}
public function registerContainerConfiguration(LoaderInterface $loader) {}
}
I then started the kernel in the bootstrap file, by adding:
use \ImageUploader\AppKernel;
$kernel = new AppKernel();
$kernel->boot();
Everything, from what I have read, is correct - minus the missing config file that shouldn't be an issue. But I still receive the error in question
How i worked around this:
First, created a custom ConstraintValidatorFactory that'd allow me to add validators
<?php
namespace My\App\Validator;
use Symfony\Component\Validator\ConstraintValidatorFactory as SymfonyConstraintValidatorFactory;
use Symfony\Component\Validator\ConstraintValidatorInterface;
/**
* Class ConstraintValidatorFactory
*
* #package My\App\Validator
*/
class ConstraintValidatorFactory extends SymfonyConstraintValidatorFactory
{
/**
* #param string $className
* #param ConstraintValidatorInterface $validator
*
* #return void
*/
public function addValidator($className, $validator): void
{
$this->validators[$className] = $validator;
}
}
Then i could do:
<?php
use My\App\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\Validation;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator;
$factory = new ConstraintValidatorFactory();
$factory->addValidator('doctrine.orm.validator.unique', new UniqueEntityValidator($registry));
$builder = Validation::createValidatorBuilder();
$builder->setConstraintValidatorFactory($factory);
$builder->enableAnnotationMapping();
$validator = $builder->getValidator();
$violations = $validator->validate($entity);
This worked for me, using symfony components with zend service manager.
Bare in mind that Symfony's UniqueEntityValidator depends on \Doctrine\Common\Persistence\ManagerRegistry.
I use a single EntityManager for my project and had to wrap it in a ManagerRegistry class to make this work.
You are missing the Doctrine bundle, which integrates doctrine into the Symfony framework. Install it with composer require doctrine/doctrine-bundle and then register it in your AppKernel.
Related to Update #1
You still need some configuration and set up the doctrine ORM. Without this configuration, ORM services (like the one missing here) are not loaded.
This is an old question but as I just stumbled upon it and find the chosen answer not entirely satisfying I would like to contribute a bit.
As I understood from the comments this is not about full-stack Symfony but only about the Symfony-validator component.
Because the validator constraint UniqueEntity is based on Doctrine integration and hard-coding class names or the such is not recommended to prevent tight-coupling, Symfony uses a much used pattern called services (see service container).
This allows defining services through configuration which would then prevent hardcoding class names (and its dependencies!) into the Validator codebase. This allows dependencies between both project to be configurable (less compatibility-breaks) and optional.
This 'doctrine.orm.validator.unique' "class" that is being searched for is actually just a reference to an instance of the actual class. For it to be found one must add two things:
A service container, which resolves this service name to the class instance
And the actual configuration of this service, which defines the class to instantiate and its constructor parameters (dependencies).
Looking at your composer.json I think we need the Symfony DependencyInjection component, I don't think you need the AppKernel for this. The following code might work (not tested it) but in any case should give you roughly the idea of what we need:
use Symfony\Component\DependencyInjection\ContainerBuilder;
$container = new ContainerBuilder();
$container
->register('doctrine.orm.validator.unique', 'Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator')
->addArgument(new Reference('doctrine'));
# register doctrine here in the same way as we just registered the validator
So in conclusion, this answer will probably be a year or two too late for the OP but might be useful to others stumbling upon this. Cheers!
In the first you can get the kernel
After using the kernel to get service validator.
For example : $validator = $kernel->getContainer()->get('validator');