Closed girvo closed 9 years ago
Your method is correct. When you specify a field name, the name is the meta key
used to save the data in the database. So on the front-end, when calling the update_post_meta
, simply specify the same key name of your field.
The framework do not alter key names so you're safe.
Beautiful! Now I just need to figure out why my Form is giving a "No route found" error :(
// routes.php
// Contact page
Route::get('page', ['contact', 'uses' => 'PagesController@getContact']);
Route::post('page', ['contact', 'uses' => 'PagesController@postContact']);
Indeed that's weird. Can you show me the form code?
<div class="contact-form">
@include('partials.formsuccess')
@include('partials.formerrors')
{{ Form::open() }}
<div class="row">
<div class="col-md-2">
{{ Form::label('name', 'Your name: <i class="required">*</i>') }}
</div>
<div class="col-md-10">
{{ Form::text('name', '', ['placeholder' => 'Your Name', 'required' => true]) }}
</div>
</div>
<div class="row">
<div class="col-md-2">
{{ Form::label('email', 'Your email: <i class="required">*</i>') }}
</div>
<div class="col-md-10">
{{ Form::email('email', '', ['placeholder' => 'you@example.com', 'required' => true]) }}
</div>
</div>
<div class="row">
<div class="col-md-2">
{{ Form::label('phone', 'Your phone number:') }}
</div>
<div class="col-md-10">
{{ Form::input('tel', 'phone', '', ['placeholder' => '0x xxxx xxxx']) }}
</div>
</div>
<div class="row">
<div class="col-md-2">
{{ Form::label('message', 'Your query: <i class="required">*</i>') }}
</div>
<div class="col-md-10">
{{ Form::textarea('message', '', ['placeholder' => 'Write your query here...', 'required' => true, 'rows' => 10]) }}
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-offset-2">
{{ Form::submit('send', 'Send Enquiry') }}
</div>
</div>
{{ Form::close() }}
</div>
The PagesController::postContact()
method just does return "yep!";
currently, and it still gives a "404" error
Have you turned on the permalinks?
I have, and I just reset it again just in case that was the problem. Bit of a weird one to be honest, I'm nearly 100% certain it was working previously!
Okay interesting, using httpie
I can get it to hit the route, but it seems the form refuses to go through to it?
dbyd-themosis [master●] http POST http://dbyd.docker/contact
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Length: 11
Content-Type: text/html; charset=UTF-8
Date: Mon, 07 Sep 2015 19:38:22 GMT
Keep-Alive: timeout=5, max=100
Link: <http://dbyd.docker/?p=10>; rel=shortlink
Server: Apache/2.4.7 (Ubuntu)
X-Pingback: http://dbyd.docker/cms/xmlrpc.php
X-Powered-By: PHP/5.5.9-1ubuntu4.11
Hello world
The form output is below:
<div class="contact-form">
<form action="http://dbyd.docker/contact/" method="POST" accept-charset="UTF-8"><input type="hidden" id="_themosisnonce" name="_themosisnonce" value="bc6a3c88c2" /><input type="hidden" name="_wp_http_referer" value="/contact/" /> <div class="row">
<div class="col-md-2">
<label for="name">Your name: <i class="required">*</i></label> </div>
<div class="col-md-10">
<input placeholder="Your Name" required="1" type="text" name="name" value=""> </div>
</div>
<div class="row">
<div class="col-md-2">
<label for="email">Your email: <i class="required">*</i></label> </div>
<div class="col-md-10">
<input placeholder="you@example.com" required="1" type="email" name="email" value=""> </div>
</div>
<div class="row">
<div class="col-md-2">
<label for="phone">Your phone number:</label> </div>
<div class="col-md-10">
<input placeholder="0x xxxx xxxx" type="tel" name="phone" value=""> </div>
</div>
<div class="row">
<div class="col-md-2">
<label for="message">Your query: <i class="required">*</i></label> </div>
<div class="col-md-10">
<textarea name="message" placeholder="Write your query here..." required="1" rows="10" name="message"></textarea> </div>
</div>
<div class="row">
<div class="col-xs-12 col-md-offset-2">
<button type="submit" name="send">Send Enquiry</button> </div>
</div>
</form></div>
And I've just ruled out something funky with the sessions, cleared my cache, everything. It seems that if it's coming from a browser it's refusing to work, which is weird as hell. I'll try removing my .htaccess
and regenerating it just in case, and I'll let you know. Sorry for the spam -- trying to get this project out the door!
EDIT: Nope, regenerated the .htaccess
and it's still exactly the same issue unfortunately.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
And what happens if you add the page ID in the route:
Route::post('page', [['contact', 10], 'uses' => 'PagesController@postContact']);
Does it catch it? Which version of the framework are you using? 1.1.2? or latest from master branch?
Also does a Route::any()
catches your requests?
Adding the page ID to the route didn't work, and using Route::any()
gives the same error. Using Paw or HTTPie with ?p=10
instead of the page name gives a 404 as well
EDIT: Also, a POST
request in Paw gives the correct result. It's just anything through the browser fails for some reason :/
I just saw that you wrote PagesController::postContact()
method returns 'yep'. In order to be sure, your postContact
method should not be static:
public function postContact()
{
return 'yep';
}
Yeah that was just a bad wording of it :) It's definitely not static!
So, I've worked around the issue thus far.
I have a custom /admin/api.php
route condition, that links in a custom routing system that I wrote for Lean (a framework for Hack). I just enabled it, and sure enough I can POST from the form to it. It breaks the Wordpress loop however (it's meant for JSON API's) -- so I'll have to work around that for now.
// admin/api.php
<?php
/**
* Custom routing system test
*/
global $matches;
function is_api_route(array $params) {
global $matches;
if (count($params) === 0 || !is_string($params[0])) {
throw new Exception('Invalid route definition');
}
$route = buildRoute($params[0]);
$path = $_SERVER['REQUEST_URI'];
$results = testRoute($path, $route['regex'], $route['vars']);
if ($results === null) {
return false;
}
// Dirty global
$matches = $results;
return true;
}
function buildRoute($url) {
if ($url === '/') {
$result = array('regex' => '/^\/$/', 'vars' => []);
return $result;
}
$split = explode('/', $url);
$regex = '/^\/';
$vars = [];
// Now iterate over the exploded items, check if they're req vars, and set up the results
foreach ($split as $item) {
$item = (string) $item;
if ($item === '') {
continue;
}
$varName = isRequestVariable($item);
if ($varName !== null) {
$vars[] = $varName;
$regex .= '([\w+-]+)';
} else {
$regex .= $item;
}
$regex .= '\/';
}
$regex .= '?$/';
return array('regex' => $regex, 'vars' => $vars);
}
function isRequestVariable($item) {
if (preg_match('/^\:\w+$/', $item)) {
// remove colon for var name
return substr($item, 1);
}
return null;
}
function testRoute($requestUri, $routeRegex, $routeVars) {
$matches = [];
$result = preg_match($routeRegex, $requestUri, $matches);
if (count($matches) > 0) {
$data = array_slice($matches, 1);
$capture = array_combine($routeVars, $data);
if ($result) {
return $capture;
}
}
return null;
}
add_filter('themosisRouteConditions', function() {
$conds['api'] = 'is_api_route';
return $conds;
});
Usage is as follows:
// routes.php
Route::get('page', ['contact', 'uses' => 'PagesController@getContact']);
Route::post('api', ['/contact', 'uses' => 'PagesController@postContact']);
That works well enough, but setup_postdata
doesn't seem to fix the @loop
even setting the global $post
to be the right object:
public function postContact() {
// Dirty workaround for broken routing in Themosis
global $post;
$page = get_post(10);
$post = $page;
setup_postdata($post);
// ...
You wrote the route is_api_route
in order to catch the default contact page? not sure to follow along...
Anyway, in order to fix the main loop, its the main query you need to modify. The route system is using WordPress conditions to see which request to listen to. It doesn't check the URI as WordPress uses query parameters behind the scene.
If you want to alter the default main query, you need to hook to the pre_get_posts
action. Also note the each route callback and controller method give you the main $post
and $query
instances.
So in your method:
public function postContact($post, $query)
{
// $post is already the \WP_Post instance for the contact page
setup_postdata($post);
}
Now you could simply run a new WP_Query and pass it to your view so you don't really care about the main loop.
I had already written the api
post condition as a test (and had it turned off), I reenabled it to help try and debug what's going on with the Route::post
problem. From the looks of it, for whatever reason the route condition of post('page')
doesn't work when in a Form
context -- I will see if I can replicate it in a fresh install for you.
Does the permalink setup need to be set to anything in particular?
This is very strange as I just put online a new client website for forms and used the same routing to handle it. Is there any other Route::post calls in your routes.php?
The permalink is needed if you pass string parameters to the route condition. Keeping default, you'll need to use post/page IDs. So no, just any permalink option is fine.
Also, do you have another custom post type with a contact
uri somewhere? Also, I just remembered you can't use some name attributes values for your form as these terms are reserved for WordPress:
I suspect your input with name=name
. Try to pre-fix all your input and let me know how it goes?
Is your issue resolved regarding POST request for your contact page?
Not yet, I've ruled out the contact slug being the issue by recreating it with a new slug (not editing it, deleting from the DB and recreating) -- I'm going to prefix the field names in an hour or so and will get back to you :)
Sent from my iPhone
On 11 Sep 2015, at 8:53 pm, Julien Lambé notifications@github.com wrote:
This is very strange as I just put online a new client website for forms and used the same routing to handle it. Is there any other Route::post calls in your routes.php?
The permalink is needed if you pass string parameters to the route condition. Keeping default, you'll need to use post/page IDs. So no, just any permalink option is fine.
Also, do you have another custom post type with a contact uri somewhere? Also, I just remembered you can't use some name attributes values for your form as these terms are reserved for WordPress:
https://codex.wordpress.org/Reserved_Terms I suspect your input with name=name. Try to pre-fix all your input and let me know how it goes?
— Reply to this email directly or view it on GitHub.
Okay, so.
I completely deleted the database, and set the entire site up from scratch again. The Form::open()
call is exactly that, and my routes.php
file is as follows;
<?php
/*
* Define your routes and which views to display
* depending of the query.
*
* Based on WordPress conditional tags from the WordPress Codex
* http://codex.wordpress.org/Conditional_Tags
*
*/
// Base pages
Route::get('front', 'PagesController@home');
Route::get('page', ['about', 'uses' => 'PagesController@about']);
// Contact page
Route::get('page', ['contact', 'uses' => 'PagesController@getContact']);
Route::post('page', ['contact', function($page) {
return "Hello world!";
}]);
// Blog archive
Route::get('page', ['blog', 'uses' => 'BlogController@index']);
// Portfolio and project pages
Route::get('page', ['portfolio', 'uses' => 'PortfolioController@index']);
Route::get('singular', ['project', 'uses' => 'PortfolioController@project']);
I have once again stepped through the code -- and as soon as I press submit on the form, it gives me a routing error 404 once more. I have prefixed the contact-input's fields, and the portfolios fields. Nothing I do seems to fix it, and I'm at a loss here.
Crucially, if I POST to the page via HTTPie
or Paw
, it works, but with the Form it does not.
I'm going to send you an email with a link to the code if that's okay? I can't work out what's gone wrong, it seems like a bug but I've run out of places to look at in my own code.
Cheers, Josh
@jlambe
I am officially an idiot, however I think this is something that should probably be noted in the Form
documentation.
For some reason I thought that prefixing the field names on my custom post types would fix it. It was the fact that I had a Form::text('name')
field that caused the problem.
Sorry about that!
@girvo Glad you resolved your issue. I will mention it in the new documentation but I think I'll add this #207 ticket to release 1.2.0. This will warn developers if they use a WordPress reserved term for inputs or custom fields ;-)
Hey there,
Quick question. If I have a custom post type, with a Metabox and set of Fields on said custom post type, and I want to have anonymous users submit (in this case, the custom post type is a ContactInput, with a contact form on the actual site that I want to create a new post) to, how do I ensure I fill in the Metabox's Fields?
Basically, if the user submits a Form, I want to map those Form fields to a corresponding new Post with a custom post type and a set of Fields and save the new post. From the looks of it, I should be able to with
wp_insert_post
andupdate_post_meta
, but I'm unsure what the meta key of the fields would be?Cheers, Josh