Yii2 adding a property to the application - properties

I would like to add a new property 'business' to the Yii2 application so I can access it like:
Yii::$app->business
I have tried adding it directly to the config file:
'Id' => 'app-frontend',
'name' => 'Application Name',
'business' => 'Business Name',
....
Which gives me an 'unknown property exception' for 'buisness'
After some searching I tried:
Yii::$app->session->set('app.business','Business Name');
Yii::$app->session->get('app.buisness');
But only works when I access it by session
I know how to create it in the params set up, but rather us the app->name. method.
I imagine I need to add the business property in the root model? But not sure where to drill into it at.
Any help to point me in the right direction please.

You can extend Application class, add required properties, and use it on bootstrap.
Create class for web:
class MyApplication extends \yii\web\Application {
public $supportname;
}
And use it in index.php:
(new MyApplication($config))->run();
You need to do the same for \yii\console\Application and yii script.

Related

Typo3 persistence variables in extended tx_scheduler_Task class

I am not sure how to call it other then "persistence". It took me quit a while to figure out why my code was not working on adding an item in my array...
Lets say I have a class with a protected array variable:
protected $fields = array(
'Features', 'Id'
);
I my class i can use this in a method by using: $this->fields
First time all is well.
Now i do change some stuff and i need another field, so I update me $fields to:
protected $fields = array(
'Features', 'Id', 'Title'
);
Strangely, if I now want to use $this->fields, they are "gone". On var_dump it returns NULL. Only if I change the name, the protected var can be used again. But I do not want to change the name of course.
I did empty all cache and reloaded browser etc, but nothing does work. Anyone an idea?
Update: I should add it is in a scheduler class that extends tx_scheduler_Task.

Save DataObject relation when fields are added via getCMSFields()?

With this code the DataObject ID (InternalExternalLinkID) is not saved to the page when the CMS page is published, how to I automatically add the scaffolding from the dataobject and have the relationship saved (without manually doing onAfterWrite() as described at http://www.silverstripe.org/data-model-questions/show/11044):
class Page extends SiteTree {
private static $has_one = array(
'InternalExternalLink' => 'InternalExternalLink'
);
function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldsToTab('Root.Main', singleton('InternalExternalLink')->getCMSFields());
I understand you probably need to create the dataobject first, get the ID and then save to the Page object - can the CMS not do this scaffolding, create (or update) and save this related dataobject automatically like ModelAdmin does?
You should use a GridField for this which handles saving to the nested object. Checkout the relational handler module for a has_one relationship editor. You can also get it working without the module if you don't want to install another dependancy. Just create a new GridField instance and pass your has_one record as an DataList query.
http://addons.silverstripe.org/add-ons/simonwelsh/gridfieldrelationhandler

Sharing data between HtmlHelpers

I'm looking for a way to share data between HtmlHelpers. The goal is to set configuration once instead of passing a parameter with each call. In the example below, I'm setting the form type to determine the grid configuration:
#{ Html.SetFormType(HtmlHelpers.FormType.Boxed); }
#Html.FormItemFor(m => m.LoginName)
#Html.FormItemFor(m => m.Password)
public static void SetFormType(this HtmlHelper helper, FormType formType)
{
helper.ViewBag.FormType = formType;
helper.ViewContext.ViewBag.FormType = formType;
}
Setting ViewBag does not persist through subsequent #Html calls. Setting ViewContext.ViewBag persists, but is it safe to do so?
The existing method EnableUnobtrusiveJavaScript is set in an instance of the ScopeCache class, which in turn is added to HttpContext.Items. Perhaps that's also a candidate to store my data?
You can use the request-based-scope object of HttpContext.Current.Items because HttpContext.Current is actually the only container that is unique and always there in a request.
Cheers
PS: don't put everything directly into the items. Just add a controller-item there and work on this.

Display the login form in the layouts main.php in Yii

I want to change the the "views/layouts/main.php" to display the login form whenever the user isn't authenticated.
So I changed the "siteController" actionIndex like that:
public function actionIndex() {
$loginForm = new LoginForm();
$this->render('index', array('loginForm'=>$loginForm));
}
And then call it in "views/layouts/main.php" like that:
if(Yii::app()->user->isGuest):
echo $loginForm;
else :
echo 'JJJ';
endif;
Then when I go to my website, It display the error: "Undefined variable: loginForm".
I don't know how to fix this? :(
Define new property in your controller class:
public $loginForm;
In your main.php access it like:
echo $this->loginForm;
If you pass variable in your render method it will be available inside view file only, but not in layout file.
It's because the index template is loaded before main template. So, better way to do hat you want, is to define a public property in your Controller. I suggest you to define this property in Controller class because SiteController and *Controller extends it.
Then, you can run this.
if(Yii::app()->user->isGuest) {
echo $this->loginForm;
} else {
echo 'JJJ';
}
Pay attention, because in this way of work you go out MVC pattern. This way of work force you to define a LoginForm in each action. I suggest you to do that:
Leave clean your calls to render file.
public function actionIndex() {
$this->render('index');
}
And add a getLoginForm method in you Controller class obtaining:
if(Yii::app()->user->isGuest) {
echo $this->getLoginForm();
} else {
echo 'JJJ';
}
There are a couple issues here. Firstly, you are creating an object called $loginForm and assigning it a value of new LoginForm();
$loginForm = new LoginForm();
I'm not sure if you are doing this on purpose and LoginForm() is a function or a method that returns something, but I have a feeling you were intending to do:
$loginForm = new LoginForm;
Which creates a new instance of the class LoginForm (which is a default Yii webapp CFormModel class). Even if that is the case, there are better ways to do this.
The easiest way is to call a renderPartial of the already existing login.php view (located in protected/views/site/login.php) inside your index.php view like so:
if(Yii::app()->user->isGuest) {
$this->renderPartial("loginform",array("model"=>new LoginForm));
} else {
echo 'JJJ';
}
This renders the view login.php (without rendering the layout because we have already rendered the layout - here's the docs on render and renderPartial) and pass it a new instance of the model LoginForm assigned to a variable called $model.
You will most likely have to edit the look of login.php view to make it "fit", but keep in mind that this view is being used in the SiteController actionLogin as well.
All that's left to do then is modify your actionIndex to handle the form submission (you can just copy the existing SiteController actionLogin functionality)
Another nicer solution would be to create a widget for the login form which can be used all over your application. I'm not going to go into that, but you can read up about it here on SO or check out this tutorial or this one.

CakePHP: get user info in models

I'm moving some of my find code inside models.
Previously in my controller I had
$this->Book->Review->find('first', array(
'conditions' => array(
'Review.book_id' => $id,
'Review.user_id' => $this->Auth->user('id')
)
));
so in my Review model I put something like
function own($id) {
$this->contain();
$review = $this->find('first', array(
'conditions' => array(
'Review.book_id' => $id,
'Review.user_id' => AuthComponent::user('id')
)
));
return $review;
}
So I'm calling AuthComponent statically from the Model. I know I can do this for the method AuthComponent::password(), which is useful for validation. But I'm getting errors using the method AuthComponent::user(), in particular
Fatal error: Call to a member function
check() on a non-object in
/var/www/MathOnline/cake/libs/controller/components/auth.php
on line 663
Is there a way to get the info about the currently logged user from a model?
Create a new function in the "app_model.php" ("AppModel.php" in CakePHP 2.x), so it will be available at all models within our application:
function getCurrentUser() {
// for CakePHP 1.x:
App::import('Component','Session');
$Session = new SessionComponent();
// for CakePHP 2.x:
App::uses('CakeSession', 'Model/Datasource');
$Session = new CakeSession();
$user = $Session->read('Auth.User');
return $user;
}
in the model:
$user = $this->getCurrentUser();
$user_id = $user['id'];
$username = $user['username'];
The way that I use is this:
App::import('component', 'CakeSession');
$thisUserID = CakeSession::read('Auth.User.id');
It seems to work quite nicely :-)
I think the code is fine as it is and belongs in the Controller, or at the very least it needs to receive the ids from the Controller and not try to get them itself. The Model should only be concerned with fetching data from a data store and returning it. It must not be concerned with how the data is handled in the rest of the application or where the parameters to its request are coming from. Otherwise you paint yourself into a corner where the ReviewModel can only retrieve data for logged in users, which might not always be what you want.
As such, I'd use a function signature like this:
function findByBookAndUserId($book_id, $user_id) {
…
}
$this->Review->findByBookAndUserId($id, $this->Auth->user('id'));
There is a nice solution by Matt Curry. You store the data of the current logged user in the app_controller using the beforeFilter callback and access it later using static calls. A description can be found here:
http://www.pseudocoder.com/archives/2008/10/06/accessing-user-sessions-from-models-or-anywhere-in-cakephp-revealed/
EDIT: the above link is outdated: https://github.com/mcurry/cakephp_static_user
I think this is not good idea to get value from Session. Better solution to get logged user id inside any model simply try this:
AuthComponent::user('id');
This will work almost every where. View, Model and Controller
Dirtiest way would be to just access the user information in the Session. Least amount of overhead associated with that.
The "proper" way would probably be to instantiate the AuthComponent object, so that it does all the stuff it needs to be fully operational. Much like a death star, the AuthComponent doesn't really work well when not fully setup.
To get a new AC object, in the model:
App::import( 'Component', 'Auth' );
$this->Auth = new AuthComponent();
Now you can use $this->Auth in the model, same as you would in the controller.
For CakePHP 3.x this easy component is available: http://cakemanager.org/docs/utils/1.0/components/globalauth/. Direct accessing the Session is not possible because of different SessionKeys.
With the GlobalAuthComponent you can access your user-data everywhere with: Configure::read('GlobalAuth');.
Greetz
Bob
I use cake 2.2 and these both work great:
$this->Session->read('Auth.User');
//or
$this->Auth->user();
You can also get a field of currently logged in user:
$this->Session->read('Auth.User.email');
//or
$this->Auth->user()['email'];
None of these solutions work in CakePHP version 3. Anyone know of a way to do this? Right now, I'm completely stepping around the framework by accessing the $_SESSION variable directly from my model.