I have a mapped Fat-Free Framework class declared as follows in my index.php:
$f3->map('/user', 'User');
The User class looks like this:
<?php
class User {
function __construct($f3) {
$this->users = new \DB\SQL\Mapper($f3->db, 'users');
}
function get($f3) {
return json_encode('Just some text');
}
function post($f3) {
// There is tested, working code in here but I've omitted it for simplicity's sake
}
function put($f3) {
}
function delete() {
}
}
I have my Javascript first loaded by app.js like this:
$(document).ready(function(){
var currentPage = $(location).attr('pathname'),
requiredJS = document.createElement('script'),
requiredJS.type = 'text/javascript';
switch(currentPage) {
case '/mypage':
requiredJS.src = 'myscript.js';
$('body').append(requiredJS);
break;
// more cases...
}
});
Then my simple AJAX call in mypage.js looks like this:
$.get('/user', function (data) {
console.log(data);
});
When I go to the /mypage route, I get only an empty string in my console. Why is this happening? Where am I messing up?
You should echo the result:
echo json_encode(array('Just some text'));
Related
I wrote an user action analysis but I can't execute my insert into statement. I tried all suggestion on stack can't but figure out my mistake, I don't even get an error: it is running through without executing the statement. I have also an connection php - this works fine so the fault is not there. I would like to insert the action var later but at first I have to call the function. So whats wrong with my request or php function?
jQuery
$( document ).ready(function() {
var action = '';
document.addEventListener('click', function(e) {
e = e || window.event;
e = e.target || e.srcElement;
if (e.nodeName === 'SECTION') {
action = e.id;
updateAction();
}
}, false);
function updateAction() {
$.ajax({
type: "POST",
url: '../actions/userAction.php',
data: {action: 'test'},
success: function(){
console.log(action);
}
});
}
});
PHP
<?php
class userAction
{
/* User Action */
public function updateAction(){
if(isset($_POST['action']) && !empty($_POST['action'])) {
$db = getDB();
$st = $db->prepare("INSERT INTO user_analysis (action) VALUES ('bla') where userID = 1945");
$st->execute();
$db = null;
$_SESSION['uid']=$uid;
return true;
} else
{
return false;
}
}
}
?>
Where do you call updateAction() method? I assume you don't. Then why do you expect that it will execute? You have at least 3 ways to deal with it.
1. Make the method static and call it without instantiating a class
If you don't have any reason to construct an object of your class then you can call your method without doing it. Just add this line of code after your class definition:
userAction::updateAction()
This way you call the method which handles your POST request.
2. Instantiate your class and then call your method
The same story as above. The difference here is to construct an object first:
$ua = new userAction();
$ua->updateAction();
3. (the easiest) Get rid of the class and method
As the title suggest. Remove whole code of a class and leave only the body of your method. Like this:
if(isset($_POST['action']) && !empty($_POST['action'])) {
$db = getDB();
$st = $db->prepare("INSERT INTO user_analysis (action) VALUES ('bla') where userID = 1945");
$st->execute();
$db = null;
$_SESSION['uid']=$uid;
return true;
} else {
return false;
}
This should be the whole content of your file: a condition.
BTW
1. Your query is not valid. If you want to UPDATE a row you need to use UPDATE statement, not INSERT
2. I would suggest you call your class UserAction (uppercase). Just to make it standardised and more intuitive
3. Why do you mix jQuery with VanillaJS? You use jQuery and bind an event using clear JS. Make it semantic and decide if you use jQuery or not.
jQuery way:
var action = '';
$(document).on('click', function(e) {
e = e || window.event;
e = e.target || e.srcElement;
if (e.nodeName === 'SECTION') {
action = e.id;
updateAction();
}
});
That's all. I hope I could help
You need to use UPDATE instead of INSERT. Try this below code:
UPDATE user_analysis SET action = 'bla' WHERE id = 1945
if(isset($_POST['action']) && !empty($_POST['action'])) {
echo $_POST['action'];
}
echo the value of $_POST['action'] inside your if loop...If not getting try to change the - type: "POST", to "GET",
I've inherited a website with an obscure PHP framework called syndrome for which I can't find any documentation, but the problem I'm trying to solve should be fairly simple for a good PHP developer.
I am trying to make ajax requests from javascript to a php file to execute a particular function. The ajax request is simply:
loadNewImage = function(){
$.ajax({ url: '/app/library/Controller/Reel.php',
data: {action: 'test'},
type: 'post',
success: function(output) {
alert(output);
}
});
}
The current PHP file is structured like this:
<?php
class Controller_Reel extends BaseController_Web {
protected function defaultAction() {
parent::getPage($this->template, 'home');
$homepage = Homepage::getInstance()->getHomepage();
$this->template->title = 'Homepage';
$this->template->image = $homepage['asset_image'];
$this->template->center = array('reel');
$this->setResponse($this->template);
}
}
What I want to do is add to the file a check for post data. I'm not good with PHP, but I tried:
<?php
if(isset($_POST['action']) && !empty($_POST['action'])) {
echo 'TEST POST';
}
class Controller_Reel extends BaseController_Web {
protected function defaultAction() {
parent::getPage($this->template, 'home');
$homepage = Homepage::getInstance()->getHomepage();
$this->template->title = 'Homepage';
$this->template->image = $homepage['asset_image'];
$this->template->center = array('reel');
$this->setResponse($this->template);
}
}
I'm assuming that's maybe because the check for post data is not happening within the class itself, but I'm not exactly sure how to structure the code. Can anybody help straighten me out?
UPDATE: I found this inside a file called ControllerSite.php -> (of which baseController_Web is extended:
protected function respond() {
switch($this->response_type) {
case self::RESPONSE_PAGE:
// always try to make ie use the latest rendering engine
case self::RESPONSE_TEXT:
Helper_Request::respond($this->processed_response, Helper_Request::RESPONSE_PRINT, Config::$platform);
break;
case self::RESPONSE_JSON:
Helper_Request::respond($this->processed_response, Helper_Request::RESPONSE_JSON, Config::$platform);
break;
case self::RESPONSE_REDIR:
Helper_Request::respond($this->processed_response, Helper_Request::RESPONSE_REDIR, Config::$platform);
break;
case self::RESPONSE_CONTENT:
// TODO: we'll need to figure the out, but don't need to worry about it for now
break;
}
return $this;
}
and then in Controller.php (of which ControllerSite.php is extended), this:
final private function execute() {
$action = $this->getMethodName();
$is_ajax = Helper_Request::isAjax();
$data_type = strtolower(Helper_Request::setDefault($_SERVER['HTTP_ACCEPT'], ''));
if($is_ajax && preg_match('/\w+\/json|\w+\/javascript/i', $data_type) && method_exists($this, $action . 'JsonAction')) {
// it there was a ajax json request and the ajax json specific method exists, execute it
return $this->{$action . 'JsonAction'}();
}
return $this;
}
Try this:
class Controller_Reel extends BaseController_Web {
protected function defaultAction() {
parent::getPage($this->template, 'home');
$homepage = Homepage::getInstance()->getHomepage();
$this->template->title = 'Homepage';
$this->template->image = $homepage['asset_image'];
$this->template->center = array('reel');
if(isset($_POST['action']) && !empty($_POST['action'])) {
$reponse['success'] = true;
$response['responseVal'] = 'This is a test';
$this->setResponse($response);
} else {
$this->setResponse($this->template);
}
}
}
Try to make a class method named testAction:
protected function testAction() {
parent::getPage($this->template, 'home');
$homepage = Homepage::getInstance()->getHomepage();
$this->template->title = 'Homepage';
$this->template->image = $homepage['asset_image'];
$this->template->center = array('reel');
$this->setResponse($this->template);
}
In ajax request you are trying to send action parameter with test value and i suppose it is the framework's duty to call the related method named with 'test' .
This may hep.
I got a script to check if a URL is present in a page. Here it is:
class LP_backlinkchecker
{
var $url;
var $content;
var $links;
var $linktocheck;
function __construct($url, $linktocheck)
{
$this->url = $url;
$this->linktocheck = $linktocheck;
}
function SetLinktocheck($link)
{
$this->linktocheck = $link;
}
function getContents()
{
$this->content = file_get_contents($this->url);
}
function lpFetchLinks()
{
$regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
preg_match_all("/$regexp/siU", $this->content, $matches);
$this->links = $matches;
return $matches;
}
function check()
{
foreach($this->links[2] as $key => $url)
{
if($url == $this->linktocheck)return TRUE;
}
return FALSE;
}
}
My problem is that the script only works for checking links on the same site. It does not work when the links to check is outside of the website. For example, the script works well to check the link
http://web.com/linktocheck present on the website http://web.com/
If think my $regexp is wrong, do you have some idea of the problem ?
Thanks for your help.
Not sure if I have misunderstood your issue but your code seems to work for me. I wrote you a little unit test that you can now have and expand upon, if you could write a test that does not work I might be able to help more.
class LP_backlinkcheckerTest extends PHPUnit_Framework_TestCase
{
public $l;
public function setUp()
{
$this->l = new LP_backlinkchecker('test.html', null);
}
public function tearDown()
{
}
public function testGetContents()
{
$this->l->getContents();
$this->assertNotEmpty($this->l->content);
}
public function testlpFetchLinks()
{
$this->l->getContents();
$matches = $this->l->lpFetchLinks();
$expected = array(
"http://google.com",
"http://www.bluesnews.com",
"http://www.bluesnews.com/somepage"
);
// 4 things captured by the regex
$this->assertEquals(4, count($matches));
$this->assertEquals($expected, $matches[2]);
}
}
and the HTML file I am using
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
Google.com
BluesNews.com
somepage
</body>
</html>
Although it would be better to make your class so that I don't have to supply it a file but that's the way you designed it. I would also suggest perhaps using parse_url to breakdown the url into it's component parts. Your problem may be just that your expecting one string to be equal to the other and there may be a user input error at construct time which your not checking at all.
I am using a script with jQuery:
$(document).ready(function () {
var button;
var line;
var inputs;
var params = {};
var updatefield;
$('button.update').click(function () {
button = $(this);
params['button'] = button.val();
line = button.closest('.line');
updatefield = line.find('td.resultFromGet');
inputs = line.find('input');
inputs.each(function (id, item) {
switch($(item).attr('type')){
case 'checkbox':{
params[$(item).attr('name')] = new Array($(item).is(':checked'));
break;
}
default:{
params[$(item).attr('name')] = new Array($(item).attr('value'));
break;
}
}
});
//alert(JSON.stringify(params, null, 4));
$.get( 'core/ajax/correct_exec.php', params )
.done(function (data){
if(data == '1'){
$(updatefield).html('UPDATE_RECORD_SUCCESS');
} else {
$(updatefield).html( data );
}
});
});
});
The page I am getting is doing echo '1'; from PHP in case of success.
I try to test this with data == 1 but it doesn't work even though it is a success. In fact, it sends me $(updatefield).html( data ); which is 1. So why can't it just print UPDATE_RECORD_SUCCESS?
The data response is coming with white space, if you use trim() function something like this, then if condition should be executed.
if(data.trim() == '1'){
$('#updatefield').html('UPDATE_RECORD_SUCCESS'); //this should be executed
} else {
$('#updatefield').html( data );
}
Here you can see the space with data in chrome debugger.
We are having an issue in the following javascript code.
doCallback function is happening before doMainProcess gets finished.
So every time we get result = null in the doCallback.
Is there a way to pause load of the doCallback to wait until we get the result ?
Edit: setResult is happening multiple times and is asynchronous via iframe, and we don't know timing. Also callback only happens some of the time decided by another process.
So we can not simply change the position of doCallback.
<html>
<head>
<script>
var result;
var callback = "callback";
var url = "http://www.example2.com/getResponse/";
function iframeCallback() {
var iframe = document.createElement('iframe');
iframe.style.border='0px';
iframe.style.width ='0px';
iframe.style.height='0px';
document.body.appendChild(iframe);
var iDocument;
if (iframe.contentDocument) {
iDocument = iframe.contentDocument;
} else if (iframe.contentWindow) {
iDocument = iframe.contentWindow.document;
} else if (iframe.document) {
iDocument = iframe.document;
}
var content = "<script type='text/javascript'>";
content += "var jsText = \"<script type='text/javascript' src='" + url + "'></\" + \"script>\";";
content += "document.write(jsText);";
content += "</"+"script>";
content += "<script type='text/javascript'>";
content += "var data = eval('"+callback+"');";
content += "window.parent.setResult(data);";
content += "</"+"script>";
iDocument.open();
iDocument.write(content);
iDocument.close();
}
function setResult(data) {
result = data;
}
function doMainProcess() {
iframeCallback()
}
function doCallback() {
//we need to wait here until we get the result.
alert(result);
}
</script>
</head>
<body>
<script>
doMainProcess();
</script>
<script>
doCallback();
</script>
</body>
<html>
Yes,
delete this:
<script>
doCallback();
</script>
Change this:
function setResult(data) {
result = data;
}
to this:
function setResult(data) {
result = data;
doCallback();
}
A clunky solution (that doesn't involve my having to read your code carefully):
var readyForCallback = false;
function doMainProcess() {
// your code here
readyForCallback = true;
}
function doCallback(arg1,arg2,arg3,etc) {
if (!readyForCallback) {
// anonymous function as way to keep the original callback
// argument(s) with a timeout
setTimeout(function(){doCallback(arg1,arg2,arg3,etc);},20);
return;
}
// your code here
}
Note: within your timeout function you could also use doCallback.apply() with the arguments object to automatically handle any number of arguments, but I didn't include this in my code because off-hand I forget whether you can just use the arguments object directly or if you'd have to first create a proper array populated from arguments.