Sylius: Only one incomplete object in RequestStack through particular route - request

I am a Symfony beginner and I am writing a plugin for the e-commerce system Sylius: Every route up until now gave me two objects in RequestStack, and I was able to get a very particular variable everywhere through the one I retrieve through $requestStack->getMasterRequest().
In a particular route suddenly the variable (set in yaml file where the routes are configured) is not retrievable and the $requestStack doesn't hold two objects, only one.
I apologize, I know this is very badly explained, I hope someone can make sense of it.
I tried $request = Request::createFromGlobals() and retrieving the Container instead of the RequestStack directly, but both end up with the same result.
# This is the route I am trying to overwrite because I want to give it an extra parameter from the request:
sylius_shop_product_show:
path: /products/{slug}
methods: [GET]
defaults:
_controller: sylius.controller.product:showAction
_sylius:
template: "#SyliusShop/Product/show.html.twig"
repository:
method: findOneByChannelAndSlug_andVarFromRequest
arguments:
- "expr:service('sylius.context.channel').getChannel()"
- "expr:service('sylius.context.locale').getLocaleCode()"
- $slug
- "expr:service('request_stack')"
//This is the function which should be used, it is part of a Repository
public function findOneByChannelAndSlug_andVarFromRequest(ChannelInterface $channel, string $locale, string $slug, RequestStack $requestStack): ?ProductInterface
{
I don't understand why suddenly I cannot get a hold off the variable I can access through all the other routes. Because it is a repository? Is the request not yet completely processed?

Try to enter variable name with $ symbol before its name. For example if your variable name is myVar:
sylius_shop_product_show:
path: /products/{slug}
methods: [GET]
defaults:
_controller: sylius.controller.product:showAction
_sylius:
template: "#SyliusShop/Product/show.html.twig"
repository:
method: findOneByChannelAndSlug_andVarFromRequest
arguments:
- "expr:service('sylius.context.channel').getChannel()"
- "expr:service('sylius.context.locale').getLocaleCode()"
- $slug
- $myVar
How it works under the hood: https://github.com/Sylius/SyliusResourceBundle/blob/1.4/src/Bundle/Controller/ParametersParser.php#L55 Note: $request->get() method is alias to get variable from GET, POST and Symfony attributes.

I solved this myself yesterday. The problem was that I did not declare the sylius_shop_product_show in the correct scope of the route description which also declared the variable I was trying to pass through, thereby Symfony logically was not able to parse it and make it available. Well, seeing the solution right now it makes perfect sense, but before and the fact that I am a Symfony (and thus Sylius) beginner it was hard to understand what was wrong.
So I understood the problem when I executed php bin/console debug:router which listed all the available routes and when I discovered that the route sylius_shop_product_show actually is not creating a route where the variable I was looking for was even available in the routing-path. Thanks for everyone who tried to help me!

Related

Writing custom php script in joomla

I am good in php and javascript. I need a guidance where to place my custom php script if i make a ajax call from joomla.
I need to fetch the file names from a specific folder. I could make an ajax that will communicate with my php code and in return, my php code will give me the files of the specific folder.
Where is that php script to be place and how it should be routed.
For example
$.ajax({
url:'....../fetchfiles.php',
success:function(data){
}
})
Hope i was clear.
If I understood correctly your question my answer would be that you can place your fetchfiles.php wherever you want providing that you put right path to the file in your $.ajax call.
Then in the fetches.php you should call Joomla framework before you start your code, something like this:
// no direct access
define( '_JEXEC', 1 );
// get joomla root
$jpath_root = $_POST['jpath_root'];
//load Joomla
define( 'JPATH_BASE', $jpath_root );
require_once ( JPATH_BASE .'/includes/defines.php' );
require_once ( JPATH_BASE .'/includes/framework.php' );
jimport( 'joomla.application.application' );
jimport( 'joomla.filter.filteroutput' );
$japp = JFactory::getApplication('site');
/* now you are good to go with your code */
Just a few words about
// get joomla root
$jpath_root = $_POST['jpath_root'];
part.
My experience is that it is the best if you pass JPATH_ROOT variable via $.ajax( one way would be to have hidden input with value set to 'JPATH_ROOT' in your joomla file from where you call ajax and then in your ajax.js just pick that value up and pass to the ajax.php or fetches.php in your case)
You can define JPATH_BASE another way too, eg
define( 'JPATH_BASE', realpath(dirname(__FILE__)));
or
define( 'JPATH_BASE', realpath(dirname(__FILE__).'/../../..' ));
depending on your actual files structure but be aware that this way you practically redefined original JPATH_BASE constant and that it may cause conflicts in case you call, later within your code, some third party component functions/classes which may depend on original Joomla defined constants ...
I've learned it hard way with ZOO Component and my ajax calls ... :)
Hope this makes some sense.
Based on where you want to show the results you can create a component or a module (you can also easily include the module in an article to print the result in component position).
In the case of module:
https://docs.joomla.org/J3.x:Creating_a_simple_module/Developing_a_Basic_Module
Obviously your ajax call will be in tmpl/default.php and your php script in the module folder, simply you have to include it in the file list in mod_helloworld.xml. Then zip your folder and install it using Module Manager.
In case of problem with your jquery code, you have to use the noConflict() mode.

Getting incorrect paths in Restangular. What am I doing wrong?

Here is a miniature proof of concept. It fetches thing #100 and then saves it.
var things = ThingsAPI.all("things");
things.one(100).get()
.then(function(thing) {
thing.put();
})
First it makes a GET request to
http://localhost:8080/things/100
but after that it PUTs to
http://localhost:8080/things/100/100
I would expect it to PUT to the same URL it came from, instead it's treating the url http://localhost:8080/things/100 as a list and then trying to find entity 100 within it.
I just want this to PUT back to http://localhost:8080/things/100. What am I doing wrong?
EDIT:
If I fetch with this instead, the PUTting works. But I would have expected to be able to do this with the all method.
ThingsAPI.one('things', 100).get()
And, for clarity, here is where I define ThingsAPI.
app.factory('ThingsAPI', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setBaseUrl('http://localhost:8080/');
});
});
The reason is that you are treating the 100 as a nested resource for things. Therefore Restangular will generate routes as if http://localhost:8080/things/100 is the index route for the resource named 100 -- although it actually is the show route for things resource with id 100. These routes just accidentally happen to have the same URI.
As you can see, Restangular has misunderstood your intented resource definiton, and eg. PUT will generate an incorrect route.
Treating 100 as an identifier for things resource will correct the issue, as you seem to have found out: ThingsAPI.one('things', 100).get()
This translates to one(resource, identifier).get().

Controller Redirect issue in CakePHP

I have a controller with name users_controller, within the login action I want to redirect to my affiliate_redirect_controller.php, now I the following code in the users controller to redirect
$this->redirect(array(
'controller'=>'affiliate_redirect',
'action'=>'logRedirect' ));
And then I get the following error which I can't seem to resolve
Error: The requested address '/affiliate_redirect/logRedirect' was not found on this server.
I honestly do not know what this could be, quite new to cakePHP and none of the solutions found work for me.
the contents of affiliate_redirect_controller.php looks like this
class AffiliateRedirectController extends AppController
{
var $name = 'AffiliateRedirect';
function logRedirect(){
}
}
I can see there is a mistake in your code its because of naming convention.
$this->redirect(array(
'controller'=>'affiliate_redirects',
'action'=>'logRedirect' ));
Please see the above changes when you are writing your controller name in lowercase like above it should be plural affiliate_redirects and should not be affiliate_redirect
Apart from this you can use directly redirect as like this also.
$this->redirect('affiliate_redirects/logRedirect');
Please try, it should work.
Do you have a table in your database that corresponds to affiliate redirect controller?
You might want to rethink your logic, and use CakePHP routes to set the URL to what you want. Having a controller named affiliate_redirect_controller doesn't follow CakePHP's naming conventions.
Since I don't know exactly what you're trying to do, I don't know if this will work for you, but maybe consider redirecting to a separate action in UsersController like /users/affiliate_redirect/
Or you can create an AffiliatesController and then redirect to /affiliates/redirect/
Also, if you don't have debug mode set to 2, you should do that. It may help reveal what the actual issue is.
What debug level do you have in app/config/core.php ? Most of the time, when you get the message
Error: The requested address '/controller/action' was not found on this server.
it means you have a debug level set to 0 and increasing it to 1 or 2 allows to get more details about the error.

CakePHP Routing Alias, no prefix

I have a dashboard with a series of widgets. Per specification, the widgets need to be buried under a /widgets/ directory.
So I have added the following to my routes.php
Router::connect('/widget/:controller/:action/*', array());
But I seem to be running into trouble on widget/links/ and widget/links/view/1
I am new to CakePHP, but this doesn't seem all that impressive. I have yet to find anything in the Book or by search. So any help is appreciated.
Thanks.
Well...at the risk of stating the obvious...your route starts with /widget/, but you indicate that you're trying to access it via a plural URI (/widgets/). That's a problem. If that's just a typo, it would help to know what error you're seeing when you "run into trouble".
UPDATE:
Yes that was a typo. I corrected it. The error that appears for widget/links/ is: Error: WidgetController could not be found. It appears my index/default route is the main problem.
Given that information, it appears that CakePHP thinks that widget is your controller. Cake processes routes top down and finds the first one that matches. Ensure that you don't have a route above this one that looks something like /:controller/... or any other route above this one that starts with a variable.

cakephp and get requests

How does cakephp handle a get request? For instance, how would it handle a request like this...
http://us.mc01g.mail.yahoo.com/mc/welcome?.gx=1&.rand=9553121_pg=showFolder&fid=Inbox&order=down&tt=1732&pSize=20&.rand=425311406&.jsrand=3
Would "mc" be the controller and "welcome" be the action?
How is the rest of the information handled?
Also note that you could use named parameters as of Cake 1.2. Named parameters are in key:value order, so the url http://somesite.com/controller/action/key1:value1/key2:value2 would give a a $this->params['named'] array( 'key1' => 'value1', 'key2' => 'value2' ) from within any controller.
If you use a CNN.com style GET request (http://www.cnn.com/2009/SHOWBIZ/books/04/27/ayn.rand.atlas.shrugged/index.html), the parameters are in order of appearance (2009, SHOWBIZ, books, etc.) in the $this->params['pass'] array, indexed starting at 0.
I strongly recommend named paramters, as you can later add features by passing get params, without having to worry about the order. I believe you can also change the named parameter separation key (by default, it's ':').
So it's a slightly different paradigm than the "traditional" GET parameters (page.php?key1=value1&key2=value2). However, you could easily add some logic in the application to automatically parse traditional parameters into an array by tying into how the application parses requests.
CakePHP uses routes to determine this. By default, the routes work as you described. The remainder after the '?' is the querystring and it can be found in $this->params['url'] in the controller, parsed into an associative array.
Since I found this while searching for it, even though it's a little old.
$this->params['url']
holds GET information.
I have tested but it does work. The page in the Cakephp book for it is this link under the 'url' section. It even gives an example very similar to the one in the original question here. This also works in CakePHP 1.3 which is what I'm running.
It doesn't really use the get in the typical since.
if it was passed that long crazy string, nothing would happen. It expects data in this format: site.com/controller/action/var1/var2/var....
Can someone clarify the correct answer? It appears to me that spoulson's and SeanDowney's statements are contradicting each other?
Would someone be able to use the newest version of CakePHP and get the following url to work:
http://www.domain.com/index.php/oauth/authorize?oauth_version=1.0&oauth_nonce=c255c8fdd41bd3096e0c3bf0172b7b5a&oauth_timestamp=1249169700&oauth_consumer_key=8a001709e6552888230f88013f23d5d004a7445d0&oauth_signature_method=HMAC-SHA1&oauth_signature=0bj5O1M67vCuvpbkXsh7CqMOzD0%3D
oauth being the controller and authorize being a method AS WELL as it being able to accept the GET request at the end?

Resources