my Yii modules file structure looks like this
-yii
-protected
-modules
-admin
-controller
-model
-view
-layout
-main.php
-assets
-css
-style.css
-js
-images
-logo.jpg
what i'm trying to do is access the logo.jpg from my protected/views/site/index.php. How do i do that?
Your should publish your assets first, then use this url. Add this code in your module:
class YourModule extends CWebModule
{
private $_assetsUrl;
public function getAssetsUrl()
{
if ($this->_assetsUrl === null)
$this->_assetsUrl = Yii::app()->getAssetManager()->publish(__DIR__ . '/assets', false, -1, true);
return $this->_assetsUrl;
}
Then use this url:
$assets = $this->module->getAssetsUrl();
echo $assets . '/images/logo.jpg'
Related
I'm using silverstripe 4 with silverstripe-fluent module. I can't translate native SiteConfig (site name and tagline/slogan) How do that ?
Thank for your help!
Aurélien
I had the same problem. Translating only specific variables.
Solved it simular:
YML (config.yml)
SilverStripe\SiteConfig\SiteConfig:
extensions:
- Pixelparker\Extensions\SiteConfigExtension
- TractorCow\Fluent\Extension\FluentExtension
SiteConfigExtension.php
private static $translate = [
'CookieMessage'
];
thats it.
Solved !
Add TractorCow\Fluent\Extension\FluentExtension in Silverstripe\SiteConfig\SiteConfig :
---
Name: myproject
---
SilverStripe\Core\Manifest\ModuleManifest:
project: app
Silverstripe\SiteConfig\SiteConfig:
extensions:
- TractorCow\Fluent\Extension\FluentExtension
- CustomSiteConfig
and extends FluentExtension instead of DataExtension in your config extension class :
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
use TractorCow\Fluent\Extension\FluentExtension;
class CustomSiteConfig extends FluentExtension
{
private static $db = [
'FooterContent' => 'HTMLText'
];
public function updateCMSFields(FieldList $fields)
{
$fields->addFieldToTab("Root.Main",
new HTMLEditorField("FooterContent", "Footer Content")
);
parent::updateCMSFields($fields);
}
}
If you just want to translate SiteConfig's default Title and Tagline DB field, then you can apply both the Fluent extension and define the DB fields to be translated in a .yml configuration file, like this:
SilverStripe\SiteConfig\SiteConfig:
extensions:
- TractorCow\Fluent\Extension\FluentExtension
translate:
- Title
- Tagline
How to upload a file in symfony 4.I have done with the symfony document. I don't know where I have missed something. Its throws error while uploading file give me some clues
REFERED LINK:
https://symfony.com/doc/current/controller/upload_file.html
ERROR:
The file "" does not exist
Entity
public function getBrochure()
{
return $this->brochure;
}
public function setBrochure($brochure)
{
$this->brochure = $brochure;
return $this;
}
File upload Listener
class FileUploader
{
private $targetDirectory;
public function __construct($targetDirectory)
{
$this->targetDirectory = $targetDirectory;
}
public function upload(UploadedFile $file)
{
$fileName = md5(uniqid()).'.'.$file->guessExtension();
$file->move($this->getTargetDirectory(), $fileName);
return $fileName;
}
public function getTargetDirectory()
{
return $this->targetDirectory;
}
}
This Symfony tutorial works fine for me so I'll try to explain how and perhaps it will help you or people still looking for an answer, this post getting a bit old.
So first you have to create the FileUploader service in App\Service for better reusability (chapter: Creating an Uploader Service). You can basically copy/paste what they've done here, it works like a charm. Then you need to open your services.yaml in Config folder and explicit your brochure directory:
parameters:
brochures_directory: '%kernel.project_dir%/public/uploads/brochures'
# ...
services:
# ...
App\Service\FileUploader:
arguments:
$targetDirectory: '%brochures_directory%'
Now everything is normally ready to use your FileUploader service.
So if you're in your controller (for example), I guess you want to use it in a form. Thus, you just have to do this (don't forget to use your Service in your Controller):
public function myController(FileUploader $fileUploader)
{
// Create your form and handle it
if ($form isValid() && &form isSubmitted()) {
$file = $myEntity->getBrochure();
$fileName = $this->fileUploader->upload($file);
$myEntity->setBrochure($fileName);
// Form validation and redirection
}
// Render your template
}
One important point I forgot to say. In your FormType, you need to say that the Brochure will be a FileType:
$builder->add('brochure', FileType::class)
But in your entity you have to specify your brochure is stored as a "string":
/**
* #MongoDB\Field(type="string")
*/
protected $brochure;
The reason is your file is getting uploaded and saved in your public/uploads/brochure. But your database is only remembering a string path to reach it.
I hope this will help!
I am trying to build a module for Prestashop 1.6 that would redirect the user if the targeted URL is present in a database.
What I'm going to do is the following:
public function checkRedirection ($url) {
$line = Db::getInstance()->executeS('SELECT * FROM ps_custom_redirection WHERE url = ' . pSQL($url));
if (!sizeof($line)) {
return null;
}
header('Location: ' . $line[0]['destination']);
http_response_code($line[0]['http_code']);
exit();
}
Now, I could run this function when the displayTop hook is fired. But I would rather launch this function at the beginning of the request's process.
Does Prestashop provide such a hook? If not, can I create one? Where should I write the code to fire it?
The fist hook executed is actionDispatcher – you can use it if you want.
You'll find this hook executed in /classes/Dispatcher.php. Search for the code Hook::exec('actionDispatcher', $params_hook_action_dispatcher);.
If you want to add this hook to your module, you need to use its name in the main module file like this:
public function install() {
return parent::install()
&& $this->registerHook('actionDispatcher');
}
public function hookActionDispatcher($params) {
// your code
Tools::redirect($url);
}
In Prestashop Tools::redirect($url); is used if redirecting.
What I know to do:
1) Create a module controller that allows translation.
I can declare texts to translate either in the controller itself or in the template:
/modules/mymodule/controllers/front/list.php
class myModuleListModuleFrontController extends ModuleFrontController
{
public function initContent()
{
parent::initContent();
$this->l('Some text to translater');
$this->setTemplate('list.tpl');
}
}
/modules/mymodule/views/templates/front/list.tpl
{l s='Some other text' mod='mymodule'}
2) I know to create some output that is not embedded in html, like for instance some json object:
/modules/mymodule/json.php
include( '../../config/config.inc.php' );
echo json_encode(array('key' => 'Some text'));
What I need:
I need to be able to translate some text AND have the output sent to the browser without the surrounding html. I have to be able to do one of those:
use a standalone file and be able to declare text to translate, similar to this (does not work):
include( '../../config/config.inc.php' );
echo json_encode(array('key' => l('Some text')));
use a module controller and force raw output, similar to this (does not work either):
class myModuleListModuleFrontController extends ModuleFrontController
{
public function initContent()
{
parent::initContent();
$this->noHtml = true;
echo json_encode(array('key' => l('Some text')));
}
}
If you want to translate text in FrontController, you can only do it in two ways:
Translate the texts inside a template
// Inside module front controller
$template = '.../template.tpl'
$this->context->smarty->fetch($template)
// Inside template.tpl
{l s='Translateable text' mod='mymodule'}
Or use strings already translated inside main module file
// Inside module front controller
$this->module->l('My string');
// But it has to already exist inside mymodule.php
$this->l('My string'); // You don't have to use it, it just has to exist to get scanned by RegEx.
If you want to return something back to Ajax request in your module front controller
public function init() {
parent::init(); // If you need to
// Some code here
if (Tools::getValue('ajax'))
{
header('Content-Type: text/html');
die($this->context->smarty->fetch($template));
// Or
header('Content-Type: application/json');
die(Tools::jsonEncode($response_array));
}
There is also a function called
FrontControllerCore::getLayout # Line 1209
Which you can use to override the whole page template, however, it should be used to create unique display for products and other page (like full screen product presentation, etc.)
If you want to ouput a file yourself while not providing a full file path to the user:
public function init() {
parent::init(); // If you need to
if (ob_get_level() && ob_get_length() > 0)
ob_end_clean();
// Set download headers
header('Content-Transfer-Encoding: binary');
header('Content-Type: '.$mime_type);
header('Content-Length: '.filesize($file));
header('Content-Disposition: attachment; filename="'.$filename.'"');
// Prevents max execution timeout, when reading large files
set_time_limit(0);
$fp = fopen($file, 'rb');
while (!feof($fp))
echo fgets($fp, 16384);
exit;
Apart from that, I don't image what else would tou possibly need to build your app. Always send token to your controllers for security!
I have a console command to do a consumer time, AND I need to know how to call (execute) it in a web application action in YII.
class MyCommand extends CConsoleCommand{
public function actionIndex(){
$model = new Product();
$model->title = 'my product';
...
$model->save();
.
.
.
}
}
I want to execute this code.
try this:
Yii::import('application.commands.*');
$command = new MyCommand("test", "test");
$command->run(null);
The 2 parameters with value "test" must be set but do not have an impact, they are used for the --help option when using the console.
/**
* Constructor.
* #param string $name name of the command
* #param CConsoleCommandRunner $runner the command runner
*/
public function __construct($name,$runner)
{
$this->_name=$name;
$this->_runner=$runner;
$this->attachBehaviors($this->behaviors());
}
https://github.com/yiisoft/yii/blob/master/framework/console/CConsoleCommand.php#L65
Try this
Yii::import('application.commands.*');
$command = new GearmanCommand('start', Yii::app()->commandRunner);
$command->run(array('start', '--daemonize', '--initd'));
where array('start', '--daemonize', '--initd') is a action and action parameters
I had same problem - i need to call action from inside controller and from command
I said same problem because it actually same - you have action which you need to call from console, and call it from controller too.
If you need to call an action(command) as a part of controller action, then i think you need to modify this solution a little. Or is my solution is enough for you?
So here is my solution:
first create action as said in http://www.yiichina.net/doc/guide/1.1/en/basics.controller#action
class NotifyUnsharedItemsAction extends CAction
{
public function run()
{
echo "ok";
}
}
then in controller action is loaded as usuall:
class TestController extends Controller
{
public function actions() {
return array(
'notifyUnsharedItems'=>'application.controllers.actions.NotifyUnsharedItemsAction',
);
}
and in command i run action in such way:
class NotifyUnsharedItemsCommand extends CConsoleCommand
{
public function run($args)
{
$action = Yii::createComponent('application.controllers.actions.NotifyUnsharedItemsAction',$this,'notify');
$action->run();
}
}
Accepting that we are on linux server, for Yii 1.1 real life example would be:
$run = '/usr/bin/php ' . Yii::getPathOfAlias('root').'/yiic' [command]
exec(sprintf("%s > %s 2>&1 & echo $! >> %s", $run, '/dev/null', '/dev/null'));
This will run Yii console command in the background.
Yii is PHP -> you can use the standard php constructs specified at http://php.net/manual/en/function.exec.php and the related methods near the bottom of the page, depending on what exactly you want to achieve.
Also, another very clean solution from cebe on gist:
<?php
// ...
$runner=new CConsoleCommandRunner();
$runner->commands=array(
'commandName' => array(
'class' => 'application.commands.myCommand',
),
);
ob_start();
$runner->run(array(
'yiic',
'idbrights',
));
echo nl2br(htmlentities(ob_get_clean(), null, Yii::app()->charset));
Yii::app()->end();
Typically what you should do in these situations is refactor.
Move the "common" code out of the MyCommand and place it into a class located in the components folder.
Now you can place any head on top of the "common" code without altering your functionality. For example:
protected/components/Mywork.php:
<?php
class Mywork
{
public function doWork()
{
$model = new Product();
$model->title = 'my product';
...
$model->save();
...
}
}
protected/controller/MyworkController.php:
<?php
class MyworkController
{
public function actionDowork()
{
$mywork = new Mywork;
...
}
}
protected/commands/MyworkCommand.php:
<?php
class MyworkCommand extends CConsoleCommand
{
public function run($args)
{
$mywork = new Mywork;
...
}
}
This approach makes testing easier too as you can test Mywork as a single unit outside of the view you are using.