Load composer scripts inside class or function - php

Im trying to load a composer script into my class or function. But keeps getting the error:
Parse error: syntax error, unexpected 'use' (T_USE) in
I have searched on Stack Overflow and Google and read something about namespaces? But how can I implement a composer script into a class or function?
function.php, loads the autoload.php script file:
require(TEMPLATEPATH.'/vendor/autoload.php');
Custom function script:
function addToMailchimp($email) {
use \DrewM\MailChimp\MailChimp;
$MailChimp_api_key = get_field('mailchimp_api_key', 'option');
$MailChimp_landings_page = get_field('mailchimp_landings_page', 'option');
$MailChimp_landings_page_failed = get_field('mailchimp_landings_page_failed', 'option');
$MailChimp = new MailChimp($MailChimp_api_key);
if ($email != '') {
$list_id = '06b233d443';
$result = $MailChimp->post("lists/$list_id/members", [
'email_address' => $email,
'status' => 'subscribed',
]);
if ($result['detail'] == '') {
header( 'Location: ' . $MailChimp_landings_page['url']);
exit;
} else {
header( 'Location: ' . $MailChimp_landings_page_failed['url']);
exit;
}
}
}
composer.json file:
{
"require": {
"drewm/mailchimp-api": "^2.5",
"mpdf/mpdf": "^8.0"
},
"autoload": {
"psr-4": {
"DrewM\\MailChimp\\":"src/"
}
}
}

Autoloading would normally be setup on the initial page, most frequently in a front-controller or other .php file that is called first, and then organises what else happens. The 'use' statement also goes outside of the function, or class, and then the aliased class (here, MailChimp, is available within the whole file).
This code appears to be in a wordpress or older-style CMS system - it is possible to use composer within a plugin, or similar. There are examples of that around.

Related

PSR-4 autoloading issue

Problem:
I have the following file structure
-api (contains index.php)
--src
---vendor
----auth (contains auth.php)
----bin
----composer
----nesbot
----rbdwllr
----sympfony
here is my composer.json
{
"autoload": {
"psr-4": {
"AuthSpace\\": "/auth",
"Tests\\": "/rbdwllr/reallysimplejwt/tests",
"Symfony\\Polyfill\\Mbstring\\": "/symfony/polyfill-mbstring",
"Symfony\\Component\\Translation\\": "/symfony/translation",
"ReallySimpleJWT\\Helper\\": "/rbdwllr/reallysimplejwt/src/Helper",
"ReallySimpleJWT\\Exception\\": "/rbdwllr/reallysimplejwt/src/Exception",
"ReallySimpleJWT\\": "/rbdwllr/reallysimplejwt/src",
"": "/nesbot/carbon/src"
}
}
}
index.php
require __DIR__ . '/src/vendor/autoload.php';
$argument1 = $_GET['argument1'];
$tokenCode = $_GET['tokenCode'];
include 'config/database.php';
include 'objects/program1.php';
include 'auth.php';
use ReallySimpleJWT\Token;
use Carbon\Carbon;
$secret = "somesecret";
if (($_SERVER['REQUEST_METHOD']) == "GET") {
if ($_GET['url'] == "bankquery") {
if($tokenCode===NULL){
echo "no correct token provided";
print($results);
} else {
$results = Token::validate($tokenCode, $secret);
if ($results = 1){
$var = new AuthClass();
$var = AuthClass::checkTime($tokenCode);
} else {
echo "no correct token provided";
}
}
} else {
echo "some GET other query";
}
?>
auth.php
<?php namespace AuthSpace;
use ReallySimpleJWT\Token;
use Carbon\Carbon;
class AuthClass{
public static function checkTime($tokenCode){
// getting payload from token code by accessing the composer dependency method in a class Token
$received = Token::getPayload($tokenCode);
return $received;
}}
?>
I've generated the autoload using composer dump-autoload, checked the prs4 links - they all seem to show correct directory and namespace linking.
But nontheless, after running index.php file i keep getting the following error, but don't know why.
PHP Fatal error: Uncaught Error: Class 'AuthSpace\AuthClass' not
found

PSR4 not working?

Class not found, apparently. I've tried various things but nothing works.
Composer:
"autoload": {
"psr-4": {
"App\\": "application/"
}
}
File structure:
https://i.imgur.com/h9wOEqI.png
<?php
namespace App\Library\Classes;
defined('START') or exit('We couldn\'t process your request right now.');
class Application
{
private static $libraries = array();
public static function get($library) {
if (isset(self::$libraries[$library]) && isset(self::$classes[$library])) {
return self::$libraries[$library];
}
$fixedLibrary = str_replace('.', '/', $library);
$file = ROOT . '/application/library/classes/' . strtolower($fixedLibrary) . '.php';
self::$libraries[$library] = $library;
$declared = get_declared_classes();
$workingClass = end($declared);
self::$libraries[$library] = new $workingClass();
return self::$libraries[$library];
}
}
?>
Error is on this line:
Application::get('test')->test();
Yet, if I change it to this, it works:
include ROOT . '/application/Library/Application.php';
App\Library\Classes\Application::get('test')->test();
The PSR4 is not built-in part or PHP, you need an implementation of autoloader to use this standard such as provided by the Composer.
When you install or update depedencies, composer generates the relevant code of autoloading, but you can directly update it by the command dump-autoload, as #jibsteroos said. Next you should explicitly include the file vendor/autoload.php in the entry point of your application.
Also, error message says about class Application, but you should add the use statement at first:
use App\Library\Classes\Application;
Application::get('test')->test();
Or use the fully qualified class name (class name with namespace prefix):
\App\Library\Classes\Application::get('test')->test();

how to use an autoloader in php

I'm new to PHP and not really familiar with using git.
I got this library:
https://github.com/CKOTech/checkout-php-library
and I wanna run the sample code here:
https://github.com/CKOTech/checkout-php-library/wiki/Tokens
I know the code may not work perfectly for you cuz you would need a secret key from the provider, however, I don't need general errors like " cannot find class ApiClient"
what I did is simply including the autoloader in my index.php file, is that all what I have to do to use an Autoloader? does it have to do anything with composer.json?
Thanks a ton for the help in advance.
Autoloader.php:
<?php
function autoload($className)
{
$baseDir = __DIR__;
$realClassName = ltrim($className, '\\');
$realClassName = str_replace('\\',DIRECTORY_SEPARATOR,$realClassName );
$fileName = '';
$includePaths = $baseDir.DIRECTORY_SEPARATOR.$realClassName. '.php';
if ( $file = stream_resolve_include_path($includePaths) ) {
if (file_exists($file)) {
require $file;
}
}elseif(preg_match('/^\\\?test/', $className)) {
$fileName = preg_replace('/^\\\?test\\\/', '', $fileName);
$fileName = 'test' . DIRECTORY_SEPARATOR . $fileName;
include $fileName;
} else {
$classNameArray = explode('_', $className);
$includePath = get_include_path();
set_include_path($includePath);
if (!empty($classNameArray) && sizeof($classNameArray) > 1) {
if (!class_exists('com\checkout\packages\Autoloader')) {
include 'com'.DIRECTORY_SEPARATOR.'checkout'.DIRECTORY_SEPARATOR.'packages'.DIRECTORY_SEPARATOR.'Autoloader.php';
}
}
}
}
spl_autoload_register('autoload');
If you want to use an autoloader to make your life measurably better:
Use namespaces/PSR4.
Use Composer.
So let's say I'm working on project foo, within my working directory [let's just say it's /] I make a folder named /src/ and inside is /src/FooClient.php. It contains:
<?php
namespace sammitch\foo;
class FooClient {}
While in / I run composer init and accept all of the defaults, because typing out the simple JSON config file that that generates is tedious. Now I have a composer.json that looks like:
{
"name": "Sammitch/foo",
"authors": [
{
"name": "Sammitch",
"email": "sammitch#sam.mitch"
}
],
"require": {}
}
All we need to do now is add a section to the end:
"autoload": {
"psr-4": {
"sammitch\\foo\\": "src/"
}
}
Now to make Composer do it's magic and make the autoloader just run composer dumpautoload. When this runs Composer will create the /vendor/ folder and the autoloader.
Now all we need to do is:
<?php
require('vendor/autoload.php');
use \sammitch\foo\Client as FooClient()
$c = new FooClient();
Now not only do you have a top-tier autoloader, but you're also set up to start using Composer packages and leveraging all that good stuff from Packagist.

Composer Autoload Multiple Files in Folder

I'm using composer in my latest project and mapping my function like this
"require": {
...
},
"require-dev": {
...
},
"autoload": {
"psr-4": {
...
},
"files": [
"src/function/test-function.php"
]
}
I imagine there will be a lot of files in a folder function, ex : real-function-1.php, real-function-2.php, etc. So, can composer call all the files in the folder function ? i lazy to use
"files": [
"src/function/real-function-1.php",
"src/function/real-function-2.php",
..,
"src/function/real-function-100.php",
]
Is there any lazy like me...
If you can't namespace your functions (because it will break a bunch of code, or because you can't use PSR-4), and you don't want to make static classes that hold your functions (which could then be autoloaded), you could make your own global include file and then tell composer to include it.
composer.json
{
"autoload": {
"files": [
"src/function/include.php"
]
}
}
include.php
$files = glob(__DIR__ . '/real-function-*.php');
if ($files === false) {
throw new RuntimeException("Failed to glob for function files");
}
foreach ($files as $file) {
require_once $file;
}
unset($file);
unset($files);
This is non-ideal since it will load every file for each request, regardless of whether or not the functions in it get used, but it will work.
Note: Make sure to keep the include file outside of your /real-function or similar directory. Or it will also include itself and turn out to be recursive function and eventually throw a memory exception.
There's actually a better way to do this now without any custom code. You can use Composer's classmap feature if you're working with classes. If you're working with individual files that contain functions then you will have to use the files[] array.
{
"autoload": {
"classmap": ["src/", "lib/", "Something.php"]
}
}
This whole process can be completely automated while still performing relatively well.
With the following package.json (note the absence of an autoload entry, you could however add others)
{
"scripts": {
"pre-autoload-dump": "\\MyComponentAutoloader::preAutoloadDump"
}
}
And then...
<?php
class MyComponentAutoloader
{
public static function preAutoloadDump($event): void
{
$optimize = $event->getFlags()['optimize'] ?? false;
$rootPackage = $event->getComposer()->getPackage();
$dir = __DIR__ . '/../lib'; // for example
$autoloadDefinition = $rootPackage->getAutoload();
$optimize
? self::writeStaticAutoloader($dir)
: self::writeDynamicAutoloader($dir);
$autoloadDefinition['files'][] = "$dir/autoload.php";
$rootPackage->setAutoload($autoloadDefinition);
}
/**
* Here we generate a relatively efficient file directly loading all
* the php files we want/found. glob() could be replaced with a better
* performing alternative or a recursive one.
*/
private static function writeStaticAutoloader($dir): void
{
file_put_content(
"$dir/autoload.php",
"<?php\n" .
implode("\n", array_map(static function ($file) {
return 'include_once(' . var_export($file, true) . ');';
}, glob("$dir/*.php"))
);
}
/**
* Here we generate an always-up-to-date, but slightly slower version.
*/
private static function writeDynamicAutoloader($dir): void
{
file_put_content(
"$dir/autoload.php",
"<?php\n\nforeach (glob(__DIR__ . '/*.php') as \$file)\n
include_once(\$file);"
);
}
}
Things to note:
preAutoloadDump takes care of adding the autoload.php entrypoint to composer.
autoload.php is generated every time the autoloader is dumped (e.g. composer install / composer update / composer dump-autoload)
when dumping an optimised autoloader (composer dump-autoload --optimize), only the files found at that point will be loaded.
you should also add autoload.php to .gitignore

using Zend_Db zf2 module outside of zf2 mvc

I'm writing a PHP application that is not based on zf2 mvc.
I do want to use only the Zend_Db zf2 module. how can I configure my application to know
how to find the Zend_Db releveant PHP file where required ?
I have zf2 Zend_db module download with phyrus and installed at the location vendor/zf2/php.
I tried adding the module to the include path with the following command:
set_include_path("../vendor/zf2/php".PATH_SEPARATOR.get_include_path());
I created Model class files relevant to each table (using zend-db-model-generator) inside directory Model/.
my main app contains the following:
use DrinkManagement\Model\DrinkTable;
use Zend\Db\Adapter\Adapter;
set_include_path("../vendor/zf2/php".PATH_SEPARATOR.get_include_path());
require_once('Model/DrinkTable.php');
/**
#var DrinkManagement\Model\Drink
*/
$drinkTable=null;
$drinkTable = new DrinkTable();
$res=$drinkTable->getDrink(1);
echo var_export($res,1);
my DrinkTable class:
namespace DrinkManagement\Model;
use Zend\Db\TableGateway\AbstractTableGateway,
class DrinkTable extends AbstractTableGateway
{
protected $table ='drink';
protected $tableName ='drink';
public function __construct(Adapter $adapter)
{
$this->adapter = $adapter;
$this->resultSetPrototype = new ResultSet(new Drink);
$this->initialize();
}
public function fetchAll()
{
$resultSet = $this->select();
return $resultSet;
}
public function newSelect() {
return new Select;
}
public function getSelect(&$select,$columnsArray=array())
{
$select = new Select;
return $select->from('drink')->columns($columnsArray);
}
public function createIfNotExist($checkColumnsArray,$optionalColumns=array(),&$isRowCreated=null) {
$rowset=$this->select($checkColumnsArray);
$row = $rowset->current();
$id=null;
if ($row == null) {
$allColumns=array_merge($checkColumnsArray,$optionalColumns);
$affectedRows = $this->insert($allColumns);
if ($affectedRows != 1) {
throw new \Exception("error: could not add line to db");
}
$id=$this->lastInsertValue;
$isRowCreated=true;
} else {
$id=$row->drink_id;
$isRowCreated=false;
}
return $id;
}
//http://stackoverflow.com/questions/6156942/how-do-i-insert-an-empty-row-but-have-the-autonumber-update-correctly
public function createEmptyRow() {
$row=array(
'drink_id' => null
);
$affectedRows=$this->insert($row);
if ($affectedRows != 1) {
throw new \Exception("error: could not add empty row to db");
}
$id=$this->lastInsertValue;
return $id;
}
public function getDrink($id)
{
$id = (int) $id;
$rowset = $this->select(array('drink_id' => $id));
$row = $rowset->current();
if (!$row) {
throw new \Exception("Could not find row $id");
}
return $row;
}
public function saveDrink(Drink $drink)
{
$data = array(
'drink_type_id' => $drink->drink_type_id,
'drink_brand_id' => $drink->drink_brand_id,
'creation_timestamp' => $drink->creation_timestamp,
);
$id = (int)$drink->id;
if ($id == 0) {
$this->insert($data);
} else {
if ($this->getDrink($id)) {
$this->update($data, array('drink_id' => $id));
} else {
throw new \Exception('Form id does not exit');
}
}
}
public function addDrink($drink_type_id, $drink_brand_id = null, $creation_timestamp = null)
{
$data = array( 'drink_type_id' => $drink_type_id,
'drink_brand_id' => $drink_brand_id,
'creation_timestamp' => $creation_timestamp,
);
$affectedRows=$this->insert($data);
if ($affectedRows != 1) {
return null;
}
return $this->lastInsertValue;
}
public function updateDrink($drink_id, $drink_type_id, $drink_brand_id, $creation_timestamp)
{
$data = array(
'drink_type_id' => $drink->drink_type_id,
'drink_brand_id' => $drink->drink_brand_id,
'creation_timestamp' => $drink->creation_timestamp,
);
$this->update($data, array(drink_id => $id));
}
public function deleteDrink($id)
{
$this->delete(array('drink_id' => $id));
}
}
when I try to execute my main php application i get the following error message:
PHP Fatal error: Class 'Zend\Db\TableGateway\AbstractTableGateway' not found in /Users/ufk/Documents/workspace/tux-drink/TuxDb/mysql/Model/DrinkTable.php on line 10
any ideas how to resolve the issue without adding require_once everywhere ?
maybe is there another zf2 component I can use that will autoload the relevant classes?
From what I see from your code, you don't include anywhere the files corresponding to the necessary classes (eg. AbstractTableGateway). Setting the vendor path as an include path won't solve your problem.
Trying to add manually your dependencies will cause you many troubles as you'll have not only to add manually your dependecies for the classes you are using but also for the their dependencies (Adapters, Drivers etc.)
In my opinion, It would be better for you to use a dependency manager such as Composer for managing your dependencies & their auto-loading. You can actually define a dependency for the zendframework\zend-db package within the composer.json (which you have to create at the root project directory) as follows :
{
"name": "Your project name",
"description": "Your project description",
"autoload": {
"psr-0": {
"Zend\\Db\\": ""
}
},
"target-dir": "Zend/Db",
"repositories": [
{
"type": "composer",
"url": "https://packages.zendframework.com/"
}
],
"require": {
"php": ">=5.3.3",
"zendframework/zend-db":"2.0.*"
}
}
After installing composer to your project folder, run php composer.phar install from your command line. Composer will generate you the auto-loading file vendor/autoload.php that you can include for automatically loading your dependencies classes.
Example:
<?php
// Always include autoload files when using vendor classes
include 'vendor/autoload.php';
require_once('Model/DrinkTable.php');
use DrinkManagement\Model\DrinkTable;
use Zend\Db\Adapter\Adapter;
//Don't forget declaring an adapter
$adapter = new Adapter(array(
'driver' => 'Mysqli',
'database' => 'test',
'username' => 'dev',
'password' => 'dev'
));
//Your constructor should include the adapter
$drinkTable = new DrinkTable('drinktable', $adapter);
//Do necessary stuff with the table
//....
echo var_export($res,1);
?>
Note: You can declare a dependency for zend-loader, so that you can use Zend\Loader\StandardAutoloader for auto-loading your own classes (assuming you're using PSR-0)
This is not my work, but Abdul Malik Ikhsan (ZF2 contributor) has a great blog post about using Zend/DB as a standalone component.
Like #yechabbi mentioned, you'll probably do yourself a lot of good to use Composer as your dependency manager.
It looks like you might be stumbling with where you're placing Zend-Db and what you're naming it. For example, in my working ZF2 installation, the Zend_Db component is located in vendor/zendframework/zendframework/library/Zend/Db. Using Composer with the correct require statements as Abdul quotes in his blog post should take care of all that for you:
"require": {
"php": ">=5.3.3",
"zendframework/zend-db": "2.*",
"zendframework/zend-stdlib": "2.*"
}
Abdul then uses the following namespaces in his Table class
use Zend\Db\TableGateway\TableGateway;
use Zend\Db\Sql\Select;
use Zend\Db\ResultSet\HydratingResultSet;
I don't know that this will fix all of your issues but it will get you on the right track I hope.

Categories