I set a nested resource like this in my routes.php file :
Route::resource('channels','ChannelsController');
Route::resource('channels.posts','PostsController');
and so when i want to show all posts on a given channel I would get the channel id form the URI :
GET /channels/{channelId}/posts with the method :
// PostsController.php
/**
* Display a listing of the resource.
* GET channels/{channelId}/posts/
* #return Response
*/
public function index($channelId)
{
...
}
but when i want to POST, the channel id will not get passed to the store method
// PostsController.php
/**
* Store a newly created post whithin a channel
* POST channels/{channelId}/posts/
* #return Response
*/
public function store($channelId)
{
... // $channelId is not set
}
I know there's a solution, passing the data with a hidden field in the form, but it is not secure since anyone can edit it and post the wrong id.
Please let me know, if you have any solution.
Actually, I found the solution in Laravel documentation itself, here is it so that everyone can take advantage from :
Form::open(array('action' => array('Controller#method', $user->id)))
the variable $user->id is passed as argument to the method method, also this last one should recieve an argument as well, like so : method($userId)
Related
I would like to build a preview page for a create form. I set "deleted" property of the record to "1" when in previewAction because in the BE the list module is used to approve the inserted records - so if the record was never finally saved its deleted anyway.
Problem: I can create the record (deleted=1) - I can jump back to the form (no history back for I have to keep the created object). But if I submit again the property mapping tells me
Object of type MyModel with identity "3" not found.
Of course that's because its deleted. The settings in the Repository to ignore deleted are not taking action here.
Yes I could bypass the Extbase magic by filling up everything manually, but this is not what I want.
Here is the action to get an idea what I'm trying
/**
* action preview
*
* #param MyModel
* #return void
*/
public function previewAction(MyModel $newModel)
{
//check if model was already saved
$uid = $this->request->hasArgument('uid') ? this->request->getArgument('uid') : 0;
if($uid){
$newModel = $this->myRepository->findDeletedByUid($uid);
$this->myRepository->update($newModel);
}
else{
$newModel->setDeleted(true);
$this->myRepository->add($newModel);
}
$this->view->assign('ad', $newModel);
$this->persistenceManager->persistAll();
$uid = $this->persistenceManager->getIdentifierByObject($newModel);
$this->view->assign('uid', $uid);
}
Any ideas?
The Extbase default query settings suppress deleted objects.
Since you've already stated the custom query findDeletedByUid() in your repository, you just need to set it to include deleted records. It is important, however, that if you want to call your controller action using the object, you'll have to retrieve it before calling the action. Use an initialization action for that. The initializaton will be called automatically before the action.
If you want to set wether the object is deleted, you'll also going to need to define a property, getter and setter in your Domain Model and a proper definition in your tca to enable the data mapper to access the column.
In the repository:
public function findDeletedByUid($uid) {
$query = $this->createQuery();
$query->getQuerySettings()->setIncludeDeleted(true);
$query->matching(
$query->equals('uid',$uid)
);
return $query->execute();
}
In your Controller class:
/**
* initialize action previewAction
* Overrides the default initializeAction with one that can retrieve deleted objects
*/
public function initializePreviewAction(){
if( $this->request->hasArgument('mymodel') ){
$uid = $this->request->getArgument('mymodel');
if( $mymodel = $this->mymodelRepository->findDeletedByUid($uid) ){
$this->request->setArgument($mymodel);
} else {
// handle non retrievable object here
}
} else {
// handle missing argument here
}
}
In your Domain Model:
...
/**
* #var bool
*/
protected $deleted;
/**
* #return bool
*/
public function getDeleted() {
return $this->deleted;
}
/**
* #param bool $deleted
*/
public function setDeleted($deleted) {
$this->deleted = $deleted;
}
In your tca.php
...
'deleted' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.deleted',
'config' => array(
'type' => 'check',
),
),
Instead of doing any magic with deleted, you should use the hidden field to allow editors to preview documents.
You can tell your query to include hidden records inside the repository.
Your findDeletedByUid($uid) function caught my eye. If it's not a custom function, should it use something like findByDeleted(TRUE) or findByDeleted(1) in combination with ->getFirst() or ->findByUid()? You can find discussions in the Extbase manual reference and the Repository __call() function API sections.
Thanks for all hints.
I think depending to the answers its not possible without bypass extbase property-mapping magic. So I think in general its not a good idea to do it like that.
So I put now my own flag "stored" to the model.
In BE List-Module the not "stored" objects are still visible, but using an own BE Module or deleting the not "stored" object by a cron-job should do the job.
If anyone has a bedder idea feel free to share it :-)
When using Extbase's "show" action:
<f:link.action action="show" arguments="{event : event}">
I would like to look up said event by a special column ('customID').
The actual TYPO3-uid should NOT appear in the URL (with or without RealURL).
The reason is that the data has been imported, and the "real" uid is 'customId'.
There's always #biesior's approach using f:link.page https://stackoverflow.com/a/26145125/160968 – but I thought I'd try it with the official way.
(how) is it possible to do that in extbase/fluid?
This is possible. Let's assume your model Event has a property customId. So you generate your link like this:
<f:link.action action="show" arguments="{event : event.customId}">
The link generated will have a queryString like this:
?tx_myext[event]=9999
The showAction generated by the Extension Builder expects that the UID of the event is passed. The PropertyMapper then fetches the object automatically and assigns it to the view:
/**
* action show
*
* #param \Your\Extension\Domain\Model\Event $event
* #return void
*/
public function showAction(\Your\Extension\Domain\Model\Event $event) {
$this->view->assign('event', $event);
}
But in your case you cannot fetch the object by UID because you passed the customId. So you need to fetch the object yourself:
/**
* action show
*
* #param integer $event
* #return void
*/
public function showAction($event) {
$event = $this->eventRepository->findOneByCustomId($event);
$this->view->assign('event', $event);
}
The annotation #param integer $event tells TYPO3 that the parameter is "just" an integer. You then call the magic method findOneByCustomId from your eventRepository. findOne indicates that you want exactly one Event object back (and not a QueryResult), while the ByCustomId that queries an existing property of your Event model.
Why not use realUrl with lookUpTable? See here: https://wiki.typo3.org/Realurl/manual#-.3ElookUpTable
I use Acceleo in order to generate code with a model I have made. I managed to protect my methods in order to protect them usinig "#generated NOT" in case I need to regenerate my code with Acceleo. The problem is that adding #generated NOT protect all the method content, that is to say the body, the signature and JavaDocs.
The thing is that I only need to keep the method body, or at least the method body and its signature, but I need the doc to be updated. How can I do this ?
Just for information here is an example of a potential generated class :
/*
* #generated
*/
public class ActeurRefEntrepriseServicesImpl implements ActeurRefEntrepriseServices {
#Autowired
HelloWorldService helloWorldService;
/**
* Service which say hello
*
* #param name
* user name
* #return print Hello username
*
* #generated NOT
*/
#Override
public void sayHello(final String name) {
helloWorldService.print(name);
}
}
Baptiste,
The #generated tags use the standard EMF protection rules : "#generated" means that the body of the block for which it is set will be generated, anything else means no re-generation. If you set something as "#generated" in any of your metamodels' generated code, you will see that there, too, the javadoc is preserved whatever the edits you do.
In short, you cannot tell EMF to re-generate anything other than the code itself.
If you need to have the body protected but not the javadoc, you have to shift from the "#generated" protection to Acceleo's [protected] blocks. i.e, change your template from :
[template generatedMethod(methodName : String)]
/**
* Some doc.
* #param param1
* param documentation.
* #generated
*/
[generateSignature(methodName)/] {
[generateBody()/]
}
[/template]
to something using a protected block :
[template generatedMethod(methodName : String)]
/**
* Some doc.
* #param param1
* param documentation.
*/
[protected (methodName)]
[generateSignature(methodName)/] {
[generateBody()/]
}
[/protected]
[/template]
With this paradigm, anything that is outside of the protected area will be regenerated, everything else will remain untouched by a regeneration.
See also the full documentation available from the Acceleo website.
If you absolutely need to use the "#generated" protection method for your model, you will need to tamper with the JMerger API from EMF and alter the launcher Acceleo generated for you in order to use your own merging strategy (see the getGenerationStrategy method from that launcher). Note that this is by no means an easy task.
I am in very bad situation, I got the objectiveC classes from the sudzc website.
using "http://www.xxx.in/mstore/api/soap/?wsdl"
in "SDZMagentoServiceExample.m" class I get one method
[service call:self action:#selector(callHandler:) sessionId: #"" resourcePath: #"catalog_category.level" args: (id)args];
It always gives me parameter error like
"Invalid website code requested:" if I pass dictionary or array in the args.
Please help me, I am in very bad situation.
thanks in advance.
From
/**
* Catalog category api
*
* #category Mage
* #package Mage_Catalog
* #author Magento Core Team <core#magentocommerce.com>
*/
class Mage_Catalog_Model_Category_Api extends Mage_Catalog_Model_Api_Resource
{
Following code:
/**
* Retrieve level of categories for category/store view/website
*
* #param string|int|null $website
* #param string|int|null $store
* #param int|null $categoryId
* #return array
*/
public function level($website = null, $store = null, $categoryId = null)
{
So nor array, nor dictionary would be accepted. Only raw string or int value.
I will not be able to help you in Objective C code, but I can show you some light with PHP. You can try out this type of call:-
$proxy = new SoapClient('http://www.iphone5case.in/mstore/api/soap/?wsdl');
$sessionId = $proxy->login('apiUser', 'apiKey');
/**
* As defined in the "Manage Stores" section of Admin panel,
* where you need to use the specific Website Code and/or Store Code
*/
$websiteCode = null;
$storeCode = 'german';
// Parent Category ID
$parentCategoryId = 2;
$firstLevel = $proxy->call($sessionId, 'category.level', array($websiteCode, $storeCode, $parentCategoryId));
Now if you print this variable "$firstLevel", you will get your required output, from this Web Service API.
Also whenever you are using Magento SOAP API v1, then each of the arguments will need to be as an array element. In this case, following are the main parameters expected for this API call "category.level":-
Website Code or ID
Store View Code or ID
Parent Category ID
So you need to create an array, and put sequentially each of the above arguments as array elements, like:-
array(
$websiteCode,
$storeCode,
$parentCategoryId
)
Lastly, please make sure that you reference this article always, as you can get the usage of almost all the Web Service API methods here.
Hope it helps.
I'm using GWT 2.4. I'm trying to submit an AJAX request with the only input being the value of a text field on the page. Here is how I attach the handler to the page's button ...
public void onModuleLoad() {
...
final com.google.gwt.dom.client.Element submitElement = Document.get().getElementById(SUBMIT_BUTTON_ID);
final Button submitButton = Button.wrap(submitElement);
...
// Add a handler to send the name to the server
GetHtmlHandler handler = new GetHtmlHandler();
submitButton.addClickHandler(handler);
}
But here's the problem. In my handler, whenever I try and get the value of the text field, it always returns the value entered in the text field when the page was first loaded, as opposed to what the most current value is ...
class GetHtmlHandler implements ClickHandler {
/**
* Fired when the user clicks on the submitButton.
*/
public void onClick(ClickEvent event) {
submitRequest();
}
/**
* Send the name from the nameField to the server and wait for a
* response.
*/
private void submitRequest() {
...
final Element nameFieldElement = DOM.getElementById(Productplus_gwt.NAME_FIELD_ID);
// This always returns an old value.
String docId = nameFieldElement.getAttribute("value");
Anyone know how I can write GWT code inside my handler to return the most current value of a text field given its page id?
Thanks, - Dave
Try using DOM.getPropertyString / DOM.getElementProperty
Following is the javadoc from GWT source for getAttribute function. It clearly says that the support for javascript's "getAttribute" function could be inconsistent for a few browsers and thus Element and subclasses should be used.
Alternatively you can use DOM.getPropertyString to fetch a value which uses object notation of javascript to get te current value
/**
* Retrieves an attribute value by name. Attribute support can be
* inconsistent across various browsers. Consider using the accessors in
* {#link Element} and its specific subclasses to retrieve attributes and
* properties.
*
* #param name The name of the attribute to retrieve
* #return The Attr value as a string, or the empty string if that attribute
* does not have a specified or default value
*/
public final String getAttribute(String name) {
return DOMImpl.impl.getAttribute(this, name);
}
I tried using javascript's "getAttribute" function to get value of a text field in IE8 and FF6. IE gave the updated value of the text field while FF did not. Here is the fiddle
http://jsfiddle.net/GvNu4/
Well like you said it's an AJAX request so whatever code you have on ... the GWT code will continue to run.
You should use the callback of the request and check the value of the nameFieldElement at that moment.