I have an application which allows users to create wishes. I use the title of each wish to make an api request to unsplash to download a picture. I now have the problem, that a user can enter a title which doesnt return any images from unsplash. In this case I'd like to use a placeholder image but my code stops after getting an 404 error. Is there a way to ignore this error and just continue my loop?
public function fetchImagesFromUnsplash() {
$wishes = $this->repository->findAll();
foreach ($wishes as $wish) {
try {
$response = $this->httpClient->request('GET', 'https://api.unsplash.com/photos/random', [
'query' => [
'query' => $wish->getDescription(),
'client_id' => 'oa1DsGebE8ehCV9SrvcA1mCx-2QfvnufUKgsIY5N0Mk'
]
]);
} catch (TransportExceptionInterface $e) {
}
if ($response) {
$data = $response->getContent();
$data = json_decode($data, true);
$imageLink = $data['urls']['raw'];
$rawImage = file_get_contents($imageLink);
if ($rawImage) {
file_put_contents("public/images/" . sprintf('imageWish%d.jpg', $wish->getId()), $rawImage);
$wish->setImagePath(sprintf('public/images/imageWish%d.jpg', $wish->getId()));
} else {
$wish->setImagePath('placeholder.png');
}
$this->em->flush();
}
}
}
EDIT:
I tried this:
public function fetchImagesFromUnsplash() {
$wishes = $this->repository->findAll();
foreach ($wishes as $wish) {
try {
$response = $this->httpClient->request('GET', 'https://api.unsplash.com/photos/random', [
'query' => [
'query' => $wish->getDescription(),
'client_id' => 'oa1DsGebE8ehCV9SrvcA1mCx-2QfvnufUKgsIY5N0Mk'
]
]);
} catch (NotFoundHttpException $e) {
}
if ($response) {
$data = $response->getContent();
$data = json_decode($data, true);
$imageLink = $data['urls']['raw'];
$rawImage = file_get_contents($imageLink);
if ($rawImage) {
file_put_contents("public/images/" . sprintf('imageWish%d.jpg', $wish->getId()), $rawImage);
$wish->setImagePath(sprintf('public/images/imageWish%d.jpg', $wish->getId()));
} else {
$wish->setImagePath('placeholder.png');
}
}
}
$this->em->flush();
}
but it still stops after the first 404
As per the documentation:
When the HTTP status code of the response is in the 300-599 range
(i.e. 3xx, 4xx or 5xx) your code is expected to handle it. If you
don't do that, the getHeaders() and getContent() methods throw an
appropriate exception
You have to check the $response->getStatusCode(), or prepare to handle a ClientException (representing 4xx status codes).
Related
I found this article on doing asynchronous requests with Goutte:
https://victor.4devs.io/en/web-scraping/scraping-data-with-goutte.html
However, it's from 2017 and it seems to be out of date. Using some code based on that article:
use Goutte\Client;
$goutte = new \Goutte\Client();
$client = $goutte->getClient();
foreach ($randomurls as $url) {
$futureResponse = $client->get($url, ['future' => true]);
$futureResponse->then(function ($response) {
echo $response->getBody();
});
}
I get the error, "Call to undefined method Goutte\Client::getClient()". Based on this thread:
Call to undefined method Goutte\Client::setClient()
I tried:
use Goutte\Client;
use Symfony\Component\HttpClient\HttpClient;
$goutte = new Client(HttpClient::create(['timeout' => 60]));
$client = $goutte->getClient();
foreach ($randomurls as $url) {
$futureResponse = $client->get($url, ['future' => true]);
$futureResponse->then(function ($response) {
echo $response->getBody();
});
}
But I still got the same error. I then tried without the getClient():
use Goutte\Client;
use Symfony\Component\HttpClient\HttpClient;
$client = new Client(HttpClient::create(['timeout' => 60]));
foreach ($randomurls as $url) {
$futureResponse = $client->get($url, ['future' => true]);
$futureResponse->then(function ($response) {
echo $response->getBody();
});
}
But then I got, "Call to undefined method Goutte\Client::get()", as now Goutte uses request(). So then I tried:
use Goutte\Client;
use Symfony\Component\HttpClient\HttpClient;
$client = new Client(HttpClient::create(['timeout' => 60]));
foreach ($randomurls as $url) {
$futureResponse = $client->request('GET', $url, ['future' => true]);
$futureResponse->then(function ($response) {
echo $response->html();
});
}
However, I then get, "Call to undefined method Symfony\Component\DomCrawler\Crawler::then()". I couldn't find any information about that error.
Is it still possible to make asynchronous requests in Goutte after the Goutte updates from a couple years ago?
I try to add a custom user field to the user by using WPGraphQL. Therefore I tried to recreate the example in the official WPGraphQL documentation https://docs.wpgraphql.com/extending/fields/#register-fields-to-the-schema :
add_action('graphql_init', function () {
$hobbies = [
'type' => ['list_of' => 'String'],
'description' => __('Custom field for user mutations', 'your-textdomain'),
'resolve' => function ($user) {
$hobbies = get_user_meta($user->userId, 'hobbies', true);
return !empty($hobbies) ? $hobbies : [];
},
];
register_graphql_field('User', 'hobbies', $hobbies);
register_graphql_field('CreateUserInput', 'hobbies', $hobbies);
register_graphql_field('UpdateUserInput', 'hobbies', $hobbies);
});
I already changed the type from \WPGraphQL\Types::list_of( \WPGraphQL\Types::string() ) to ['list_of' => 'String'].
If I now execute the updateUser mutation my hobbies don't get updated. What am I dowing wrong?
Mutation:
mutation MyMutation {
__typename
updateUser(input: {clientMutationId: "tempId", id: "dXNlcjox", hobbies: ["football", "gaming"]}) {
clientMutationId
user {
hobbies
}
}
}
Output:
{
"data": {
"__typename": "RootMutation",
"updateUser": {
"clientMutationId": "tempId",
"user": {
"hobbies": []
}
}
}
}
Thanks to xadm, the only thing I forgot was to really mutate the field. I was a bit confused by the documentation, my fault. (I really am new to WPGraphQL btw)
Here's what has to be added:
add_action('graphql_user_object_mutation_update_additional_data', 'graphql_register_user_mutation', 10, 5);
function graphql_register_user_mutation($user_id, $input, $mutation_name, $context, $info)
{
if (isset($input['hobbies'])) {
// Consider other sanitization if necessary and validation such as which
// user role/capability should be able to insert this value, etc.
update_user_meta($user_id, 'hobbies', $input['hobbies']);
}
}
I am having problem to get session variable in header file. In my controller i have this code for login.
public function login(Request $request)
{
$inputs = $request->only('email', 'password');
//dd($request->input('email'));
$rules = array(
'email' =>'required',
'password' => 'required'
);
$validator = Validator::make($inputs, $rules);
if ($validator->fails()){
$messages = $validator->messages();
return redirect('login')
->withErrors($validator)
->withInput($request->except('password'));
} else {
if (auth()->attempt($inputs)) {
$is_admin = DB::table('users')
->where('email', $request->input('email'))
->first();
if ($is_admin->is_admin == 1) {
return redirect('/company_details');
} elseif ($is_admin->is_admin == 2) {
return redirect('dashboard');
} else {
dd('something wrong');
}
} else {
return redirect('login')->withErrors(['error' => 'Email or password donot match']);
}
}
}
I have a login form which in which my header file is include, and i have to get session variable in my header file. Like if a user is logged in, username or email should appear in place of login button.
Anyone please help me for this.
use Illuminate\Support\Facades\Session;
or
use Session
Set Session Variable
Session::Flash('message_key', 'Your Message');
return redirect('/yourmsgpage')
Show the session output
#if(Session::has('message_key'))
<div>
{{ Session::get('message_key' }}
</div>
#endif
Try this to get user session id
Auth::user()->id
I asked this on https://github.com/silexphp/Silex/issues/1442 but I have a feeling it isn't necessarily a code problem so I thought I would extend the reach.
upgrading to silex 2 and symfony 3 and all the rest...
routes are included at end of app.php and look something like this...
$app->get('/', 'queue.controller:indexAction')
->after(function (Request $request, Response $response, $app) {
$response->setPublic();
$response->setSharedMaxAge($app['cache']['s-maxage']);
})
->host($app['domains']['xxx'])
->bind('homepage');
this works great in a browser, goto homepage, works fine. If I am running phpunit though... I get the following error when trying to generate a route...
Symfony\Component\Routing\Exception\RouteNotFoundException: Unable to generate a URL for the named route "homepage" as such route does not exist.
and the test looks something like this...
public function testTargetingOnHomepage()
{
$client = $this->createClient();
echo $this->app->url('homepage');
.....
}
i am bewildered as to why my routes are not getting added to app when being executed from phpunit.
test case class has ...
class AdTargetControllerTest extends SomeWebTestCase
and that somewebtestcase.php looks like ...
<?php
namespace theapp\SomeFramework;
use Silex\WebTestCase;
use Fixtures\UserFixture;
use Symfony\Component\BrowserKit\Client;
use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage;
class SomeWebTestCase extends WebTestCase
{
public $youtubeEmbed;
private $mockSessionDir;
public function createApplication()
{
$appDir = __DIR__.'/../../..';
$app = include "$appDir/app.php";
$app['debug'] = true;
$app['session.test'] = true;
$this->mockSessionDir = $app['tmpdir']. '/mocksessions';
$app['session.storage.test'] = function ($app) {
return new MockFileSessionStorage($app['tmpdir']. '/mocksessions');
};
unset($app['exception_handler']);
// Emails get stored in the mail "logger" ... not delivered.
$app['mailer.logger'] = function ($app) {
return new \Someecards\SomeFramework\MessageLogger();
};
// Force silex to use transport and not spooltransport
$app['swiftmailer.use_spool'] = false;
$app["swiftmailer.transport"] = function ($app) {
return new \Swift_Transport_NullTransport($app['swiftmailer.transport.eventdispatcher']);
};
$app->extend('mailer', function ($mailer, $app) {
$mailer->registerPlugin($app['mailer.logger']);
return $mailer;
});
$this->youtubeEmbed = '<iframe width="480" height="270" src="https://www.youtube.com/embed/';
$this->youtubeEmbed .= 'LDtHJYa6xu4?feature=oembed" frameborder="0" allowfullscreen></iframe>';
// using Mockery since this library uses a static method for create
$app['oembedMock'] = \Mockery::mock('alias:Embed\Embed');
$app['oembedMock']
->shouldReceive('create')
->andReturn(
(object) array(
'title' => 'Oembed title',
'description' => 'Oembed Description',
'providerName' => 'YouTube',
'code' => $this->youtubeEmbed,
'type' => 'video',
'author' => 'test',
'authorUrl' => 'test',
'width' => 500,
'height' => 500,
'image' => 'test',
'imageWidth' => 500,
'imageHeight' => 500
)
);
$app->boot();
return $app;
}
there are other functions here but thats the important one i believe.
phpunit bootstraps with ...
<?php
use theapp\SomeFramework\TestingUtil;
// autoload libraries
require_once __DIR__.'/../thirdparty/vendor/autoload.php';
TestingUtil::init();
and then testingutil.php looks like ...
namespace Someecards\SomeFramework;
class TestingUtil
{
public static function init()
{
// This if/else allows the phpunit processIsolation flag to be set to true.
// We're not currently doing that because it slows things down three fold.
// If you see errors about too many open connections/files you can run
// ulimit -n 10000, try to close db connections and log files (couldn't fclose
// these in tearDowns for some reason), or turn on processIsolation.
if (!defined('PHPUNIT_HAS_BOOTSTRAPED')) {
self::bootstrap();
define('PHPUNIT_HAS_BOOTSTRAPED', true);
}
}
public static function bootstrap()
{
$app = require __DIR__.'/../../../app.php';
$app->boot();
$dbOptions = $app['db.options'];
if ($dbOptions['driver'] == 'pdo_sqlite') {
$testdb = $dbOptions['path'];
if (file_exists($testdb)) {
#unlink($testdb);
}
$cacheDriver = $app['orm.em']->getConfiguration()->getMetadataCacheImpl();
$cacheDriver->deleteAll();
$cacheDriver = $app['orm.em']->getConfiguration()->getResultCacheImpl();
$cacheDriver->deleteAll();
$cacheDriver = $app['orm.em']->getConfiguration()->getQueryCacheImpl();
$cacheDriver->deleteAll();
$tool = new \Doctrine\ORM\Tools\SchemaTool($app['orm.em']);
$classes = $app['orm.em']->getMetadataFactory()->getAllMetadata();
$tool->createSchema($classes);
$loader = new \Doctrine\Common\DataFixtures\Loader();
$loader->loadFromDirectory(__DIR__ ."/../../Fixtures");
$purger = new \Doctrine\Common\DataFixtures\Purger\ORMPurger();
$executor = new \Doctrine\Common\DataFixtures\Executor\ORMExecutor($app['orm.em'], $purger);
$executor->execute($loader->getFixtures());
}
register_shutdown_function(
function ($app) {
$path = $app['orm.default_cache']['path'];
if (is_dir($path) === true) {
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path),
\RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($files as $file) {
if (in_array($file->getBasename(), array('.', '..')) !== true) {
if ($file->isDir() === true) {
rmdir($file->getPathName());
} elseif (($file->isFile() === true) || ($file->isLink() === true)) {
unlink($file->getPathname());
}
}
}
rmdir($path);
} elseif ((is_file($path) === true) || (is_link($path) === true)) {
return unlink($path);
}
},
$app
);
}
}
I have this code and I want to add duplication error catch in it, how can I?
if (!$row_id) {
// insert a new
if ($wpdb->insert($table_name, $args)) {
return $wpdb->insert_id;
}
} else {
// do update method here
if ($wpdb->update($table_name, $args, array('id' => $row_id))) {
return $row_id;
}
}