I'm working in WP using PHP and trying to reduce the load time of a function that gets a lot of data. I thought transients would work, and (as shown below) I loaded the course query in transients, but it doesn't work with the foreach statement, or rather, I don't know how to set it up correctly to make it work.
The main piece of code that slows everything down is the foreach statement, which gets the Vimeo video id for each topic, runs it through the vimeo_api() function, then gets the duration of the video, and then appends it to the topic id inside an array .
Technically I don't have to have the get_vimeo_duration_all_courses() function (it calls all courses/courses/topics) but just get the Vimeo ID from each topic on load This is what I have The way it started, it did work, but unfortunately it increased my page load time. My idea is that if I can load all the durations within the array and append each duration to the topic ID, then I don't have to call the vimeo_api() function every time I want to get the video duration. I could also update the $vimeo variable once a day and then search the $vimeo variable for the topic ID to get the vimeo duration.
So I guess I'd like to know if I'm going in the right direction or if you know of a better way?
Is there a way to store the $vimeo variable and all the values inside it so that the vimeo_api() function doesn't have to be run every time?
Any help would be great! Thanks
function get_vimeo_duration_all_courses($vimeo) { $courses = get_transient('all_courses'); if (false === $courses) { $courses = new WP_Query(array( 'posts_per_page' => -1, 'post_type' => 'sfwd-courses', 'no_found_rows' => true, 'cache_results' => true, 'ignore_sticky_posts' => true, 'fields' => 'ids', )); //Grabs all the courses set_transient('all_courses', $courses, (24 * HOUR_IN_SECONDS)); } $vimeo = get_transient('all_vimeo_durations'); if (false === $vimeo) { $vimeo = array(); foreach ($courses->posts as $course_id) { $lessons = learndash_course_get_lessons($course_id); //Gets all the lessons under the course foreach ($lessons as $lesson) { $topics = learndash_course_get_topics($course_id, $lesson->ID); //Gets all the topics under the lesson foreach ($topics as $topic) { $vimeoVideo = get_field('lesson_video', $topic->ID); if (!empty($vimeoVideo)) { //Looks at each topic and determines whether it has a vimeo video or not $vimeoDuration = vimeo_api($vimeoVideo); //If true, it runs the vimeo ID through the vimeo_api() function (THIS IS WHERE IT BECOMES SLOW) $vimeo[$topic->ID] = $vimeoDuration; } } } } set_transient('all_vimeo_durations', $vimeo, (24 * HOUR_IN_SECONDS)); } return $vimeo; } function show_vimeo_duration($topicID) { return $vimeo[$topicID]; //Returns the value of the vimeo_api() function that matches the topicID }
Here is where I get the Vimeo api and return the video duration
function vimeo_api($id) { try { $authorization = 'CODELEFTOUTONPURPOSE'; $ch = curl_init(); curl_setopt_array($ch, array( CURLOPT_URL => "https://api.vimeo.com/videos/$id?fields=duration", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => array( "authorization: Bearer {$authorization}", "cache-control: no-cache", ), )); $res = curl_exec($ch); $obj = json_decode($res, true); return $obj['duration'];//Returns the duration of the video } catch (Exception $e) { return "0"; } }
P粉7574324912024-04-04 10:04:36
It makes no sense to store the object returned by WP_Query in a transient. This object is used to control WordPress loops. But using transients like all_video_durations
does make sense, very much. Transient will persist the data of any php array or object.
Transients are great for caching hard-to-get values, such as those obtained from the video service API. They work on all WordPress installations and run faster in installations with persistent object caching.
You may want to use separate transients for each video item rather than bundling them together. This will make your code work a little better if you add new projects.
(Additionally, if you use WordPress's built-in Request class instead of cURL, your code will run on a WordPress installation on a hosting service that does not handle cURL correctly. If you submit your cURL code to plugin repository, reviewers will ask you to replace it. Sometimes ask me how I know this :-)
P粉7606754522024-04-04 00:29:41
Thanks for your suggestions, they really helped me move in the right direction. I ended up removing the function that calls all classes and built in a cache file that hosts all Vimeo IDs and durations. Then when I call the function it first searches the cache file and if it finds the Vimeo ID it gets the duration but if it doesn't find the ID it runs the API.
The following is the final code...
function vimeo_api($vimeoID) { $vimeoCacheUrl = WP_CONTENT_DIR . '/cache/vimeo-duration-cache.txt'; $newData = ''; $vimeoData = array(); $vimeoCache = file($vimeoCacheUrl); $vimeoCache = array_unique($vimeoCache); file_put_contents($vimeoCacheUrl, implode($vimeoCache), LOCK_EX); foreach ($vimeoCache as $key => $value) { $data = explode(',', $value, 2); $vimeoData[$data[0]] = $data[1]; } if (isset($vimeoData[$vimeoID])) { return $vimeoData[$vimeoID]; } else { try { $authorization = 'XXXX'; $ch = curl_init(); curl_setopt_array($ch, array( CURLOPT_URL => "https://api.vimeo.com/videos/$vimeoID?fields=duration", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => array( "authorization: Bearer {$authorization}", "cache-control: cache", ), )); $res = curl_exec($ch); $obj = json_decode($res, true); $newData = $vimeoID . ',' .$obj['duration']; file_put_contents($vimeoCacheUrl, str_replace("'", '', var_export($newData, true)) . PHP_EOL, FILE_APPEND | LOCK_EX); return $obj['duration']; } catch (Exception $e) { return "0"; } } }