CakePHP Variable containing an array of models becomes inaccessible? - php

So I'm building this small REST API for a part of a website so I can load comments asynchronously, after the main content has loaded. But every time my dataset goes above 25 entries the variable where I store the comments becomes completely inaccessible.
This is exactly the database find operation I'm doing:
// A nice default before responding
$response = array('status'=>'error','message'=>'Request incomplete');
// [...] Some validation stuff
// $response is perfectly accessible here
$response = $this->Comment->find(
'threaded',
array(
'conditions' => array(
'Comment.object_class' => $query['object_class'],
'Comment.object_id' => $query['object_id'] ,
'Comment.status' => 'approved'
),
'order' => 'Comment.created ASC'
// No limits, I need all the comments
)
);
// $response is not accessible anymore
// So my JSON response below comes absolutely empty;
$this->set('response',$response);
$this->set('_serialize',array('response'));
By the time I use $this->set('_serialize',array('response')); to be able to send the JSON response the $comments variable is still inaccessible, so my response comes back empty, at 0 length, which of course is pretty bothersome and very confusing.
I've experienced this problem before and have found that it solves by requesting a limited set of entries, but in this case I need the entire comment list, don't wanna do several requests and kill the purpose. Is there a limit to what Cake can retrieve from the database and keep usable in the Controllers? Am I missing something here?
I also tried "manually " doing a json_encode($response); but since the problem is that the $response var is inaccessible/empty then of course it fails as well.
The json response does work for some 25 comments or less, but many of the website entries have more comments than that, up to 100 comments! How can I solve this weird issue?

So after souting the Internet in search of a concrete answer and ending up in the #cakephp IRC channel, a very kind fellow suggested my data may have some encoding mistakes.
Turns out he was correct about it, and the comments table still had some comments that were encoded as latin1. Back in the day I moved the database to utf8, but it was just a charset change, not an actual text encoding conversion for every entry.
After a quick search I found this post which instructs you about how to move loads of data from latin1 to utf8 with three simple cli lines.
I hope this serves someone else that may encouter this issue and doesn't know what to do about it :)
Thanks to those who commented on the question.

Related

PHP getting remote url image file size doesn't wait for content-length header to be set

I know this question has been asked millions of times, but please actually take the time to understand my problem before marking as duplicate or closing.
So I am using the following code. For some reason it gets all of the correct header information the first time I run the code EXCEPT for content-length. The second time I run the code it actually gets it correctly. I am retrieving the images from Facebook API if that changes anything.
function remote_filesize($url) {
$data = get_headers($url, 1);
if(isset($data['Content-Length'])) {
return (int) $data['Content-Length'];
}
else {
return -1;
}
}
Edit
Gotta love when you get downvoted with no explanation. Personally I think it should be required to provide a reason.
Anyway, this is still an issue, but in case anyone googling this needs a solution for getting the remote filesize, I would suggest using this awesome snippet from the PHP docs http://php.net/manual/en/function.filesize.php#114952
Sounds like a server caching issue.
So you may have to issue a full GET request instead of just a HEAD request.
Also, maybe check different casing -- 'content-length:' -- lowercase.

Youtube API v3 missing "creation date" in request

I'm trying to make Youtube v3 Data API work on my website.
I shamelessly copied this code from google's code samples, and it is not working. The error message showed is this:
An client error occurred: All cacheable requests must have creation dates.
I previously had issues with API keys as I forgot almost everything about APIs in general and I just thought this sample would have been useful to remember things. I managed to generate the appropriate key and now I know for sure it isn't the real problem.
Sadly Google didn't find posts related to this issue, except two links to the actual Php Library that I implemented in my site to make everything work. By looking at it closely I noticed a developer comment that could be useful.
$rawDate = $resp->getResponseHeader('date');
$parsedDate = strtotime($rawDate);
if (empty($rawDate) || false == $parsedDate) {
// We can't default this to now, as that means future cache reads
// will always pass with the logic below, so we will require a
// date be injected if not supplied.
throw new Google_Exception("All cacheable requests must have creation dates.");
}
I can understand english pretty well but I really don't know what to do now.
I even tried to add some sort of date in the request in my code, but it isn't working (you can laugh):
// Call the search.list method to retrieve results matching the specified
// query term.
$searchResponse = $youtube->search->listSearch('id,snippet', array(
'q' => $_GET['q'],
'maxResults' => $_GET['maxResults'],
'date' => strtotime(),
));
An client error occurred: (list) unknown parameter: 'date'
Any tips? Thank you in advance
EDIT: I know, this PHP library is currently in beta, but there must be some workaround.
EDIT 2: I found a temporary work around. I inverted the logic gate of that 'if' in the Php Library and now it works. But I don't like doing this, and I won't mark this as solved. At least if you know the reason of the bug please explain it to me, I'm really interested.

parse_url giving host name as stars when debugged (but can still get value)

Using PHP 5.5.12
Using CakePHP 2.6.7
Running
debug($url); // output = "http://google.co.uk"
debug(parse_url($url));
/* output = array(
'host' => '*****',
'scheme' => 'http'
)
*/
I had been using this without trouble but now copy/pasting a section of my code to have it as method (to save repeating myself) has started giving me this output. But testing it back in the same place I had it originally gives me this output too.
Can anyone explain why the hostname is stars and why the rest of the array doesn't appear (I realise all other elements should be expected to be NULL)?
Edit
Just tried it again with a url that had a path to a page after the host. The path shows up fine but the host is still starred out.
Partial Answer
Just thought to try debug(parse_url($url)['host']) and it prints the host correctly. I realised that the other elements would only be set if they exist in the url.
However, can anyone explain why printing out the array prints several stars instead of the hostname even though it is definitely stored there?
The reason this happens is because of how debug() works. Many moons ago people were not pleased that they could accidentally have their database credentials dumped out in error pages (which use the same underlying code as debug()). Because of this, debug() and Debugger::export() blacklist a set of array keys that could have database credentials. The following keys are replaced with ***'s:
password
login
host
database
port
prefix
schema

CakePHP find method crashes on live server when more than a few entries

I'm encountering a strange error in CakePHP and I have no idea how to figure out what is going on.
I am using a Ajax request to load dynamic data for a dataTable and it works perfectly on my localhost. For some reason I can't get it to work on my live server when I have more than a few entries.
After debugging I found that it's the find function that is not working. When I have more than a few entries in my response array than one of the arrays('SollProject') is just simply completely empty and the whole script stops working.
Here is my Code:
$project = $this->Project->find("first", array('conditions'=>array('id'=>$project_id) ,
'contain' => array(
'SollProject' => array(
'conditions'=> array(
'SollProject.date >=' => $year.'-01-01',
'SollProject.date <=' => $year.'-12-31'
)
),
'HabenProject'=> array(
'conditions'=> array(
'HabenProject.date >=' => $year.'-01-01',
'HabenProject.date <=' => $year.'-12-31'
)
))));
Any idea what I am doing wrong here or why it is not working on the live server? There is no afterFind method in case you were wondering.
Maybe I should mention that I tried error debugging already and I don't get any error messages. I also tried the same sql code on my sql server and it works perfectly. There is also no memory issues since the memory I'm using is way beyound what I'm usually using and it's only a json response.
The function itself also works for small entries (not more than maybe 5 entries) but as soon as I have a little bit more entries in the database it just crashes.
The interesting thing is that I can debug($project['HabenProject']) and it shows me all HabenProject but if I try debug($project['SollProject']) or just debug($project) the variable is just empty. It's not even declared as array. There is just no output. The rest of the page is still showing.
Basic debugging steps:
Set debug to 2
Check your CakePHP apps logs
Check the php logs
Check the webserver logs
However, I guess it's a memory limit and debug is off, that's probably why you get a white page. Check the memory usage and increase the php memory limit.
Ok, after lots of debugging it looks like I found the problem:
For some reason every entry with an Umlaut (äüö) in the database produced an error that caused the result array of the find function to not work anymore.
Turns out the problem was the live server database utf-8 encryption was commented off...

How does get_headers work in the background

I tryied searching for this and I belive I alredy know the answer but it's crusal that I'm not wrong, so here I go..
When calling get_headers, will I retrieve the whole file even though the function only returns the headers or will it retrieve, as expected, only the headers and nothing else?
I'm guessing the last but if I'm wrong this will cause some serious problems..
Also I noticed that there is a global setting I can change to send a HEAD request instead of the default GET request, witch is why I'm asking my self whats really going on.
Edit
Maybe this function is a better alternative? stream_get_meta_data or do they actually do the same thing?
You could also take a look at the source code, if you are familiar with C.
The function is defined here. I quickly looked over this, and it seems it is a header-only request, see line 715:
STREAM_ONLY_GET_HEADERS
GET
Requests a representation of the specified resource. Requests using
GET should only retrieve data and should have no other effect. (This
is also true of some other HTTP methods.) The W3C has published
guidance principles on this distinction, saying, "Web application
design should be informed by the above principles, but also by the
relevant limitations."
HEAD
Asks for the response identical to the one that would correspond to a
GET request, but without the response body. This is useful for
retrieving meta-information written in response headers, without
having to transport the entire content.
Wikipedia/Hypertext_Transfer_Protocol
The PHP-docs clearly states that normal get_headers() uses a GET-request, but you can force it to use HEAD instead, like this:
<?php
// By default get_headers uses a GET request to fetch the headers. If you
// want to send a HEAD request instead, you can do so using a stream context:
stream_context_set_default(
array(
'http' => array(
'method' => 'HEAD'
)
)
);
$headers = get_headers('http://example.com');
?>
Unfortunaley you're right, just read the PHP manual:
get_headers() returns an array with the headers sent by the server in response to a HTTP request.
Also take a look at the examples.
Okay, next time I should spend more attention to the question formulation.
Yeh, if the request type is set to GET (standard) you will get the whole content. You could change it to HEAD, but this is not what you want.

Categories