I'm implementing a "Clone" button in my application, which should allow to perform the following:
create a copy of the chosen model;
redirect to the create view, whose form field should be populated with the cloned model's data;
allow the user edit some fields;
save the new model.
So far, my ModelController#clone method is:
$newModel = $existingModel->replicate();
$newModel->title = "Copy of ".$existingModel->title;
$newModel->created_at = now() // not sure if necessary, or if it'll be changed once the model is stored in the database
return redirect(route('models.create')); // I know this doesn't do what I need
As it is, obviously, nothing gets passed to the create view, but I can't find any clue on how to do that.
I have tried adding ->withInput(compact($newModel)) to the redirect() call, but I don't see the field being populated.
In the models.create view, I have set up the form field to use the old(...) data, if available.
This answer is almost what I need, but it would imply changing every field to check if there is some sort of input other than the old session data, like this:
<input [other attributes omitted] value="{{ $newModel['title'] ?? old('title') }}">
Is it the right way to do so, or is there a quicker/more standardized way of proceeding?
you could overriding the session old input data by:
Session::put('_old_input', $newModel);
and then just render the old() in form inputs
Related
Basically I have an anchor tag (update) that gets the id of the request in the table and load the update view getting all the request details
<i class="fa fa-eye"></i> Update
This is then received in my method
public function update_request_view($idx)
{
//some code here to load the view and get details
}
The url then becomes http://localhost/dashboard/staff/request/update_request_view/48
Now when I try to save the update that I make using another method
public function update()
{
$idx = $this->uri->segment(5);
}
My $idx variable is empty. When I use $this->uri->segment(4), I get update_request_view.
I dont wanna use hidden fields since it will cause lots of security issues and also when I will be able to work this out i will encrypt the id. Why is my $this->uri->segment(5) empty and how do I get it?
Most likely, if I understand you correctly, it is because the update function is a separate page than http://localhost/dashboard/staff/request/update_request_view/48. So CI doesn't see any of the previous url variables. You can either submit to update/{$id} (action url) or you can use a hidden field; it is no less safer than using an id in the url as that can be just as easily manipulated with a change to the form action.
That being said, if you are really concerned about security you should restrict access to particular users for a given record using some sort of ACL.
I have a Controller that parses an XML and returns a view with a list of names and URLs.
return view('view_1',compact('myList'));
View_1 will have a form with parameters method="POST" action="goToView_2"
Then I get some information from my view_2 through a POST, but I still want to keep $myList so that view_2 view uses it aswell.
How do I pass $myList from the first view to the next through a controller?
It sounds like you're trying to have multi-step form of some kind.
I would store the data in the session and easily access it in the second controller or in the view (although not recommended).
https://laravel.com/docs/5.4/session#using-the-session
PS. I personally love using the global session helper.
On the page, there will be several posts by a user. Each post has an id # to identify it which is used when editing or deleting the post. With blade, I can make it so that hidden ID div only shows up when the authenticated user is on their own profile (since only they are allowed to edit or delete the posts).
However, I also have a liking feature that also uses that hidden ID div. I don't want someone to view the page source, change the ID, then click the like button. Is there a way to include the ID in the view, but not allow it to be changed?
I could try do to some validation on each like such as match the user, body, time posted, and ID and if that doesn't match then throw an error. Curious if there's a better way.
View:
<div class="post-like">
Like
</div>
Controller:
The $postId is that hidden ID div
public function getLike($postId)
{
$post = Post::find($postId);
if (!$post) {
return redirect()->back();
}
if (Auth::user()->hasLikedPost($post)) {
return redirect()->back();
}
$like = $post->likes()->create([]);
Auth::user()->likes()->save($like);
return redirect()->back();
}
It's not wise expose users' ID like this, but if you really need it, Laravel provides a way to handle users' action authorization. It can be done using either policies or model scopes.
Alternatively, you can ignore those authorizations and use UUID instead ID.
There is a nice package that handles it for you. Basically you'll just need to add a new field to the users' table.
In my applications I use both of them.
If I understand your question correctly, here's one idea: you can hide the actual post ID by concatenating your ID with some server-side only "key" and hashing.
For example:
In your app.php you add something like "post_mask_key" => "super_secret_123456"
...and in your code, something like:
$maskedPostId = sha1(\Config::get("app.post_mask_key") . $postId);
Then, share $maskedPostId with your view, which will be embedded into the HTML. The user can try to change it but when it is submitted, you can re-generate the hash easily (since you know both the key and ID server side) and compare the two.
Note: this approach is cryptographically weak but should be sufficient for masking a non-critical item like a post ID.
I'm pretty new to PHP programming and Magento. I wanna to pass the current ProductId from a form within a custom block to a controller (new action).
Yes I know that one method would be to add an input hidden (with my product id) in the custom block form and then to retrieve the Value through a regular:
$this->getRequest()->getPost('myvalue'))
Is there a better way in Magento to retrieve the value within the controller without having to declare extra secret input fields ?
Good for you for wanting to adhere to best practices within Magento! The passing of data to controllers is pretty standard, however. If we look at how the product is added from a product page, we'll actually see the product ID in the form action URL's parameters:
http://domain.com/checkout/cart/add/uenc/uenc_value/product/45573/
...where 45573 is the product ID. Of course this can also be sent to the controller via a hidden input field, which I use all the time. Note that the above is the same as http://domain.com/checkout/cart/add/?uenc=uenc_value&product=45573 in Magento.
Another way of storing data for use in controllers for future use is setting data into a session. For posting data to a controller I wouldn't recommend this method but it's something to keep in mind:
$session = Mage::getSingleton('core/session');
$session->setMyValue(true);
We can then retrieve the data from my_value later just by instantiating the session. Good luck!
Passing your data could be done in different ways :
You could use Magento's magic setters and getters.
So you would have to do this to set the value :
Mage::getSingleton('core/session')->setSomeVariable($value);
and this to retrieve it :
Mage::getSingleton('core/session')->getSomeVariable();
Or you could use the register.
Mage::register('key', $value); //to set your data
Mage::registry('key'); //to get your data
Magento provides a way to construct a URL with the necessary values, calculated against the configuration DOM. Blocks (and therefore block templates) can call Mage_Core_Block_Abstract::getUrl() directly:
$this->getUrl('some_handle/foo/test',array('id'=>'some_value'));
// Mage::getUrl() will work as well
The above would result in the following URL:
http://base_url/frontname/foo/action/id/some_value/
...which can be read in the FooController testAction() as
$this->getRequest()->getParam('id') // 'some_value'
My background is more server-side than front-end. So I may be lacking in some basic front-end knowledge.
I have a endpoint called
/quotations/:id/products
which if you do a POST action, this means you want to add products to the specified quotation where :id represents the quotation id.
In my schema, quotations and products have a many-to-many relationship.
The endpoint also expects the data is sent in the form of products[].
Meaning to say, if I want to add products with id 2, 7, and 154 to the quotation 3
I am POSTING
<input name="products[]" value="2" />
<input name="products[]" value="7" />
<input name="products[]" value="154" />
to the url /quotations/3/products
My question is how do I create the Model and View using Backbone for this setup?
I bought Addy Osmani's book on Developing Backbone.js Applications. So I have setup my backbone similar to his example.
There is only an example of a straight forward add model.
Hopefully I get an answer that follows the convention that Osmani sets out for adding children to a parent type of behavior.
Osmani also mentioned about Backbone Relational.
I am not sure if I should use this or even how. I have read the documentation, but I am not sure how to fit this into the way Osmani has structured his Backbone example apps.
UPDATE:
If it is a success, I want the page to redirect to another page called /success.
If it is a failure, I want the page to display a failure message somewhere. Assume there is a <div id="message"></div> for me to update.
In other words, for failure, the page stays as a single page app.
For success, the page goes to another page.
As for server-side code for returning JSON replies etc, I can do this without any problems. Assume I use PHP.
I faced a similar problem recently, I can't tell your for certain this is the best way to do it but it's the way i've found to work reliably. I tried BackboneRelational but was having troubles with it.
This assumes you will need to create the Quote object & ProductQuotation in 1 step.
Set up a view for New Quote
On initialization of this view:
A) Create a new empty Quote model
B) Create a new collection for ProductQuotes
C) Create a new ProductQuote view for each ProductQuote you're adding
D) Subscribe the Quote view to a custom Backbones event binding (Backbone JS: can one view trigger updates in other views?), i.e.
Backbone.pubSub.on('quote_new-product-save', this.AddProduct, this)
This view will now call AddProduct any time you trigger this event.
On initializing each ProductQuote view create a new Product model
Wire this view up for your user to fill in any applicable information & when they are done set this information to that views Product model & trigger the "quote_new-product-save" event mentioned above and pass it that product model.
Back in the Quote view, AddProduct will automatically be called as it was binded to this event. You should wire this to receive the new Product model & add it to the ProductQuotes collection.
So now you have your Product model data set to your ProductQuotes collection but this is still not directly linked to the current Quote (which still hasn't been saved) so set the 'order_items' attribute on your model to all models in your ProductQuote collection i.e.
this.model.set('product_quotes', this.collection.models)
Now your unsaved Quote model will have all members of your ProductQuotes collection set as an attribute.
Now you'll need to call save on the Quote model & send the data to the server. Things to keep in mind here is that your urlRoot is set properly & that the data being sent to the server is being properly formatted. I recommend reading Saving nested objects with Rails, backbone.js, and accepts_nested_attributes_for about overriding the toJSON method in your Quote model.