S3 SDK Breaking my site - php

My problem:
require_once '/includes/aws-sdk-1.5.2/sdk.class.php';
My environment:
I have a pretty standard PHP site that uses __autoload() to grab any classes that I need. However, I now need to include the SDK to send files over to S3, but simply requiring that library seems to throw off the scope of the entire app so that any code that follows is broken.
Example:
// Save to S3
require_once '/var/www/html/system/aws-sdk-1.5.2/sdk.class.php';
$s3 = new AmazonS3();
if( ! $s3->if_bucket_exists(S3_BUCKET) )
throw new Exception('S3 bucket does not exist.');
$response = $s3->create_object(S3_BUCKET, $temp_file['s_unique_name'], array(
'fileUpload' => $_FILES['my_file']['tmp_name'],
'acl' => $s3::ACL_PUBLIC
));
// Save file
$photo = new vehicle_photo();
$photo->i_vehicle = $i_vehicle;
$photo->s_file = $temp_file['s_url'];
$photo->s_label = $_FILES['my_file']['name'];
$photo->save();
So, with the // Save to S3 snippet enabled, the following vehicle_photo class can no longer be found, in addition to all other classes that may be used after this point. If I disable it, everything works.
What's happening here?

Sounds like the autoloading mechanisms are conflicting. You might find this helpful: https://forums.aws.amazon.com/thread.jspa?threadID=85239 . Additionally, spl_autoload_register is better than plain old __autoload - consider migrating your autoloader code to that.

Related

Get Response and Handle Errors for Google Cloud StorageClient $bucket->upload

I have just created my first app that talks to Google.
It currently successfully uploads to a bucket, everything is working nicely.
One thing I can't seem to find is good documentation on how to perform error handling when using StorageClient.
A simplified version of the code I'm using is below:
function test_bucket_upload($file_source)
{
$bucketName="my-bucket";
$objectName = "my-object";
$uploadName = "some-dir/{$objectName}";
$storage = new StorageClient();
$file = fopen($file_source, 'r');
$bucket = $storage->bucket($bucketName);
$object = $bucket->upload($file, [
'name' => $uploadName
]);
}
I can see in The Code for the upload function, that a new StorageClient object is returned but every time I try and access the response variables, I get a 500 internal server error.
I would like to be able to do a check on whether the upload succeeded.
I've had a pretty good look on the web but again, I can't seem to find any good documentation on how to perform this check.
Any Help would be much appreciated.
The PHP cloud storage library throws exceptions on error. Specifically it will through a subclass of GoogleException, e.g. BadRequestException, ConflictException, NotFoundException or ServerException.
To handle errors, use try { ... } catch (GoogleException $e) { ... } (or one of the sub-classes if you want to specifically handle 404 differently, for example).

Packaging a PHP application

I am trying to create a .phar file from my web application. Following the php documentation's example I tried the following for this purpose.
<?php
$srcRoot = __DIR__ . "/../app";
$buildRoot = __DIR__ . "/../build";
$p = new Phar("$buildRoot/build.phar", 0, 'build.phar');
$p->buildFromIterator(
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($srcRoot)
),
$srcRoot
);
However I got the following error. I dont have any idea about the error. What is wrong with the code?
PHP Fatal error: Uncaught exception 'UnexpectedValueException' with message
'Iterator RecursiveIteratorIterator returned a path "D:\site\app" that is
not in the base directory "D:\site\app"'
in D:\site\tools\create-phar.php:7
The source of the problem is that RecursiveDirectoryIterator also lists the dot files - . and ...
When iterating over /path/to/foo it also lists /path/to/foo/. and /path/to/foo/.. which goes to the parent directory - outside the base directory.
Thus you have to prevent the inclusion of the ".." files, which is most easily achieved with FilesystemIterator::SKIP_DOTS as second parameter to DirectoryIterator:
new RecursiveDirectoryIterator($srcRoot, FilesystemIterator::SKIP_DOTS)
(#cweiske -- I just realized you beat me to it, I'll make sure to refresh the page next time, my sincerest apologies!)
You need just a slight edit to skip over the unix paths /. and /..:
<?php
$srcRoot = __DIR__ . "/../app";
$buildRoot = __DIR__ . "/../build";
$p = new Phar("$buildRoot/build.phar", 0, 'build.phar');
$p->buildFromIterator(
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($srcRoot, FilesystemIterator::SKIP_DOTS)
),
$srcRoot
);
Box makes it very easy to create PHAR archives from your source files. Basically you first add a configuration file and then you can create your PHAR file by simply invoking box build on the command line.
There is a great blog post by Matthieu Moquet describing how he used Box to simplify the distribution of a PHP Cli application. Personally, I've also been using Box for a CLI application, however the official project description is not limited to CLI applications, but rather summarizes the Box project as:
An application for building and managing Phars.
The Box project provides the PHAR build script and takes care of setting all paths correctly, so this might solve your problem.
The solution proposed by #cweiske is brilliant. In some situations, however, you may need the ability to add more directory path exclusions. Have a look at this example that excludes any references to the .git directory, using FilterIterator:
// create phar
$p = new Phar($pharFile, 0, $pharFile);
// produce iteration which excludes any references to values assigned to $excludes
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)
);
$filter = new class($iterator) extends FilterIterator {
public static $excludes = [];
public function accept()
{
$item = $this->current();
$actual = 0;
foreach (self::$excludes as $exclude) {
$actual += (int) boolval(strpos($item->getPath(), $exclude));
}
return ($actual === 0);
}
};
$filter::$excludes = ['.git'];
$p->buildFromIterator($filter, $path);
Have a look at php.ini file to check the value of phar.readonly field.
It must be 0 to create phar archive.
Ref: http://php.net/manual/en/phar.configuration.php#ini.phar.readonly

Using FirePHP with Zend Framework 2

I'm trying to use FirePHP with Zend Framework 2, but there seems to be something missing. Here's the basic code I'm trying to run:
$writer = new Zend\Log\Writer\FirePhp();
$logger = new Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('FirePHP logging enabled');
The error I get is "FirePHP Class not found". I was initially puzzled because I do have a FirePhp class in my Zend/Log/Writer folder. But then I saw that the class constructor requires a FirePhp\FirePhpInterface object. So I checked the Zend/Log/Writer/FirePhp folder and there's a FirePhpBridge class in there that implements FirePhpInterface, but it also requires a FirePHP instance in the constructor. I don't have any FirePHP.php file in my Zend/Log/Writer/FirePhp folder. Am I supposed to get this from somewhere else?
Update
I now have managed to get FirePHP working, but I'm trying to figure out how to do it in a clean way so this works. The only way I've gotten it to work is putting it in the root directory of my project and doing the following:
include_once('FirePHP.php');
$writer = new Zend\Log\Writer\FirePhp(new Zend\Log\Writer\FirePhp\FirePhpBridge(FirePHP::getInstance(true)));
$logger = new Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('FirePHP logging enabled');
I assume that normally I should be able to create a writer like so:
$writer = new Zend\Log\Writer\FirePhp();
However, where this goes wrong I believe is in the getFirePhp() function of the Zend\Log\Writer\FirePhp class. The class does this:
if (!$this->firephp instanceof FirePhp\FirePhpInterface
&& !class_exists('FirePHP')
) {
// No FirePHP instance, and no way to create one
throw new Exception\RuntimeException('FirePHP Class not found');
}
// Remember: class names in strings are absolute; thus the class_exists
// here references the canonical name for the FirePHP class
if (!$this->firephp instanceof FirePhp\FirePhpInterface
&& class_exists('FirePHP')
) {
// FirePHPService is an alias for FirePHP; otherwise the class
// names would clash in this file on this line.
$this->setFirePhp(new FirePhp\FirePhpBridge(new FirePHPService()));
}
This is where I get lost as to how I'm supposed to set things up so that this class_exists('FirePHP') call finds the right class and new FirePHPService() also works properly.
First you should add this code to Module.php of your module
return array(
//...
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
),
);
and here content of autoload_classmap.php
<?php
return array(
'FirePHP' => realpath(APPLICATION_PATH . '/vendor/FirePHP').'/FirePHP.php',
);
FirePHP.php(renamed from FirePHP.class.php) downloaded from official site.
then you can write below code in any place of your module and it will work
use Zend\Log\Writer\FirePhp;
use Zend\Log\Logger;
$writer = new FirePhp();
$logger = new Logger();
$logger->addWriter($writer);
$logger->info("hi");
Am I supposed to get this from somewhere else?
Yes, you need to get FirePHP into your project and autoloading.
If you're using composer (and I recommend that you do), just add:
"firephp/firephp-core" : "dev-master"
(or similar) in your composer.json and update. If you're not using composer, you should grab the firephp libs, and let your autoloader know about them.

How to install the AWS SDK in Yii

I would like to use the Amazon AWS SDK for PHP in my Yii project, however I get all kinds of include errors (such as include(CFCredentials.php): failed to open stream: No such file or directory ).
I think it may be related to Yii's assumption that class names must match file names...
What can we do??
I've made that:
spl_autoload_unregister(array('YiiBase', 'autoload'));
require_once PATH_TO_AWS_SDK . 'sdk.class.php';
// I write down in PATH_TO_AWS_SDK.'config.inc.php' my CFCredentials
spl_autoload_register(array('YiiBase', 'autoload'));
$amazon_opts = array(
'curlopts' => array(
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_FORBID_REUSE => false,
),
);
$amazon = new AmazonSES();
$response = $amazon->get_send_quota($amazon_opts);
This worked beautifully:
// Include the SDK
Yii::import('application.vendors.aws.*');
spl_autoload_unregister(array('YiiBase', 'autoload'));
require_once 'sdk.class.php';
spl_autoload_register(array('YiiBase', 'autoload'));
// Instantiate the AmazonEC2 class
$ec2 = new AmazonEC2();
In case someone stumbles upon this issue, I've found that if one is using the PHAR file directly (poor decision, I know) and importing via require_once, you cannot call spl_autoload_register to re-add YiiBase autoload until after your SDK call is complete.
At least this was our case when using the StsClient to call assume role with an IAM role.
This is more easier way, You can use Yii S3 Upload extension.
http://www.yiiframework.com/extension/s3upload/

How to use Zend Service Amazon?

I've been doing a lot of digging around and have ended up with a huge headache and no success. I am trying to use the Zend Amazon Service (within my Codeigniter framework) to fetch information about a book using its ISBN. I initially tried it with Zend 1.12 but I kept getting an error about missing parameter AssociateTag. I am now trying with Zend 2.0 but still getting problems.
This is the code I am using within my controller:
set_include_path(get_include_path() . PATH_SEPARATOR . 'site/libraries');
require_once 'Zend2/Loader/StandardAutoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();
$amazon = new Zend_Service_Amazon('[apikey]', 'US', '[secretkey]');
$item = $amazon->itemLookup('B0000A432X');
I get the following error:
Fatal error: Class 'Zend_Loader_Autoloader' not found.
My questions are:
How can I load the correct autoloader?
Where do I include the associate tag in the parameters? There is no mention of it in the outdated zend user guide
Zend 2.0 doesn't even seem to have the amazon service files or even the /service folder. What does this mean?
Note: The demo included with zendservice-amazon doesn't work as is. Requests must include your App ID, Secret Key, and Associate Tag which the demo script doesn't do by default. It took me a while to figure this out, without these, all queries throw an exception saying the HTTP response status was 400. Unfortunately the exception doesn't have the response body which says what parameters were missing.
Here is some code that will get you started with ZF2 and ZendService\Amazon.
To start, let me outline the directory structure of where I will be putting files for this example:
testing
|-Zend
|---Crypt
|---Escaper
|---Http
|---I18n
|---Loader
|----+AutoloaderFactory.php
|----+... more files
|----+StandardAutoloader.php
|-----Exception
|---Stdlib
|---Uri
|---Validator
|-ZendRest
|-ZendService
|---Amazon
|-----Authentication
|-------Exception
|-----Ec2
|-------Exception
|-----Exception
|-----S3
|-------Exception
|-----SimpleDb
|-------Exception
|-----Sqs
|-------Exception
|----+AbstractAmazon.php
|----+...more files
|----+SimilarProduct.php
|-+test.php
The gist is I have created a directory called testing where we will place the ZF2 autoloader as well as the Amazon classes and their dependencies. Under testing is a Zend folder that contains the autoloader (in Loader) and also a ZendService folder where the Amazon service goes.
First, we need to get a copy of the autoloader from ZF2. Part of the reason you were having trouble is because it looks like you are using the ZF1 autoloader which is incompatible with ZF2. To get the Autoloader from ZF2, you can download the latest ZF2 package and copy the Loader directory from ZendFramework-2.0.x/library/Zend/ into the Zend folder we created in the testing directory.
Now that we have the autoloader files, let's grab the Amazon service files. I'll write a detailed answer on how to use Composer to get the latest package, but for now I'll explain how to get it manually. To get the full list of available ZF2 packages, load up the JSON file at http://packages.zendframework.com/packages.json In it find, zendframework/zendservice-amazon, determine the highest version available from the list, and grab the corresponding dist. EDIT As of 11th Jul 2013, this is the latest zendservice-amazon package.
From the library directory in ZendService_Amazon-2.0.2.zip, copy the entire ZendService directory into the testing directory. You now have the ZF2 Amazon service files.
Next, take care of the dependencies. From the ZF2 library, copy the directories, Crypt, Escaper, Http, I18n, Json, Stdlib, Uri, and Validator into the Zend directory inside testing.
You will also need the ZendRest package. Copy the ZendRest folder from library from the ZendRest package to testing/ZendRest.
Now for some code. Create test.php inside the testing folder with the following contents:
<?php
require_once './Zend/Loader/StandardAutoloader.php';
$autoloader = new Zend\Loader\StandardAutoloader(array(
'namespaces' => array(
'Zend' => dirname(__FILE__) . '/Zend',
'ZendRest' => dirname(__FILE__) . '/ZendRest',
'ZendService' => dirname(__FILE__) . '/ZendService',
),
'fallback_autoloader' => true));
$autoloader->register();
$tag = 'prdesign-20'; // replace with your Amazon app ID
$appId = '1JT2V3QNEHDAMKYR5F02'; // replace w/ your access key from https://portal.aws.amazon.com/gp/aws/securityCredentials
$secretKey = 'Qgjeiw39f8UNzjJgeerrgDs1a193du/v7djDAtn/x';
$query = new ZendService\Amazon\Query($appId, 'US', $secretKey);
$query->Category('Books')->Keywords('PHP')->AssociateTag($tag);
$result = $query->search();
foreach($result as $item): ?>
<div class="item">
<?php echo $item->Title ?>
by <?php if (is_array($item->Author)): ?>
<?php echo implode(', ', $item->Author) ?>
<?php else: ?>
<?php echo $item->Author ?>
<?php endif; ?>
</div>
<?php endforeach; ?>
First, we require_once the StandardAutoloader class from ZF2. Once the autoloader is registered, this is the only class you have to manually include.
Next, we create a new autoloader and pass some options. This tells the autoloader where classes in the namespace Zend and ZendService are located. We tell the autoloader they live in the respective folders in our current directory. Change dirname(__FILE__) to the correct path as needed. The fallback_autoloader option tells the autoloader to look for classes of any namespace or vendor in the include_path.
Calling $autoloader->register(); then actually registers the autoloader we set up within PHP. Setting up the autoloader is now finished.
The next 3 lines define some required parameters for the API.
The next 3 lines are straightforward, we now create a new instance of ZendService\Amazon\Query and pass our Amazon app ID and secret key. We then build the query by specifying to search in the Books Category and set the Keywords to be PHP. We also add the required AssociateTag. Finally, we execute the search.
I haven't yet used ZendService\Amazon yet so I can't provide detailed instructions on using the class but the included demo script should get you started with sending basic queries to Amazon and processing the results.
Hope that helps.
i have use Amazon AWS S3 bucket along with Zend Framework. A simple example is photo upload to amazon AWS Bucket.In you application/config/application.ini file
;AWSAccessKeyId= "AccessKey"
;AWSSecretKey= "SecretKey"
;AWSS3BucketName = "zoshare-images"
;AWSS3GetImageUrl = "http://[name].s3.amazonaws.com/[folder]/"
Lets say you want to upload an image to bucket, below is sample code of controller
public function updateAction()
{
if($_FILES["fuPic"]["size"] > 0 || $_FILES["fuPre"]["size"] > 0)
{
$config = Zend_Registry::get('config');
$s3 = new Zend_Service_Amazon_S3($config['AWSAccessKeyId'],$config['AWSSecretKey']);
$bucketName = $config['AWSS3BucketName'];
if($_FILES["fuPic"]["size"] == 0)
unset($_FILES["fuPic"]);
else if($_FILES["fuPre"]["size"] == 0)
unset($_FILES["fuPre"]);
$s3->removeObject($bucketName."/[folder]/".$campaignModel->getCampaignId().'_pic_'.$campaign_olddata->getPicture());
$s3->removeObject($bucketName."/[folder]/".$campaignModel->getCampaignId().'_pre_'.$campaign_olddata->getPreview());
if (isset($_FILES["fuPic"]))
{
$filename = $campaignModel->getCampaignId().'_pic_'.$_FILES["fuPic"]['name'];
$s3->putObject($bucketName."/[folder]/".$filename, file_get_contents($_FILES["fuPic"]["tmp_name"]),
array(Zend_Service_Amazon_S3::S3_ACL_HEADER =>
Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ));
$data['picture'] = $_FILES["fuPic"]['name'];
}
if (isset($_FILES["fuPre"]))
{
$filename = $campaignModel->getCampaignId().'_pre_'.$_FILES["fuPre"]['name'];
$s3->putObject($bucketName."/[folder]/".$filename, file_get_contents($_FILES["fuPre"]["tmp_name"]),
array(Zend_Service_Amazon_S3::S3_ACL_HEADER =>
Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ));
$data['preview'] = $_FILES["fuPre"]['name'];
}
}
}
Happy Coding !!!!

Categories