Can I access old-style piBase classes and methods from my Extbase extension?
For example, can I create an AccessMyoldExtensionService.php Service as a wrapper class and then pull the return values into my controller?
In my case, I need to return a list of old data records that can't be migrated to MVC style directly.
If so, what would the basic approach be?
To get access on the db records of your old extension you can map the table into your new extension.
Create a new model with matching properties of the needed table fields.
Create the mapping in TS setup.txt like
persistence{
[...]
classes{
Tx_YourNewExtension_Domain_Model_Bar {
mapping {
tableName = tableNameOfOldExtension
}
}
}
}
Create the related repository.
Related
GET and POST parameters in custom extbase controllers need to be prefixed with the plugin signature to be injected automatically:
<?php
namespace Vendor\Example\Controller;
class SearchController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
public function resultsAction($q = null)
{
//...
}
}
Search term $q is only filled automatically if it is passed as ?tx_example_search[q]=foo.
Is there a way declare that the readable version ?q=foo is also fine, and that this should be injected by extbase as well?
(I know that this breaks when multiple plugins on the same page use that parameter, but that's no problem here.)
(The parameter mapping seems already done when ActionController::processRequest() is called, so it must be done earlier.)
You could use the Extbase Plugin enhancer within the routing configuration.
See here: TYPO3 Advanced routing configuration Docs
TYPO3 would then transform the EXTbase URLs into an readable version.
Example:
without the routeEnhancer: yourdomain.com/?tx_example_search[q]=foo
with the routeEnhancer: yourdomain.com/foo
Tipp: You have to define all GET Params otherwise TYPO3 will show the cHash Param.
You can use the method \TYPO3\CMS\Core\Utility\GeneralUtility::_GP($var) in order to retrieve parameters from global variables GET/POST.
Or also \TYPO3\CMS\Core\Utility\GeneralUtility::_GET($var) or \TYPO3\CMS\Core\Utility\GeneralUtility::_POST($var).
Take care of security, those parameters are not sanitized !
If you really want to add the parameter to the action, you have to create an initializeAction() and set the parameter, something like this I guess :
public function initializeResultsAction() {
$myVar = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('q');
$this->request->setArgument('q', $myVar);
}
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.
I created an extension with a domain model Message. This model has a relation m:n with the TYPO3 pages (the one which has the details of the pages, like title, issite_root etc) table. However, by using the mapping to existing tables option, it gives me type error saying page :
The configured type field for table "pages" is of type int(11) unsigned
This means the type field can not be used for defining the record type.
You have to configure the mappings yourself if you want to map to this
table or extend the correlated class
So I just create the relation without mapping, so that I can later map it from setup.txt.
The I created model Pages in MyExt/Classes/Domain/Model/ with all the getters/setters and repository in MyExt/Classes/Domain/Repository/.
In my setup.txt I did this:
config.tx_extbase {
persistence{
enableAutomaticCacheClearing = 1
updateReferenceIndex = 0
classes {
Tx_Playfield_Domain_Model_Pages {
mapping {
tableName = pages
columns {
uid.mapOnProperty = uid
pid.mapOnProperty = pid
sorting.mapOnProperty = sorting
title.mapOnProperty = title
subtitle.mapOnProperty = subtitle
}
}
}
}
}
}
But when I try to access the Pages model I created,
var_dump($this->pagesRepository->findByUid(74));
its searching for tx_playfield_domain_model_pages which does not exists, it shows
Table 'typo3.tx_playfield_domain_model_pages' doesn't exist: SELECT tx_playfield_domain_model_pages.* FROM tx_playfield_domain_model_pages WHERE tx_playfield_domain_model_pages.uid = '74' LIMIT 1
What am I missing here?
Update
After following http://t3-developer.com/extbase-fluid/cheats-extbase/model/tabelle-pages-in-extbase/ suggested by #Michael I get an empty result from $this->pagesRepository->findByUid(74)
setup.txt is loading. I did this to check it:
plugin.tx_playfield{
settings{
temp=yes
}
}
And this is being accessed from my controller.
Is it possible that you didn't create the Pages domain model (within the extension builder or not at all)? The file my_ext/Classes/Domain/Model/Pages.php needs to exist. Check that your "Pages" domain model has the property Map to existing table set to pages, it should look like that:
I don't know where exactly your error is, but I did some more tinkering in the extension builder and made it work. You can probably find out by comparing your extension playfield to my temporary extension testfield: Download it here (updated).
Btw, you don't need to map properties that you do not want to be displayed in the frontend unless they are named differently.
mapping {
tableName = pages
columns {
title.mapOnProperty = title
subtitle.mapOnProperty = subtitle
}
}
I think you have to write the mapping with camel case letters (the class name). Although this post is in German, I think the code might help you. The author added some fields he is going to use to the class and also added a mapping in the typoscript of the extension (see the example code there). The most important part of the German text is that this example there was designed only to read from the db. If you want to create new pages using the model, you have (at least) to add the TCA and setters in the model class to make it work.
Using an EF model in the Models folder in my MVC 4 project, I succeeded to display data in a razor view using a coded class named Prod and a controller method as next:
public ActionResult Index()
{
IEnumerable<Prod> Pr = from p in db.Products
select new Prod
{
ProductId = p.ProductID,
ProductName = p.ProductName
};
return View(Pr);
}
Now I am trying to do the same thing using a model in a class library instead of the current one, so I added to my solution a new class library, added then a model using the same connection string, and mapping the same entities, then added to my MVC project a reference to the new class library, and put at the top of both MyController and Prod class the next:
using MyClassLibrary;
Then I deleted the old model, now when I try to display the view, I get the following error:
Unable to load the specified metadata resource.
Any help please ?
When you move or rename the project the data context (.edmx) is in the metadata part of the Entity Framework connection string has to change
you can try have
connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;
instead of
connectionString="metadata=res://*/Models.MyModel.csdl|res://*/Models.MyModel.ssdl|res://*/Models.MyModel.msl;
or try deleting your context and recreating it then check the connection string it adds automatically.
You need to put your connectionstring in web.config in Mc4 web project
You need to Mention the datasource in the connection string.
If you have not used any other web.config file for views. Use you generic web.config file and upload a connection string with New datasource name , user and password.
I'm using Postgres and also the Datasources plugin.
Rails has a property called schema_search_path. Is there an equivalent in Grails?
I have two schemas, hk and public in the database.
Where can I specify a search path for the schema or a specific schema name?
I was able to make this work using the syntax like the following on the individual class.
static mapping = {
table name:'he_stats_item_summary_keywords', schema:'he'
}
However, it would still be nice to know if there was an equivalent to the schema_search_path on the datasource.
Possible solution found at:
PostgreSQL Default Schema in DataSource
Add support the hibernate.default_schema property to the _DataSource.groovy file
development {
dataSource {
dbCreate = "update"
url = "jdbc:postgresql://localhost:5432/deploy"
hibernate.default_schema = "turnkey_dev"
dialect = org.hibernate.dialect.PostgreSQLDialect
}
}