How to declare a static variable with base url in Yii - yii

I am using a variable
$path = Yii::app()->basePath.'/../images1/';
in many functions of a controller. How can i declare it as global?

In your main.php config you may use params.
...
// application-level parameters that can be accessed
// using Yii::app()->params['paramName']
'params' => require(__DIR__ . '/params.php'),
In params.php, for example.
return [
...
'imagesPath' => __DIR__ . '/../../images1/',
];
PHP 5.3+ required to use __DIR__ constant.
With PHP 5.2 you may use dirname(__FILE__) expression.

Related

Web push notification example with PHP backend

I am looking for an example for web push notification with JS code and PHP backend. Can anyone share example code or a tutorial?
Here's a basic example that uses web-push-php : https://github.com/Minishlink/web-push-php-example
Main PHP code is:
<?php
require __DIR__ . '/vendor/autoload.php';
use Minishlink\WebPush\WebPush;
$auth = array(
'VAPID' => array(
'subject' => 'https://github.com/Minishlink/web-push-php-example/',
'publicKey' => 'BCmti7ScwxxVAlB7WAyxoOXtV7J8vVCXwEDIFXjKvD-ma-yJx_eHJLdADyyzzTKRGb395bSAtxlh4wuDycO3Ih4',
'privateKey' => 'HJweeF64L35gw5YLECa-K7hwp3LLfcKtpdRNK8C_fPQ', // in the real world, this would be in a secret file
),
);
$webPush = new WebPush($auth);
$res = $webPush->sendNotification(
$subscription['endpoint'],
"Hello!", // payload
$subscription['key'],
$subscription['token'],
true // flush
);
// handle eventual errors here, and remove the subscription from your server if it is expired
Hope this helps :)

Class 'KeenIO\Client\KeenIOClient' not found

I am including Keen in my product (code snippet below)
require INCLUDE_DIR . '/vendor/autoload.php'; // Autoloader for Composer (https://getcomposer.org/)
use KeenIO\Client\KeenIOClient;
class Statistics extends Model {
private $client;
public function __construct( $id = null ){
parent::__construct();
$this->client = KeenIOClient::factory([
'projectId' => KEEN_PROJECT_ID,
'writeKey' => KEEN_WRITE_KEY,
'readKey' => KEEN_READ_KEY
]);
}
...
but I continue to get an "Class 'KeenIO\Client\KeenIOClient' not found" error when the "KeenIOClient::factory" line runs. I was able to successfully install Keen.io through Composer - I feel it's something simple I'm missing - any ideas?
So I can't leave a comment, but I am wondering if there is maybe an issue with the include path? I was able to get this PHP snippet to work:
require 'vendor/autoload.php';
use KeenIO\Client\KeenIOClient;
$client = KeenIOClient::factory([
'projectId' => "53f3a8687d8cb95095000001",
'readKey' => "99a06e48fd7fb1279bc40995160eb0b61a9e0efaab8b651b029f0d895f77c0a804ba089282eff28bf8ad07f337422441d0542b7feaac9fea1e92fc153ee7efc51afad3276bda8d7754a338b349d540bfb402cba0dfdc82498c217054efd8abd0f47a0c0bc963bbdf0dc938c91b17d9f2"
]);
$count = $client->count('bitcoin-prices', [
'impressions' => [
'interval' => 'daily',
'timeframe' => 'this_30_days',
'group_by' => 'keen.timestamp'
]
]);
print_r($count);
That project id and read key are from the keen io open data sets (good to test with).

Yii Framework: setPathOfAlias() returns null

I am trying to put MaxMind's GeoIp2 into my Yii application. Basically, I copied the files under "src" (see previous link) under protected -> vendors -> maxmind. The folder structure under my application is the following:
protected
|---- vendors
|---- Zend
|---- maxmind
|---- Database
|---- Reader.php
|---- Model
|---- ...
|---- ...
After that, I created the path aliases into my index.php file:
Yii::setPathOfAlias('Zend', Yii::getPathOfAlias('application.vendors.Zend'));
Yii::setPathOfAlias('GeoIp2', Yii::getPathOfAlias('application.vendors.maxmind'));
The path works just fine for the 'Zend' alias, but it fails for 'GeoIp2' by returning null.
Yii::createApplication("FrontendApplication", $config)->run();
echo "Path 1: " . Yii::getPathOfAlias("Zend"). '<br />'; // Correct path!
echo "Path 2: " . Yii::getPathOfAlias("GeoIp2"). '<br />'; // <==== NULL
echo "Maxmind path: " . Yii::getPathOfAlias('application.vendors.maxmind'). '<br />'; // correct path
var_dump(is_dir(Yii::getPathOfAlias('application.vendors.maxmind'))); // true
Any ideas why this could happen?
Thanks!
getPathOfAlias() call to create path aliases are created in the constructor of CApplication. But the constructor wasn't called yet at the point when main.php is included.
To configure path aliases use the aliases property in your main.php. Like this:
return array(
'aliases' => array(
'GeoIp2' => 'application.vendors.maxmind',
),
...
Fixed! The solution:
Instead of calling setPathOfAlias() into the index.php file I added the aliases into my configuration file (i.e. protected -> config -> main.php), as paramaters, like this:
$config = array(
'import' => array(),
'components' => array(),
...
'aliases' => array(
'Zend' => 'application.vendors.Zend',
'Maxmind' => 'application.vendors.Maxmind',
),
...
'params' => array()
);
Apparently, index.php is not the right place to declare this. It may be because of the autoloader, I am not 100% sure, but since Zend has an autoloader and MaxMind doesn't, that's why it may work for Zend and not for MaxMind. Doing this made the things work. As you may notice, I also moved the Zend alias path to the same place, for consistency reasons :)

git ignore Yii database details

Some of the details in the main.php needed by all application instances (URL details) and some details will be specific to each application instance (database details).
Is there any idea to separate the database details from protected/config/main.php?
Just include the shared configuration from another PHP file:
main.php:
return array
(
....
'components' => array
(
'db' => include('sharedDatabaseConfiguration.php');
)
);
sharedDatabaseConfiguration.php:
return array('host' => ...);
You might have to add a path or something, depending where the file is stored.
Edit: Btw, Yii also has a fancy CMap::mergeArray() function that can do something similar (in case you want to "augment" the contents of a single config file with that from another one. Look at the default generated console.php for an example of that.
You can find an idea here: Manage application configuration in different modes .
Basically it works by importing a different PHP file (your db configuration) and merging the includedarrays:
<?php
return CMap::mergeArray(
require(dirname(__FILE__).'/db-config.php'),
array(
'basePath' => dirname(__FILE__).DIRECTORY_SEPARATOR.'..',
'name' => 'Page Title',
...
)
);
?>
You can use separate configuration file (e.g. protected/config/production.php), that is based on your main configuration file and that overrides some settings using CMap::mergeArray as this answer suggests:
return CMap::mergeArray(
require(dirname(__FILE__) . '/main.php'),
array(
'components' => array(
'db' => array(
'connectionString' => '...',
'username' => '...',
'password' => '...',
),
),
)
);
Then you can add protected/config/production.php to .gitignore.

Blocking access via HTTP Authentication with Zend Framework 2

I'm trying to implement HTTP-based authentication through a Zend\Authentication\Adapter\Http as explained in the ZF2 documentation about the HTTP Authentication Adapter.
I want to block every incoming request until the user agent is authenticated, however I'm unsure about how to implement this in my module.
How would I setup my Zend\Mvc application to deny access to my controllers?
What you are looking for is probably a listener attached to the Zend\Mvc\MvcEvent::EVENT_DISPATCH event of your application.
In order, here's what you have to do to block access to any action through an authentication adapter. First of all, define a factory that is responsible for producing your authentication adapter:
namespace MyApp\ServiceFactory;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Authentication\Adapter\Http as HttpAdapter;
use Zend\Authentication\Adapter\Http\FileResolver;
class AuthenticationAdapterFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$config = $serviceLocator->get('Config');
$authConfig = $config['my_app']['auth_adapter'];
$authAdapter = new HttpAdapter($authConfig['config']);
$basicResolver = new FileResolver();
$digestResolver = new FileResolver();
$basicResolver->setFile($authConfig['basic_passwd_file']);
$digestResolver->setFile($authConfig['digest_passwd_file']);
$adapter->setBasicResolver($basicResolver);
$adapter->setDigestResolver($digestResolver);
return $adapter;
}
}
This factory will basically give you a configured auth adapter, and abstract its instantiation logic away.
Let's move on and attach a listener to our application's dispatch event so that we can block any request with invalid authentication headers:
namespace MyApp;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\ModuleManager\Feature\BootstrapListenerInterface;
use Zend\EventManager\EventInterface;
use Zend\Mvc\MvcEvent;
use Zend\Http\Request as HttpRequest;
use Zend\Http\Response as HttpResponse;
class MyModule implements ConfigProviderInterface, BootstrapListenerInterface
{
public function getConfig()
{
// moved out for readability on SO, since config is pretty short anyway
return require __DIR__ . '/config/module.config.php';
}
public function onBootstrap(EventInterface $event)
{
/* #var $application \Zend\Mvc\ApplicationInterface */
$application = $event->getTarget();
$serviceManager = $application->getServiceManager();
// delaying instantiation of everything to the latest possible moment
$application
->getEventManager()
->attach(function (MvcEvent $event) use ($serviceManager) {
$request = $event->getRequest();
$response = $event->getResponse();
if ( ! (
$request instanceof HttpRequest
&& $response instanceof HttpResponse
)) {
return; // we're not in HTTP context - CLI application?
}
/* #var $authAdapter \Zend\Authentication\Adapter\Http */
$authAdapter = $serviceManager->get('MyApp\AuthenticationAdapter');
$authAdapter->setRequest($request);
$authAdapter->setResponse($response);
$result = $adapter->authenticate();
if ($result->isValid()) {
return; // everything OK
}
$response->setBody('Access denied');
$response->setStatusCode(HttpResponse::STATUS_CODE_401);
$event->setResult($response); // short-circuit to application end
return false; // stop event propagation
}, MvcEvent::EVENT_DISPATCH);
}
}
And then the module default configuration, which in this case was moved to MyModule/config/module.config.php:
return array(
'my_app' => array(
'auth_adapter' => array(
'config' => array(
'accept_schemes' => 'basic digest',
'realm' => 'MyApp Site',
'digest_domains' => '/my_app /my_site',
'nonce_timeout' => 3600,
),
'basic_passwd_file' => __DIR__ . '/dummy/basic.txt',
'digest_passwd_file' => __DIR__ . '/dummy/digest.txt',
),
),
'service_manager' => array(
'factories' => array(
'MyApp\AuthenticationAdapter'
=> 'MyApp\ServiceFactory\AuthenticationAdapterFactory',
),
),
);
This is the essence of how you can get it done.
Obviously, you need to place something like an my_app.auth.local.php file in your config/autoload/ directory, with the settings specific to your current environment (please note that this file should NOT be committed to your SCM):
<?php
return array(
'my_app' => array(
'auth_adapter' => array(
'basic_passwd_file' => __DIR__ . '/real/basic_passwd.txt',
'digest_passwd_file' => __DIR__ . '/real/digest_passwd.txt',
),
),
);
Eventually, if you also want to have better testable code, you may want to move the listener defined as a closure to an own class implementing the Zend\EventManager\ListenerAggregateInterface.
You can achieve the same results by using ZfcUser backed by a Zend\Authentication\Adapter\Http, combined with BjyAuthorize, which handles the listener logic on unauthorized actions.
Answer of #ocramius is accept answer But you forget to describe How to write two files basic_password.txt and digest_passwd.txt
According to Zend 2 Official Doc about Basic Http Authentication:
basic_passwd.txt file contains username, realm(the same realm into your configuration) and plain password -> <username>:<realm>:<credentials>\n
digest_passwd.txt file contains username, realm(the same realm into your configuration) and password hashing Using MD5 hash -> <username>:<realm>:<credentials hashed>\n
Example:
if basic_passwd.txt file:
user:MyApp Site:password\n
Then digest_passwd.txt file:
user:MyApp Site:5f4dcc3b5aa765d61d8327deb882cf99\n
Alternatively you can use Apache Resolver for HTTP Adapter
use Zend\Authentication\Adapter\Http\ApacheResolver;
$path = 'data/htpasswd';
// Inject at instantiation:
$resolver = new ApacheResolver($path);
// Or afterwards:
$resolver = new ApacheResolver();
$resolver->setFile($path);
According to https://zendframework.github.io/zend-authentication/adapter/http/#resolvers