Where should I create a template for a json view in CakePHP 3? - cakephp-3.1

I am using CakePHP 3.1 and trying to render the json index response for User model. I followed the CakePHP manual page and created index.ctp under the directory src/Template/Users/json/, but the file does not get hooked by the controller. I also tried src/View/Users, which also did not work. Should I specify a file to render or something else? In src/Controller/UsersController.php, I have index() method with
$users = $this->paginate('Users');
$this->set(compact('users'));

Check your AppController.php. Since version 3.1.0 this sets the _serialize to true by default. Therefore the template files are all ignored.
public function beforeRender(Event $event)
{
if (!array_key_exists('_serialize', $this->viewVars) &&
in_array($this->response->type(), ['application/json', 'application/xml'])
) {
$this->set('_serialize', true);
}
}
You need to remove that code from beforeRender.

Related

Typo3: Controller action with hidden record as its parameter

I am currently trying to get a extension working in Typo3 v10, which enables the user to show, edit, update, disable and enable other user accounts.
Unfortunately, I am running into the issue that I cannot use disabled users as arguments for the actions:
/**
* Save user changes
*
* #param \Company\MyExtension\Domain\FeUser $feuser
* #return void
*/
public function updateAction(\Company\MyExtension\Domain\FeUser $feuser): void {}
It would resulting in the error following error:
Object of type \Company\MyExtension\Domain\FeUser with identity "3" not found.
From what I have gathered, extbase does not rely on the repository's default query settings to create the objects but instead uses PersistenceManager::createQueryForType to get the query settings via QueryFactory::create. This is an issue also listed in a few bug reports.
There's a suggestions as to how to use a custom QueryFactory to set different default QuerySettings for my extension, however this does not seem to work in Typo3 v10 anymore, at least my custom QueryFactory isn't being used after registering it... Also, if this were to work, wouldn't it use the new QueryFactory for all objects instantiated through a controller action and not just this extension?
How can I properly handle hidden users my extension with Typo3 v10.4?
P.S. Another suggestion was to fetch object early through initializeAction, but this only works well if it is about the unmodified model and not when setting new values for the object, as it would just load the database values in the end...
Checkout the extension "news" how it is handled here:
if ($news === null || $this->settings['isShortcut']) {
$previewNewsId = ((int)$this->settings['singleNews'] > 0) ? $this->settings['singleNews'] : 0;
if ($this->request->hasArgument('news_preview')) {
$previewNewsId = (int)$this->request->getArgument('news_preview');
}
if ($previewNewsId > 0) {
if ($this->isPreviewOfHiddenRecordsEnabled()) {
$news = $this->newsRepository->findByUid($previewNewsId, false);
} else {
$news = $this->newsRepository->findByUid($previewNewsId);
}
}
}
https://github.com/georgringer/news/blob/master/Classes/Controller/NewsController.php#L338
I am assuming you need the URL as well. I gave an answer here if you wanna take a look.
Show, edit and update hidden records in FrontEnd (TYPO3)
You can adjust it to your own needs as well.
Best regards

How can I use Spatie Media Library with Backpack for Laravel upload field?

I want to upload a file in Backpack for Laravel and immediately attach the file to the model using Spatie Media Library.
What is my best option to do this?
I tried doing this using the SetImageAttribute mutator as recommended in the docs: https://backpackforlaravel.com/docs/4.1/crud-fields#upload-1
public function setImageAttribute($value) {
$this->addMedia('image');
}
However this method requires me to have an unused "image" field on the DB (because Spatie Media Library uses its own table).
Is there another way to do this without using a mutator/creating extra DB fields?
You can avoid having to create an unused image field on your DB by overwriting both the set and get mutators/accessor on your model.
Laravel documentation defining accessor
Laravel documentation defining mutator
Create the following 2 methods on your model:
public function getImageAttribute()
{
return $this->getFirstMediaUrl('image') ?? '';
}
public function setImageAttribute($file)
{
$this->clearMediaCollection('image'); // to remove any previous files
if ($file) {
$this->addMedia($file)->usingFileName($file->hashName())->toMediaCollection('image');
}
}
If you have a fillable set on your model, also add image to it.
protected $fillable = ['image']
Now you should be able to create and update the files using Backpack.
You may change the implementation based on your needs and requirements.

cakephp 3.0 'App\Controller\ContactForm' not found modelless form

I am trying to create a modelless form using cakePHP 3.0, I have been following the guide through the cookbook here http://book.cakephp.org/3.0/en/core-libraries/form.html but it seems I am getting confused as to where to put ContactForm.php. It says to put it in src/Form/ContactForm.php but it did not work. Can someone direct me to this? Thanks
Pls, provide a bit more info about your problem
1) is ContactForm recognized in controller?
if not - check namespace
2) handle your data only in
protected function _execute(array $data)
{
// Send an email.
return true;
}
not in controller's
if ($this->request->is('post')) {
if ($contact->execute($this->request->data)) {
//NOT HERE!!!
} else {
// error
}
}
Also bear in mind that your server configuration may forbid php short open tags.
Make sure your class starts with <?php and not only <? to be on the safer side. If not, CakePHP will simply respond by the Your\Namespace\Class Not Found message.
Just verify where you have put Form Folder, it must be inside src Folder.
Also be sure that the class has Form as suffix.
Because your error is App\Controller\ContactForm not found, that means that you have NOT put Form Folder inside src Folder.

How to pass argument to controller action with FluidTypo3?

How do I have to pass an argument to a flux-enabled controller so it is recognized by the controller action?
I created an extension using builder and added the following method to the ContentController.
/**
* #param string $var
*/
public function exampleAction($var = null) {
var_dump($var);
die;
}
But no matter how I add the parameter to the URL, I only get "null" as a result.
Extensions directory is "test" and so is $_EXTKEY. The builder put "Mac.Test" into ext_tables.php for calls to registerProviderExtensionKey(). So in the URL I tried these parameters:
http://host/index.php?id=1&tx_test_content[var]=abc
http://host/index.php?id=1&tx_test[var]=abc
http://host/index.php?id=1&tx_mactest_content[var]=abc
http://host/index.php?id=1&tx_mactest[var]=abc
http://host/index.php?id=1&var=abc
and some others. But to no avail.
I tried with the f:link.action ViewHelper, resulting in
http://localhost/test2/index.php?id=1&no_cache=1&tx_test_content[member]=foo&tx_test_content[action]=example&tx_test_content[controller]=Content
Also $this->request->getArguments() only returns an empty array, so there must be something seriously wrong.
Used versions:
PHP 5.6.11
TYPO3 6.2.21
vhs 2.4.0
flux 7.2.3
fluidpages 3.3.1
fluidcontent 4.3.3
fluidcontent_core 1.3.0
builder 1.0.0
Nothing else installed (fresh system just for testing this behaviour).
Using fluid link, you can pass para like
<f:link.action action="example" controller="controllerName" arguments="{var:'abc'}">Go</f:link.action>
It'll create link like:
http://host/index.php?id=1&tx_[extension_key]_[fe_plugin_key][var]=abc
Now, how to get para from url in extBase
$arguments = $this->request->getArguments(); // OR
$var = $this->request->getArgument('var');
Useful links:
Fluid
extBase Accessing GET/POST vars

How to make extbase extension recognize storage page from plugin?

In an extbase extension built with extension builder on TYPO3 6.1.7, I haven't set any storagePid via Typoscript.
But I have set the "Record Storage Page" in the plugin:
I would expect that it would now only fetch records from this page.
But it doesn't, it just returns all items from that table.
How do I make the extension recognize the setting from the plugin?
Or (if it's supposed to do that out of the box) how do I find out why it doesn't?
I did a lot of research when my extension's frontend plugin (TYPO3 7.6.4) refused to use the 'pages' field of the plugin ("Record Storage Page"), so I would like to share my findings:
My extension's name is 'tx_dhsnews', my plugin's name is 'infobox'
setRespectStoragePage must be set to true (default): $query->setRespectStoragePage(TRUE)
In the typoscript-setup, the plugin-specific storagePid plugin.tx_dhsnews_infobox.persistence.storagePid MUST NOT be present at all! Not even with an empty value! Else the 'pages'-field will not be respected!
That's all. The Extensions Builder just created a typoscript-setup with the storagePid for the specific plugin 'infobox' set to nothing. That resulted in the plugin not respecting the 'pages' - field.
It's no problem to set the storagePid on extension-level (e.g. 'tx_dhsnews..persistence.storagePid'), the value will be merged with the value(s) given in 'pages' ("Record Storage Page"), but as soon the plugin-specific tx_[extension]_[plugin].persistence.storagePid exists in the typoscript, it will overrule everything else!
Hope this will help somebody to save some time + nerves
Add the following code to your repository
namespace <Vendor>\<Extkey>\Domain\Repository;
class ExampleRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
// Example for repository wide settings
public function initializeObject() {
/** #var $defaultQuerySettings \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings */
$defaultQuerySettings = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Typo3QuerySettings');
// add the pid constraint
$defaultQuerySettings->setRespectStoragePage(TRUE);
}
// Example for a function setup changing query settings
public function findSomething() {
$query = $this->createQuery();
// add the pid constraint
$query->getQuerySettings()->setRespectStoragePage(TRUE);
// the same functions as shown in initializeObject can be applied.
return $query->execute();
}
}
You will find more informations at this page
http://forge.typo3.org/projects/typo3v4-mvc/wiki/Default_Orderings_and_Query_Settings_in_Repository
I actually modified my MVC controller to achieve a record filtering depending on the actual page(storagePid==page.id).. looked like this:
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
class MyMVCController extends ActionController {
protected function initializeAction() {
parent::initializeAction();
//fallback to current pid if no storagePid is defined
$configuration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
if (empty($configuration['persistence']['storagePid'])) {
$currentPid['persistence']['storagePid'] = GeneralUtility::_GP('id');
$this->configurationManager->setConfiguration(array_merge($configuration, $currentPid));
}
[..]
I used the solution by http://wiki.t3easy.de/ and modified the value of the storagePid cause i developed a backend module.
His tscript example didnt worked for me..
Also an article by Thomas Deuling was interesting for the topic..
but i still dont get the whole connection into my mind.. wanna go back to symfony xD
edit: for the modification of the repo queries also this article looked interesting:
https://forge.typo3.org/projects/typo3v4-mvc/wiki/Default_Orderings_and_Query_Settings_in_Repository