I have a widget that uses assets. The asset look like this:
class publicHeaderNavbarAsset extends AssetBundle {
public $sourcePath = '#app/components/#device';
public $css = [
'styles.css'
];
public $js = [];
public $depends = [];
}
I also have a (bootstrapped) component, defined like that:
class Aliases extends Component {
public function init() {
Yii::setAlias('#device', Utils::device());
}
}
Utils::device() is a function that parses the UA of the device and returns mobile, tablet or desktop, depending on the device type.
The problem is that Yii2 doesn't seem to be converting #device to the value it has. I first thought that it could be my fault, but then I changed the sourcePath to:
public $sourcePath = '#app/components/#app';
just to see if that will trigger an error with a duplicated path (basepath/componenets/basepath), but it didn't.
Is there a way I can change the sourcePath of my asset at runtime? Or maybe make Yii2 parse all the aliases in sourcePath?
Look at the getAlias function http://www.getyii.com/doc-2.0/api/yii-baseyii.html#getAlias()-detail
It will basically not match your second alias in the string you have given it.
You can try setting
Yii::setAlias('#device', '#app/components/' . Utils::device());
and
public $sourcePath = '#device';
This should work as you should be able to set an alias based on another alias
http://www.yiiframework.com/doc-2.0/guide-concept-aliases.html#defining-aliases
Related
I want to set public static variable inside vendor folder.
I want to change this
public static $serverKey_as = 'my-secret-key';
into this, get the key from config -> app.php file
public static $serverKey_as = config('app.serverkey_as');
But i get this error
Symfony\Component\ErrorHandler\Error\FatalError: Constant expression contains invalid operations in file
this is my code in config -> app.php
'serverkey_as' => env('SERVERKEY_AS', 'my-defauly-secret-key'),
and this is my .env
SERVERKEY_AS = 'my-secret-key'
and this is what i've try but still no luck
<?php
namespace Midtrans;
class Config
{
public static $serverKey_as;
public function __construct()
{
return self::$serverKey_as = config('app.serverkey_as');
}
}
Got any hint for me?
First of all: you really shouldn't change code in the /vendor directory. That directory contains code made and maintained by other people.
Furthermore, an initial static variable assignment cannot contain function calls of any kind. I would suggest using the boot() method in your AppServiceProvider to change the static variable to the value you want:
public function boot()
{
\Midtrans\Config::$serverKey_as = config('app.serverkey_as');
//...
}
I was trying to add an uploadfield to a Custom DataExtension and got the Image field working. However the image i uploaded stays in concept mode, and i have to go to the File tab to publish it. I tried to use the code provided in the Silverstripe documentation but this only seems to work on regular pages. I found a question similar to mine:How to automaticaly publish files uploaded to a dataobject in Silverstripe model admin however this only seems to work on DataObjects.
This is my current code:
<?php
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\Assets\Image;
use SilverStripe\Assets\Storage\AssetStore;
use SilverStripe\Versioned\Versioned;
use SilverStripe\ORM\DataExtension;
class CustomSiteConfig extends DataExtension
{
private static $db = [
];
private static $has_one = [
'Logo' => Image::class
];
private static $owns = [
'Logo'
];
private static $extensions = [
Versioned::class,
];
private static $versioned_gridfield_extensions = true;
public function updateCMSFields(FieldList $fields)
{
$fields->addFieldToTab("Root.Header", LiteralField::create("","<h1>Header</h1>"));
$fields->addFieldToTab("Root.Header", UploadField::create('Logo', 'Logo'));
}
}
Does anyone know a solution?
There's currently a bug that prevents "owned" records to be published if the owning dataobject is not versioned.
I think you're experience this bug, since SiteConfig is not versioned and thus won't publish owned files/images when it's being saved.
Until this bug has been resolved, you could use an onAfterWrite hook in your extension to publish the file:
public function onAfterWrite()
{
if ($this->owner->LogoID) {
$this->owner->Logo()->publishSingle();
}
}
For example, I created a new page, and I'd like to use, for example, backbone.js, custom css file and some collection of images. Where should I declare all this stuff in Yii2? I found the AppAsset.php module, but this is only for css/js files and I haven't noticed any changes when my css/js files and path were declared there:
class AppAsset extends AssetBundle {
public $basePath = '#webroot';
public $baseUrl = '#web';
public $css = [
'css/site.css',
'js/jquery.mobile-1.4.2.min.css',
];
public $js = [
'js/jsquery-2.1.0.min.js',
'js/jquery.mobile-1.4.2.min.js',
'js/script.js',
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
];
}
What am I doing wrong?
It took me a while to figure it out, but below is the relevant part of the Yii2 source code
if ($this->sourcePath !== null && !isset($this->basePath, $this->baseUrl)) {
list ($this->basePath, $this->baseUrl) = $am->publish($this->sourcePath, $this->publishOptions);
}
So Yii2 will publish assets only if $sourcePath is set, and $basePath and $baseUrl are not set(!). The latter tripped me up, and it looks like the same goes for you.
So I have this AppAsset, which duly publishes
use yii\web\AssetBundle;
class AppAsset extends AssetBundle
{
public $sourcePath = '#app/assets/app';
public $css = [
'css/openbook.css',
'fontello/css/fontello.css',
'fontello/css/animation.css'
];
public $js = [
'js/plug.openbook.js',
'js/plug.interpret.js',
'js/plug.drop.message.js'
];
public $depends = [
// 'yii\web\YiiAsset',
// 'yii\bootstrap\BootstrapAsset',
];
}
Of course, I have in the main layout
use frontend\assets\AppAsset;
...
AppAsset::register($this);
to use this AppAsset or any other you should register it in the view
use app\assets\AppAsset;
AppAsset::register($this);
At first, you should create SomeAsset class in your app/assets/ folder with your new js and css files.
You can extend your AppAsset overloading its properties.
Next use this in SomeController
use Yii;
use app\assets\SomeAsset;
and in actionSome like this:
SomeAsset::register(Yii::$app->view);
From personal experience, assets are one of the parts of Yii that I found extremely frustrating.
It is hard to reliably find out where the file is going to be and the switching back and forth with debug mode on and off will create further frustration.
I suggest scrapping the asset handling and just keep all your JS files in a folder, then it can be included like this:
Yii::app()->clientScript->registerScriptFile('/js/jquery.jeditable.mini.js');
I have been unsuccessfully trying to update database records within a package (my first) I am trying to develop. It's a file upload script and it is suppose to upload the file to a directory, save its path, the name given to it by the user and the set of tags assigned to a database. Insert works perfectly. However, when the file is updated with new tags (same name) it just gives me a blank response. My implementation is as below:
$filename = Input::get('filename') . '.' . Input::file('file')->getClientOriginalExtension();
$tags = Input::get('tags');
$doc = Document::firstOrNew(array('filename' => $filename));
$doc->tags = $tags;
$saved = $doc->save();
Document model is as below:
class Document extends Eloquent {
protected $table = 'documents';
protected $softDelete = true;
protected $fillable = array('filename');
public function __construct($attributes = array()) {
parent::__construct($attributes);
}
}
What am I doing wrong? Why would "selects" not work while insert works perfectly?
Old question, but I thought I would answer just to be tidy. Looks like you are missing the relationship definition in your model:
public function tags()
{
return $this->hasMany('App\YourTagsModel');
}
Also in turn, your tags model should have the opposite definition:
public function document()
{
return $this->belongsTo('App\YourDocumentModel');
}
I am using the following code to initialize a model from within my controller:
$this->load->model('model_name');
Is it possible to modify the above line somehow so that the model constructor recieves a parameter? I want to use the following code in the model constructor:
function __construct($param_var) {
parent::Model();
$this->$param_var = $param_var; //I'm not even sure this works in PHP..but different issue
}
This would be very helpful so that I can reuse my model classes. Thanks.
UPDATE:
(from one of the answers, my original question is solved..thanks!)
Just to explain why I wanted to do this: the idea is to be able to reuse a model class. So basically to give a simple example I would like to be able to pass an "order_by" variable to the model class so that I can reuse the logic in the model class (and dynamically change the order-by value in the sql) without having to create a separate class or a separate function.
Is this poor design? If so could you please explain why you wouldn't do something like this and how you would do it instead?
You can't pass parameters through the load function. You'll have to do something like:
$this->load->model('model_name');
$this->model_name->my_constructor('stuff');
In the model:
function my_constructor($param_var) {
...
}
Response to update:
You could just pass the order_by value when you're calling your model function. I'm assuming in your controller action, you have something like $this->model_name->get($my_id); Just add your order_by parameter to this function. IMO this makes your model logic more flexible/reusable because the way you were doing it, I assume setting order_by in the constructor will set the order_by value for every function.
In model
<?php
/* Load Model core model */
/* BASEPATH = D:\xampp\htdocs\ci_name_project\system\ */
include BASEPATH . 'core\\Model.php';
class User_model extends CI_Model {
/* Properties */
private $name;
/* Constructor parameter overload */
public function __construct($name) {
$this->set_name($name);
}
/* Set */
public function set_name($name) {
$this->name = $name;
}
/* Get */
public function get_name() {
return $this->name;
}
}
in controller
<?php
class User_controller extends CI_Controller {
public function index() {
/* Load User_model model */
/* APPPATH = D:\xampp\htdocs\ci_name_project\application\ */
include APPPATH . 'models\\User_model.php';
$name = 'love';
/* Create $object_user object of User_model class */
$object_user = new User_model($name);
echo $object_user->get_name(); // love
}
}
I see your reasoning for this, but may I suggest looking at Object-Relational Mapping for your database needs. There is a user-made ORM library for CodeIgniter called DataMapper that I've been using lately. You can use tables in your controllers as objects, and it may be a better fit for your problem.
Instead of using DataMapper i suggested to use IgnitedRecord because that the DataMapper is no longer maintained more over it has been replaced into Ruby
I am using CI ver 3.X, so what I am about to say is it will work for Codeigniter 3.X (and I haven't checked ver 4+ yet).
When I went thru the source code of the function model() in file system/libraries/Loader.php, noticed that it does not support loading the model with construct parameters. So if you want to make this happen you have to change the source code (bold, I know, and I just did).
Down below is how I did it.
1. Firstly, replace line 355
$CI->$name = new $model();
with some modifications:
$_args_count = func_num_args();
if(3 < $_args_count){
$refl = new ReflectionClass($model);
$CI->$name = $refl->newInstanceArgs(array_slice($_args_count, 3));
}else{
$CI->$name = new $model(); // origin source code
}
2. Load the model with a bit difference:
$this->load->model("model_name", "model_name", false, $param_var); // where amazing happens
Now you can have $this->model_name as you wished.