I want to create a thumb but am getting this error:
PHP Fatal Error – yii\base\ErrorException
Class 'Imagine\Image\ManipulatorInterface' not found
I don't know from where i can get this? I used yii2-imagine but didn't find any ManipulatorInterface class.
controller file:
<?php
namespace backend\controllers;
use Yii;
use app\models\Employee;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\web\UploadedFile;
use yii\imagine\Image; // this is where i used Image class
public function actionCreate()
{
$model = new Employee();
$model->added_date_time = date('Y-m-d H:i:s');
if($model->load(Yii::$app->request->post())) {
$model->file = UploadedFile::getInstance($model,'avatar');
if(!empty($model->file)) {
$imageName = Yii::$app->security->generateRandomString();
$model->file->saveAs('uploads/'.$imageName.'.'.$model->file->extension);
$model->avatar = $imageName.'.'.$model->file->extension;
$file = 'uploads/'.$imageName.'.'.$model->file->extension;
Image::thumbnail($file, 200, 200)->save('uploads/thumb/', ['quality' => 80]);
}
if($model->save()){
$this->redirect(\Yii::$app->urlManager->createUrl('employee'));
}
}
else {
return $this->render('create', [
'model' => $model
]);
}
}
?>
Image class file is in \vendor\yiisoft\yii2\imagine folder and ManipulatorInterface is in \vendor\yiisoft\yii2\imagine\Imagefolder
Image.php
<?php
namespace yii\Imagine;
class Image extends BaseImage
{
}
?>
BaseImage.php
<?php
namespace yii\imagine;
use Yii;
use imagine\Image\Box;
use imagine\Image\Color;
use imagine\Image\ImageInterface;
use imagine\Image\ImagineInterface;
use imagine\Image\ManipulatorInterface;
use imagine\Image\Point;
use yii\base\InvalidConfigException;
use yii\base\InvalidParamException;
use yii\helpers\ArrayHelper;
class BaseImage
{
public static function thumbnail($filename, $width, $height, $mode = 'outbound')
{
$box = new Box($width, $height);
$img = static::getImagine()->open(Yii::getAlias($filename));
if (($img->getSize()->getWidth() <= $box->getWidth() && $img->getSize()->getHeight() <= $box->getHeight()) || (!$box->getWidth() && !$box->getHeight())) {
return $img->copy();
}
$img = $img->thumbnail($box, $mode);
// create empty image to preserve aspect ratio of thumbnail
$thumb = static::getImagine()->create($box, new Color('FFF', 100));
// calculate points
$size = $img->getSize();
$startX = 0;
$startY = 0;
if ($size->getWidth() < $width) {
$startX = ceil($width - $size->getWidth()) / 2;
}
if ($size->getHeight() < $height) {
$startY = ceil($height - $size->getHeight()) / 2;
}
$thumb->paste($img, new Point($startX, $startY));
return $thumb;
}
?>
I have the same problem. I try 'composer global require "fxp/composer-asset-plugin:~1.0.0"' after that I try 'composer.phar require --prefer-dist yiisoft/yii2-imagine' again and it's work for me. Hope it helps you too
you can try this:
1) copy imagine to your vendor
`pathA: "vendor/Imagine/Draw...."`
2) add a alias into config.php
'components' => [
],
....
'aliases'=>[
'#Imagine'=>'#vendor/Imagine', //this should correspond to pathA above
],
....
'params' => [
],
3) check vendor/composer/autoload_psr4.php
config it like this
return array(
...
'yii\\imagine\\' => array($vendorDir . '/yiisoft/yii2-imagine'),
...
);
4) copy yii-imagine into yiisoft
pathB:"vendor/yiisoft/yii-imagine"
then you can use it .
I have resolved to set path in extensions.php under the yiisoft folder.
Just follow 2 steps:
Open extensions.php
On the bottom of the file add
'yiisoft/yii2-imagine' =>
array (
'name' => 'yiisoft/yii2-imagine',
'version' => '~2.0.0',
'alias' =>
array (
'#yii/imagine' => $vendorDir . '/yiisoft/yii2-imagine',
'#Imagine/Image' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Image',
'#Imagine/Gd' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Gd',
'#Imagine/Draw' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Draw',
'#Imagine/Effects' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Effects',
'#Imagine/Exception' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Exception',
'#Imagine/Filter' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Filter',
'#Imagine/Gmagick' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Gmagick',
'#Imagine/Imagick' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Imagick',
'#Imagine/resources' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/resources',
),
),
So my extensions.php looks like
<?php
$vendorDir = dirname(__DIR__);
return array (
'yiisoft/yii2-swiftmailer' =>
array (
'name' => 'yiisoft/yii2-swiftmailer',
'version' => '2.0.6.0',
'alias' =>
array (
'#yii/swiftmailer' => $vendorDir . '/yiisoft/yii2-swiftmailer',
),
),
'yiisoft/yii2-bootstrap' =>
array (
'name' => 'yiisoft/yii2-bootstrap',
'version' => '2.0.6.0',
'alias' =>
array (
'#yii/bootstrap' => $vendorDir . '/yiisoft/yii2-bootstrap',
),
),
'yiisoft/yii2-debug' =>
array (
'name' => 'yiisoft/yii2-debug',
'version' => '2.0.6.0',
'alias' =>
array (
'#yii/debug' => $vendorDir . '/yiisoft/yii2-debug',
),
),
'yiisoft/yii2-gii' =>
array (
'name' => 'yiisoft/yii2-gii',
'version' => '2.0.5.0',
'alias' =>
array (
'#yii/gii' => $vendorDir . '/yiisoft/yii2-gii',
),
),
'yiisoft/yii2-faker' =>
array (
'name' => 'yiisoft/yii2-faker',
'version' => '2.0.3.0',
'alias' =>
array (
'#yii/faker' => $vendorDir . '/yiisoft/yii2-faker',
),
),
'yiisoft/yii2-imagine' =>
array (
'name' => 'yiisoft/yii2-imagine',
'version' => '~2.0.0',
'alias' =>
array (
'#yii/imagine' => $vendorDir . '/yiisoft/yii2-imagine',
'#Imagine/Image' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Image',
'#Imagine/Gd' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Gd',
'#Imagine/Draw' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Draw',
'#Imagine/Effects' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Effects',
'#Imagine/Exception' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Exception',
'#Imagine/Filter' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Filter',
'#Imagine/Gmagick' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Gmagick',
'#Imagine/Imagick' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/Imagick',
'#Imagine/resources' => $vendorDir . '/yiisoft/yii2-imagine/Imagine/resources',
),
),
);
Related
I added 5 folders to the vendor folder:
paragonie
setasign
psr/log
mpdf
kartik-v/yii2-mpdf
Then I wrote in the vendor/composer/autoload_psr4.php:
'Mpdf\\' => array($vendorDir . '/mpdf/mpdf/src'),
'kartik\\mpdf\\' => array($vendorDir . '/kartik-v/yii2-mpdf/src'),
And wrote in the vendor/yiisoft/extensions.php:
'kartik-v/yii2-mpdf' =>
array (
'name' => 'kartik-v/yii2-mpdf',
'version' => '9999999-dev',
'alias' =>
array (
'#kartik/mpdf' => $vendorDir . '/kartik-v/yii2-mpdf/src',
),
),
When I call in the controller:
$pdf = new Pdf();
I get an error:
Previously, when I manually added an extension, there were no problems.
I have a problem. I want to add my custom library when the webapplication starts and i want use it in application layout. I want to create a form (composed by 2 concatenated select with ajax functions) and it must be visible in all parts of the application. when i tried to use my helper custom library, this is the error message:
Fatal error: Class 'SelectSearchList' not found in C:\Program Files (x86)\xampp\htdocs\Easyanimal\module\Application\view\layout\layout.phtml on line 118
this is the code of vendor/composer/autoload_namespaces.php:
<?php
// autoload_namespaces.php generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Zend\\' => $vendorDir . '/zendframework/zendframework/library/',
'ZendTest\\' => $vendorDir . '/zendframework/zendframework/tests/',
'MyHelpLib\\' => $vendorDir . '/MyHelpLib/',
);
this is my help library in vendor/MyHelpLib/LoaderSelect.php:
namespace MyHelpLib
class SelectSearchList {
public $select;
public function showOpt (){
return $select = '<option value="">Select...</option>';
}
}
and this my layout in application/view/layout
<?php
use MyHelpLib\LoaderSelect;
$Opt = new SelectSearchList();
echo $Opt->showOpt();
?>
i tried to add this in Application/module.php but it isn't work again!
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
'MyHelpLib' => __DIR__ . '/../../vendor/MyHelpLib',
),
),
);
}
thanks so much for the help
Create view helper. http://framework.zend.com/manual/2.3/en/modules/zend.view.helpers.advanced-usage.html#writing-custom-helpers
Index\src\View\Helper\MyHelpLib
namespace Index\View\Helper;
use Zend\View\Helper\AbstractHelper;
class MyHelpLib extends AbstractHelper
{
public function __invoke()
{
return 'MyHelper'
}
}
Index\config\module.config.php
return array(
...
'view_helpers' => array(
'invokables' => array(
'MyHelpLib' => '\Index\View\Helper\MyHelpLib'
)
)
);
layout.phtml
echo $this->MyHelpLib();
I have a json file of about 50M in size, about 10k records. I am using following code to insert into Joomla programmatically, it works pretty well as all relevant tables get updated simultaneously, e.g., #_assets, however the code runs really slow: about 40 hours passed now but only about 4k articles are processed. Can I speed up the process somehow?
I do know that if I do insert into #_content, #_tags, etc, it'll be much quicker, but that approach has some trivia complications that I try to avoid.
<?php
define( '_JEXEC', 1 );
define('JPATH_BASE', dirname(dirname(__FILE__)));
define( 'DS', DIRECTORY_SEPARATOR );
require_once (JPATH_BASE . DS . 'includes' . DS . 'defines.php');
require_once (JPATH_BASE . DS . 'includes' . DS . 'framework.php');
require_once (JPATH_BASE . DS . 'libraries' . DS . 'joomla' . DS . 'factory.php' );
define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_BASE . DS . 'administrator' . DS . 'components' . DS . 'com_content');
$mainframe = JFactory::getApplication('site');
require_once (JPATH_ADMINISTRATOR.'/components/com_content/models/article.php');
$string = file_get_contents("items.json");
$json_str = json_decode($string, true);
foreach($json_str as $row){
$new_article = new ContentModelArticle();
$data = array(
'title' => $row['title'][0],
'alias' => $row['alias'],
'introtext' => $row['content'],
'state' => 1,
'catid' => 8, /* don't hard code here! */
'created' => $row['pdate'][0],
'created_by' => 798,
'created_by_alias' => $row['poster'][0],
'publish_up' => $row['pdate'][0],
'urls' => $row['urls'],
'access' => 1,
'metadata' => array(
'tags' => $row['tags'],
'robots' => "",
'author' => implode(" ", $row['poster']),
'rights' => "",
'xreference' => "",
),
);
$new_article->save($data);
}
If you were running this in Joomla as an extension I would suggest turning on debugging and having a look at the Profile Information in the Joomla! Debug Console to see where allthe time is being spent.
You're not, so the rest is deduction (therefore possibly faulty).
You're loading the ContentModelArticle for each insert this means that it creates and destroys not only the model class for each row but also the table class for each row.
If these are all inserts, then you don't need all the overhead of the model (e.g. checking if the article exists first).
If the data is all valid you also don't need the data preparation (prepareTable()) in the content model nor the check() in the content table.
If you don't need that you could load the JTable once, then call the table objects save() passing in your array for each article. That will run the bind(), check(), store() — where asset tracking is updated, and complete the insert.
So, you could try something like this, I think it will be faster, not sure by how much.
$contentTable = JTable::getInstance('Content', 'JTable', array());
foreach($json_str as $row){
$data = array(
'title' => $row['title'][0],
'alias' => $row['alias'],
'introtext' => $row['content'],
'state' => 1,
'catid' => 8, /* don't hard code here! */
'created' => $row['pdate'][0],
'created_by' => 798,
'created_by_alias' => $row['poster'][0],
'publish_up' => $row['pdate'][0],
'urls' => $row['urls'],
'access' => 1,
'metadata' => array(
'tags' => $row['tags'],
'robots' => "",
'author' => implode(" ", $row['poster']),
'rights' => "",
'xreference' => "",
),
$contentTable->save($data);
}
*Disclaimer: this isn't tested code it's just out of my head and into the browser.
I refer to http://samsonasik.wordpress.com/2012/08/31/zend-framework-2-creating-upload-form-file-validation/ and follow this, I can upload 1 file successfully by using rename filter in ZF2.
However when I use this way to upload 2 files, it goes wrong. I paste my code as following:
$this->add(array(
'name' => 'bigpicture',
'attributes' => array(
'type' => 'file'
),
'options' => array(
'label' => 'Big Pic'
)
));
$this->add(array(
'name' => 'smallpicture',
'attributes' => array(
'type' => 'file'
),
'options' => array(
'label' => 'Small Pic'
)
));
<div class="row"><?php echo $this->formRow($form->get('smallpicture')) ?></div>
<div class="row"><?php echo $this->formRow($form->get('bigpicture')) ?></div>
$data = array_merge(
$request->getPost()->toArray(),
$request->getFiles()->toArray()
);
$form->setData($data);
if ($form->isValid()) {
$product->exchangeArray($form->getData());
$picid = $this->getProductTable()->saveProduct($product);
$pathstr = $this->md5path($picid);
$this->folder('public/images/product/'.$pathstr);
//move_uploaded_file($data['smallpicture']['tmp_name'], 'public/images/product/'.$pathstr.'/'.$picid.'_small.jpg');
//move_uploaded_file($data['bigpicture']['tmp_name'], 'public/images/product/'.$pathstr.'/'.$picid.'_big.jpg');
$fileadaptersmall = new \Zend\File\Transfer\Adapter\Http();
$fileadaptersmall->addFilter('File\Rename',array(
'source' => $data['smallpicture']['tmp_name'],
'target' => 'public/images/product/'.$pathstr.'/'.$picid.'_small.jpg',
'overwrite' => true
));
$fileadaptersmall->receive();
$fileadapterbig = new \Zend\File\Transfer\Adapter\Http();
$fileadapterbig->addFilter('File\Rename',array(
'source' => $data['bigpicture']['tmp_name'],
'target' => 'public/images/product/'.$pathstr.'/'.$picid.'_big.jpg',
'overwrite' => true
));
$fileadapterbig->receive();
}
the above are form,view,action.
using this way, only the small picture uploaed successfully. the big picture goes wrong.
a warning flashed like the following:
Warning:move_uploaded_file(C:\WINDOWS\TMP\small.jpg):failed to open stream:Invalid argument in
E:\myproject\vendor\zendframework\zendframework\library\zend\file\transfer\adapter\http.php
on line 173
Warning:move_uploaded_file():Unable to move 'C:\WINDOWS\TMP\php76.tmp'
to 'C:\WINDOWS\TEMP\big.jpg' in
E:\myproject\vendor\zendframework\zendframework\library\zend\file\transfer\adapter\http.php
on line 173
Who can tell me how to upload more than 1 file in this way. you know, the rename filter way similar to above. thanks.
I ran into the same problem with a site i did. The solution was to do the renaming in the controller itself by getting all the images and then stepping through them.
if ($file->isUploaded()) {
$pInfo = pathinfo($file->getFileName());
$time = uniqid();
$newName = $pName . '-' . $type . '-' . $time . '.' . $pInfo['extension'];
$file->addFilter('Rename', array('target' => $newName));
$file->receive();
}
Hope this helps point you in the right direction.
I encountered the same problem and i managed to make it work using the below code;
$folder = 'YOUR DIR';
$adapter = new \Zend\File\Transfer\Adapter\Http();
$adapter->setDestination($folder);
foreach ($adapter->getFileInfo() as $info) {
$originalFileName = $info['name'];
if ($adapter->receive($originalFileName)) {
$newFilePath = $folder . '/' . $newFileName;
$adapter->addFilter('Rename', array('target' => $newFilePath,
'overwrite' => true));
}
}
I must hard code to add new layout. Then i want find some way to add template map dynamic in ZF2.
My module.config.php
'view_manager' => array (
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array (
'layout/layout' => __DIR__ . '/../../../template/layout/layout.phtml',
'layout/custom' => __DIR__ . '/../../../template/layout/custom.phtml',
'error/404' => __DIR__ . '/../../../template/error/404.phtml',
'error/index' => __DIR__ . '/../../../template/error/index.phtml'
),
'template_path_stack' => array (
__DIR__ . '/../view/'
)
)
And I set new layout by this way
$e->getApplication()->getEventManager()->getSharedManager()->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch', function($e) {
$controller = $e->getTarget();
$controller->layout('template_name');
}, 100);
Please lets me some advise/sample
Thanks !
==================
Update 12/08/2012:
I found the solution for this and apply to my "hierarchy template system"
Modify module.config.php
'template_path_stack' => array (
__DIR__ . '/../view/',
__DIR__ . '/../../../' //Parent folder of template path
)
In Module.php added :
$e->getApplication()->getEventManager()->getSharedManager()->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch', function($e) {
$controller = $e->getTarget();
$controllerClass = get_class($controller);
//Get routing info
$controllerArr = explode('\\', $controllerClass);
$currentRoute = array(
'module' => strtolower($controllerArr[0]),
'controller' => strtolower(str_replace("Controller", "", $controllerArr[2])),
'action' => strtolower($controller->getEvent()->getRouteMatch()->getParam('action'))
);
//Get curr route
$currAction = implode('/',$currentRoute);
$currController = $currentRoute['module'] . '/' . $currentRoute['controller'];
$currModule = $currentRoute['module'];
//Template file location
$templatePath = __DIR__ .'/../../template/';
//Set template
$template = 'layout/layout'; // Default template
if (file_exists($templatePath . $currAction.'.phtml')) {
$template = $currAction;
}else if(file_exists($templatePath . $currController.'.phtml')) {
$template = $currController;
}else if(file_exists($templatePath . $currModule.'.phtml')) {
$template = $currModule;
}else{
if($currentRoute['controller']=='admin'){
$template = 'admin/layout'; // Admin default template
}
}
$controller->layout('template/'.$template); //Pevert duplicate layout
}, 100);
Note: If you set the key same variable between your 'layout' and 'view'. It will render duplicate the 'layout' and don't understand your current view
In your controller when you create a new viewmodel you can set the template you've created there.
public function someAction() {
$viewModel = new ViewModel();
$viewModel->setTemplate('layout/custom');
return $viewModel;
}
Just make sure the layout.phtml file is in the path you set in your template_map