i ve created an empty extbase/fluid extension and added an ImportCommandController for a scheduler task. For some reason i am not able to load that task in my scheduler. Please note that i want to realise my task via CommandController (http://wiki.typo3.org/CommandController_In_Scheduler_Task) and NOT via \TYPO3\CMS\Scheduler\Task\AbstractTask.
ext_localconf.php
<?php
if (!defined('TYPO3_MODE')) {
die('Access denied.');
}
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['extbase']['commandControllers'][] = 'VENDORx\\Sched\\Command\\ImportCommandController';
Classes/Command/ImportCommandController.php
<?php
namespace VENDORx\Sched\Command;
/**
*
*
* #package Sched
* #license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
*
*/
class ImportCommandController extends \TYPO3\CMS\Extbase\Mvc\Controller\CommandController {
public function importCommand($commandIdentifier= NULL) {
echo 'command run';
}
}
?>
any idea whats missing??
As Jost already mentioned you neet proper Annotations:
/**
* #param integer $commandIdentifier
*/
public function importCommand($commandIdentifier = NULL) {
$this->outputLine('command run');
}
Select "Extbase-CommandController-Task" in dropdown
You'll get another select field on the bottom where you can find your "ImportCommand" select and save
Related
Magento 2.3.1
After making the data patch at the following location:
vendor/ModuleName/Setup/Patch/Data/AddMyColumnPatch.php
(Code given below for AddMyColumnPatch.php)
When I run bin/magento setup:upgrade to get this patch installed I get following error at cli:
DDL statements are not allowed in transactions
I have used the following file as reference to add a column to my table using data patch:
vendor/magento/module-quote/Setup/Patch/Data/InstallEntityTypes.php
Follow lines from 47 to 65.
My AddMyColumnPatch.php code is:
<?php
namespace Vendor\ModuleName\Setup\Patch\Data;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\PatchRevertableInterface;
use Magento\Quote\Setup\QuoteSetupFactory;
use Magento\Sales\Setup\SalesSetupFactory;
use Psr\Log\LoggerInterface;
/**
*/
class AddressSuburbPatch implements DataPatchInterface, PatchRevertableInterface
{
/**
* Attribute Code of the Custom Attribute
*/
const CUSTOM_ATTRIBUTE_CODE = 'my_column';
/**
* #var \Magento\Framework\Setup\ModuleDataSetupInterface
*/
private $moduleDataSetup;
/**
* #var \Magento\Quote\Setup\QuoteSetupFactory
*/
private $quoteSetupFactory;
/**
* #var Magento\Sales\Setup\SalesSetupFactory
*/
private $salesSetupFactory;
/**
* #var \Psr\Log\LoggerInterface
*/
private $logger;
/**
* #param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup
*/
public function __construct(
ModuleDataSetupInterface $moduleDataSetup,
QuoteSetupFactory $quoteSetupFactory,
SalesSetupFactory $salesSetupFactory,
LoggerInterface $logger
)
{
$this->moduleDataSetup = $moduleDataSetup;
$this->quoteSetupFactory = $quoteSetupFactory;
$this->salesSetupFactory = $salesSetupFactory;
$this->logger = $logger;
}
/**
* {#inheritdoc}
*/
public function apply()
{
$this->moduleDataSetup->getConnection()->startSetup();
$this->logger->debug('DDL Statements error');
$quoteSetup = $this->quoteSetupFactory->create(['setup' => $this->moduleDataSetup]);
$quoteSetup->addAttribute('quote_address', self::CUSTOM_ATTRIBUTE_CODE, ['type' => 'text']);
$salesSetup = $this->salesSetupFactory->create(['setup' => $this->moduleDataSetup]);
$salesSetup->addAttribute('order_address', self::CUSTOM_ATTRIBUTE_CODE, ['type' => 'text']);
$this->logger->debug('Script working');
$this->moduleDataSetup->getConnection()->endSetup();
}
/**
* {#inheritdoc}
*/
public static function getDependencies()
{
return [
];
}
public function revert()
{
$this->moduleDataSetup->getConnection()->startSetup();
$this->moduleDataSetup->getConnection()->endSetup();
}
/**
* {#inheritdoc}
*/
public function getAliases()
{
return [];
}
}
After going through declarative schema docs again and referencing core Magento code for quote module and PayPal module I have figured out that if you want to add a field into an existing table in Magento >=2.3 you should use configure declarative schema for that. Read more:
https://devdocs.magento.com/guides/v2.4/extension-dev-guide/declarative-schema/db-schema.html
So create a db_schema.xml file under Vendor/ModuleName/etc
<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
<table name="quote_address" resource="checkout" comment="Sales Flat Quote Address">
<column xsi:type="varchar" name="suburb" nullable="true" length="255" comment="Suburb for Quote Address" />
</table>
<table name="sales_order_address" resource="sales" comment="Sales Flat Order Address">
<column xsi:type="varchar" name="mycolumn" nullable="true" length="255" comment="mycolumn for Sales Order Address" />
</table>
</schema>
Then generate whitelist for your db_schema as follows:
bin/magento setup:db-declaration:generate-whitelist --module-name=Vendor_ModuleName
Run again and your column will be added to quote_address and order_sales_address tables.
bin/magento setup:upgrade
However, further investigation revealed that there is no need of making data patch for adding columns in flat tables quote_address and sales_order_address. Only declaring columns in db_schema.xml will do the job.
I installed Symfony4 using the following steps.
step1: composer create-project "Symfony/skeleton:^4.0” symfony4
step2: git status
step3: git add.
step4: git commit
step5: composer require annotations
step6: create a controller named ArticleController
<?php
namespace App\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Response;
class ArticleController
{
/**
* #Route("/")
*/
public function indexAction()
{
return new Response('OMG! My first page already! Wooooo!');
}
/**
* #Route("/{id}", requirements={"id" = "\d+"}, defaults={"id" = 1})
*/
public function showAction($id)
{
echo 123;die;
}
/**
* #Route("/news/{$slug}")
* #Method({"GET", "POST"})
*/
public function news($slug)
{
return new Response(sprintf('Today new is "%s"', $slug));
}
}
Step7: access http://127.0.0.1:8000
You can view 'OMG! My first page already! Wooooo!'.
But http://127.0.0.1:8000/123 and http://127.0.0.1:8000/news/test do not work. Who can tell me why? And please help me to fix it.
Just find the solution.
composer require symfony/apache-pack
It will automatically generate .htaccess.
the right namespace is :
use Symfony\Component\Routing\Annotation\Route;
thanks
The follwing below is an controller for an template i am making in codeignither HMVC. I am trying to load this template module in my task modules but for some reason it wont load in the template modules but the data loads in my task controller.
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class templates extends MX_Controller
{
/**
* Index Page for this controller.
*
* Maps to the following URL
* http://example.com/index.php/welcome
* - or -
* http://example.com/index.php/welcome/index
* - or -
* Since this controller is set as the default controller in
* config/routes.php, it's displayed at http://example.com/
*
* So any other public methods not prefixed with an underscore will
* map to /index.php/welcome/<method_name>
* #see https://codeigniter.com/user_guide/general/urls.html
*/
public function one_col($data)
{
$this->load->view('one_col',$data);
}
public function two_col($data)
{
$this->load->view('two_col',$data);
}
public function admin($data)
{
$this->load->view('admin', $data);
}
public function index()
{
echo "Hello world";
}
}
this code below is my task controller and it works fine when i run it in the link http://localhost:81/hmvc/index.php/tasks however when i try to run the template view "two_col" http://localhost:81/hmvc/index.php/templates/two_col
using this code in the template
<?php $this->load->view($module.'/'.$view_file); ?>
i get this error :
task module controller below
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class tasks extends MX_Controller
{
/**
* Index Page for this controller.
*
* Maps to the following URL
* http://example.com/index.php/welcome
* - or -
* http://example.com/index.php/welcome/index
* - or -
* Since this controller is set as the default controller in
* config/routes.php, it's displayed at http://example.com/
*
* So any other public methods not prefixed with an underscore will
* map to /index.php/welcome/<method_name>
* #see https://codeigniter.com/user_guide/general/urls.html
*/
public function index()
{
$this->load->model('mdl_tasks');
$data['query'] = $this->mdl_tasks->get('priority');
#$this->load->view('display', $data);
$data['view_file'] = "display";
$data['module'] = "tasks";
echo Modules::run('templates/two_col', $data);
#$this->load->module('templates');
#$this->templates->two_col($data);
}
}
echo Modules::run('templates/two_col', $data);
#$this->load->module('templates');
I'm pretty sure replacement these codes together will work.
Because php is an interpreted programming language. PHP loads every line one by one if deteced an error for ex. on 5Th line it doesnt compile the rest of lines. More information for interpreted lang. and also in your code you implementing the lib function before loading lib
I'm using doctrine in my Symfony project, by connecting to an already existent postgres database.
The DB has several schemas, but the symfony app will use nothing but its own schema. The first Entity class I created is the following one:
namespace Belka\TestBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="app_auth.User", schema="app_auth")
*/
class User {
/**
* #ORM\Column(type="string")
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $username;
/**
* #ORM\Column(type="string")
*/
private $email;
/**
* #ORM\Column(type="string")
*/
private $password;
}
as you can see, the Entity is specifying its own schema app_auth.
Next, I tried to use the migrations bundle. So, I installed and configured it, in order not to consider anything but my schema:
Extract of config.yml:
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
schema_filter: ~^app_auth\..*~
Extract of config_dev.yml:
doctrine_migrations:
dir_name: "%kernel.root_dir%/../.container/update/DoctrineMigrations"
namespace: Application\Migrations
table_name: "app_auth.migration_versions"
name: Application Migrations
And I run the diff:
php app/console doctrine:migrations:diff
Unfortunately, the migration class generated is the following one:
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20160422171409 extends AbstractMigration
{
/**
* #param Schema $schema
*/
public function up(Schema $schema)
{
// this up() migration is auto-generated, please modify it to your needs
}
/**
* #param Schema $schema
*/
public function down(Schema $schema)
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('CREATE SCHEMA app_auth');
}
}
what's wrong with my configuration then?
Dirty but working solution:
Tested with doctrine/migrations: 3.0.1
We can patch out the schema removing functionality of the DiffGenerator. I personally used this https://github.com/cweagans/composer-patches
Install the package, and then in composer.json "extra" section add:
"patches": {
"doctrine/migrations": {
"Change doctrine behavior to correctly pass PostgreSQL schema to schema_filter while diffing": "patches/doctrine-diff-generator.patch"
}
}
The patch file in patches/doctrine-diff-generator.patch:
--- lib/Doctrine/Migrations/Generator/DiffGenerator.php 2020-06-21 10:55:42.000000000 +0200
+++ lib/Doctrine/Migrations/Generator/DiffGenerator.patched.php 2020-12-23 12:33:02.689405221 +0100
## -142,8 +142,6 ##
*/
private function resolveTableName(string $name) : string
{
- $pos = strpos($name, '.');
-
- return $pos === false ? $name : substr($name, $pos + 1);
+ return $name;
}
}
Of course you have to bare in mind, that updates to doctrine could break the patch. And you are changing this functionality globally for your doctrine, so beware of breaking changes.
Personally, for my use case, which is adding doctrine entities into legacy database, without breaking it, this works nicely, and saves me from adding every new table managed by doctrine into the schema_filter.
Explanation:
When we look into DiffGenerator implementation it actually decodes the table names with schema correctly, but only when collecting the current database schema. This happens in PostgreSqlSchemaManager.php:
/**
* {#inheritdoc}
*/
protected function _getPortableTableDefinition($table)
{
$schemas = $this->getExistingSchemaSearchPaths();
$firstSchema = array_shift($schemas);
if ($table['schema_name'] === $firstSchema) {
return $table['table_name'];
}
return $table['schema_name'] . '.' . $table['table_name'];
}
But then then when calculating the target schema, this information is lost here in DiffGenerator.php:
/**
* Resolve a table name from its fully qualified name. The `$name` argument
* comes from Doctrine\DBAL\Schema\Table#getName which can sometimes return
* a namespaced name with the form `{namespace}.{tableName}`. This extracts
* the table name from that.
*/
private function resolveTableName(string $name) : string
{
$pos = strpos($name, '.');
return $pos === false ? $name : substr($name, $pos + 1);
}
And only afterwards the return value of this function is passed into the schema_filter. Unfortunate, but i guess there was a reason for this :)
in my project i need to share objects between orm and odm. I have an entity "Variation" and a document "Tracking". One variation can hold many trackingevents. I tried to solve it through doctrine extension references using the stofdoctrineextensionbundle for symfony 2.3 but whatever i do it wont work. Maybe someone of you have an idea.
Tracking Document: ( watch for $variation )
namespace Anchorbrands\Bundle\LandingpageBundle\Document;
use Anchorbrands\Bundle\LandingpageBundle\AnchorbrandsLandingpageBundle;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/**
* #ODM\Document(collection="landingpage_tracking")
*/
class Tracking {
/**
* #Gedmo\ReferenceOne(type="entity", class="Anchorbrands\Bundle\LandingpageBundle\Entity\Variation", inversedBy="trackingEvents", identifier="variationId")
*/
protected $variation;
protected $variationId;
public function setVariationId($variationId)
{
$this->variationId = $variationId;
}
public function getVariationId()
{
return $this->variationId;
}
Variation Entity ( watch out for $trackingEvents )
/**
* Variation
*
* #ORM\Table(name="landingpage_variation")
* #ORM\Entity
*/
class Variation
{
/**
* #Gedmo\ReferenceMany(type="document", class="Anchorbrands\Bundle\LandingpageBundle\Document\Tracking", mappedBy="variation")
*/
protected $trackingEvents;
public function getTrackingEvents()
{
return $this->trackingEvents;
}
public function setTrackingEvents(Collection $trackingEvents)
{
$this->trackingEvents = $trackingEvents;
}
Workaround to the circular referencing problem (unless you can solve it using DI) #see stof's bundle
<?php
namespace ACME\CoreBundle\Listener;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Class ReferencesListener
*
* #package ACME\CoreBundle\Listener
*/
class ReferencesListener extends \Gedmo\References\ReferencesListener
{
/**
* #var \Symfony\Component\DependencyInjection\ContainerInterface
*/
private $container;
/**
* #var array
*/
protected $managers
= [
'document' => 'doctrine.odm.mongodb.document_manager',
'entity' => 'doctrine.orm.default_entity_manager'
];
/**
* #param ContainerInterface $container
* #param array $managers
*/
public function __construct(ContainerInterface $container, array $managers = array())
{
$this->container = $container;
parent::__construct($managers);
}
/**
* #param $type
*
* #return object
*/
public function getManager($type)
{
return $this->container->get($this->managers[$type]);
}
}
Listener defination
acme.listener.reference:
class: ACME\CoreBundle\Listener\ReferencesListener
arguments: ["#service_container"]
tags:
- { name: doctrine.event_subscriber, connection: default }
When using doctrine extension's references you need to make sure you have registered the subscriber with doctrine. Otherwise the references won't work.
In symfony2 you can register doctrine listeners/subscribers using container tags:
config.yml
services:
gedmo_reference_listener: # choose whatever name you like
class: Gedmo\References\ReferencesListener
arguments:
- { entity: #doctrine.orm.entity_manager, document: #doctrine.odm.mongodb.document_manager }
tags:
- { name: doctrine.event_subscriber, connection: default }
This is what StofDoctrineExtensionsBundle usually does in the bundle's compilerpass. It just simplifies the process of registering the services using a bit of configuration.
But as you can see here ... #stof didn't yet add the reference listener to the configuration options.
There is already an open pull request but #stof doesn't want to add it until the implementation has been refactored. Meanwhile use my solution above :-)
Maybe try from :
services:
# reference behavior doctrine < mongodb
gedmo.listener.reference:
class: Gedmo\References\ReferencesListener
tags:
- { name: doctrine_mongodb.odm.event_subscriber }
calls:
- [ setAnnotationReader, [ "#annotation_reader" ] ]
- [ registerManager, [ 'entity', "#doctrine.orm.default_entity_manager" ] ]
# reference behavior doctrine > mongodb
gedmo.listener.reference:
class: Gedmo\References\ReferencesListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ "#annotation_reader" ] ]
- [ registerManager, [ 'document', "#doctrine_mongodb.odm.document_manager" ] ]
They both work for me, but alone...
If you put them both like this only the second is taken