i'm using sfDoctrineGuardPlugin, but i would like a little change, i have 2 groups(admins,users) and i want to manage them separately, what i mean is a page that only shows me the "admins" group and another one the "users" group, i want this because users in "users" group will have some additional info and behavior, i already create a "sfGuardUser" empty module in my backend app, so i can overwrite and add everything i want, i create de actions.class.php
class sfGuardUserActions extends autoSfGuardUserActions
{
public function executeAdmins(sfWebRequest $request)
{
// sorting
if ($request->getParameter('sort') && $this->isValidSortColumn($request->getParameter('sort')))
{
$this->setSort(array($request->getParameter('sort'), $request->getParameter('sort_type')));
}
// pager
if ($request->getParameter('page'))
{
$this->setPage($request->getParameter('page'));
}
$this->pager = $this->getPager();
$this->sort = $this->getSort();
}
}
i copied exactly the "executeIndex" function from "autoSfGuardUserActions" class in cache, and now i can go to guard/admin and it acts like the default one, but now, how can i show only de users from "admins" group?
You have to modify buildQuery() method.
Related
Let's imagine I have two Models:
A list of users User
A list of marbles Marble which belongs to one User
I would like to fetch all the existing marbles with api/marbles and only my marbles with api/user/marbles. The idea is to avoid a route named like api/marbles?owned=true
In my API routes I have this:
Route::get('marbles', 'MarbleController#index');
Route::get('user/marbles', 'MarbleController#index(true)');
Then in my MarbleController:
class MarbleControllerextends Controller
{
function index($owned = false) {
return $owned ? Marble::where('user_id', Auth::id())->get() : Marble::all();
}
}
Unfortunately the MarbleController#index(true) doesn't really work because (true) will not be accepted by Laravel not populate the optional $owned variable.
Is there a way to avoid defining a new method such as Route::get('user/marbles', 'MarbleController#owned');
function owned() {
return $this->index(true);
}
Route::get('marbles/{me?}', 'MarbleController#index'); will work fine.
Here me is an optional parameter. If you omit it, it will take false otherwise true as it's value.
I have a NewsholderPage and NewsPage. NewsPages are subpages of NewsholderPage.
I need users of a certain group to be able to create NewsPages, but not to be able to edit the NewsholderPage.
If I put the following code into the NewsholderPage...
public function canEdit($member = null){
if(permission::check('SUPERUSER')){
return true;
}
return false;
}
... then a not-admin cannot edit the NewsholderPage but also gets a "forbidden" message, when he is trying to create a NewsPage as child of the NewsholderPage.
What is the best way to allow the creation of subpages, while not allowing to edit the parent page?
You'll want to override the canAddChildren method on NewsholderPage to return something other than the default (which is simply $this->canEdit()). To get the default behaviour back, you can use something like:
public function canAddChildren($member = null) {
// Call SiteTree::canEdit rather than NewsholderPage::canEdit
return parent::canEdit($member);
}
i want create register page in 3 step:
Step1: Basic Infomation (ext: example.site/register/step1)
Step2: Profile Infomation (ext: example.site/register/step2)
Step3: Done (ext: example.site/register/step3)
looke like:
Somebody can help me?
To Achieve something like this you have two options:
Do it without reloading the page using javascript to show and hide relevant fields. As you declare a different url for each of your gui-prototypes, I think this is not what you want.
You send the data from one page to the other using models and the POST-data. I will explain this way in detail now, as this seems to be your desired solution. Actually this can be done in a single action if you implement functions to check if there is enough data to render the next page (see the model below).
The following code is not tested, but should give you an idea of how it could be done. Lets start with the model.
The model contains the data of all pages. Working with only model across the two input-pages makes things way easier.
class Registration extends CFormModel {
public $firstName;
public $lastName;
//...
public $gender;
public $age;
//...
public function rules()
{
//add all your field-rules here...
}
//further functions like attributeLabels(), etc. as needed
/**
* Returns the fullname as needed on page two
*/
public function getFirstname()
{
return $this->firstName . ' ' . $this->lastName;
}
public function hasValidStepOneData()
{
//validate the fields you need to continue to step two and return a boolean value.
//yii provides this functionality via the validate-function having the abiliy to only
//only validate certain fields at once. If one of them fails return false, otherwise true.
//see here: http://www.yiiframework.com/doc/api/1.1/CModel#validate-detail
}
public function hasValidStepTwoData()
{
//same as above but with values needed for completing step 2
//return boolean
}
}
Now to the controller. According to your URLs fromabove it should be like this:
class RegistrationController extends CController {
public function actionRegSteps()
{
$model = new Registration();
//get the values if there are any
if (isset($_POST['Registration']) {
$model->attributes = $_POST['Registration'];
}
//decide what to do depending on the data available
if ($model->hasValidStepOneData() && $model->hasValidStepTwoData()) {
//all data needed is present...save the data and redirect to success-page
//TODO: save data here...
$model->unsetAttributes();
$this->render('success');
} else if ($model->hasValidStepOneData()) {
//step one is complete...show step2
$this->render('reg_step2', array('model'=>$model));
} else {
//model is still empty...show step 1
$this->render('reg_step1', array('model'=>$model));
}
}
}
The views are quite simple. You have to keep in mind though that you have to add hidden fields on page two to keep the data of step 1. step one only contains input-fields for firstname, lastname and email. Step 2 contains input-fields for password, gender and age and also hidden fields for firstname, lastname and email. The success-view contains no input-fields at all, as the registration-process is completed by then.
Other than this custom-solution, there is a wizard-extension which could come in handy for you. You can find it here: http://www.yiiframework.com/extension/wizard-behavior/
Moreover a similiar solution was already answered here: https://stackoverflow.com/a/3551704/3402681
I provided you the answer above to give you a general insight on how you can handle this. There is no "correct" solution for this. You have to find the one which suits you the best. Hope I could help!
i need differents results from a model but i don't understand if it is correct make a single call and leave to model all the work or make more calls and collect the result to pass to the view when tables aren't joined or when i need fetch one row from a table and differents rows from others.
First example (more calls, collect and send to view):
CONTROLLER
// call functions of model
$modelName = new Application_Model_DbTable_ModelName();
$rs1 = $modelName->getTest($var);
$rs2 = $modelName->getTest2($var2);
// collect data
$pippo = $rs1->pippo;
if ($rs2->pluto == 'test') {
$pluto = 'ok';
} else {
$pluto = 'ko';
}
// send to view
$this->view->pippo = $pippo;
$this->view->pluto = $pluto;
MODEL
public function getTest($var) {
...
select from db...
return $result;
...
}
public function getTest2($var) {
...
select from db...
return $result;
...
}
Second example (one call, model collect all data, return to controller and send to view):
CONTROLLER
// call one function of model
$modelName = new Application_Model_DbTable_ModelName();
$rs = $modelName->getTest($var);
MODEL
public function getTest($var) {
...
select from db...
if ($result > 0) {
call other function
call other function
collect data
return $result;
...
}
Thanks
There's no one correct answer to this question, but in general, you should endeavor to keep your business logic in one place. Think of it as, "thin controller, thick model." I.e., keep the controllers as small and simple as possible and put all the business logic in the models.
There seems to be a few questions here:
But if i don't need to interact with db and i need only a simply
function is better put that function in model? For example:
CONTROLLER:
public function printAction() {
$data = $this->getRequest()->getPost();
$label = "blablabla";
$this->view->label = $label;
}
first, in the context of Zend Framework this particular example doesn't make much sense. The whole point of the controller is to populate the view template. However, I do get the idea. I would point you to Action Helpers and View helpers as a means to address your concerns. You can always add a utility class to your library for those pieces of code that don't seem to fit anywhere else.
Action Helpers typically are employed to encapsulate controller code that may be repetitive or reusable. They can be as simple or as complex as required, here is a simple example:
class Controller_Action_Helper_Login extends Zend_Controller_Action_Helper_Abstract
{
/**
* #return \Application_Form_Login
*/
public function direct()
{
$form = new Application_Form_Login();
$form->setAction('/index/login');
return $form;
}
}
//add the helper path to the stack in the application.ini
resources.frontController.actionhelperpaths.Controller_Action_Helper = APPLICATION_PATH "/../library/Controller/Action/Helper"
//the helper is called in the controller
$this->_helper->login();
a View helper does the same thing for the view templates:
class Zend_View_Helper_PadId extends Zend_View_Helper_Abstract
{
/**
* add leading zeros to value
* #param type $id
* #return string
*/
public function padId($id)
{
return str_pad($id, 5, 0, STR_PAD_LEFT);
}
}
//in this example the helper path is added to the stack from the boostrap.php
protected function _initView()
{
//Initialize view
$view = new Zend_View();
//add custom view helper path
$view->addHelperPath('/../library/View/Helper');
//truncated for brevity
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
'ViewRenderer');
$viewRenderer->setView($view);
//Return it, so that it can be stored by the bootstrap
return $view;
}
//and to use the helper in the view template
//any.phtml
<?php echo $this->padId($this->id) ?>
i need differents results from a model but i don't understand if it is
correct make a single call and leave to model all the work or make
more calls and collect the result to pass to the view when tables
aren't joined or when i need fetch one row from a table and differents
rows from others.
This question is more about structure then about correctness.
You can interact with your database table models in Action and View helpers for simple/repetitive queries if you need to, however most developers might frown on this approach as being difficult to maintain or just ugly.
Many people seem to favor Doctrine or Propel to help them manage their database needs.
At this point I like to roll my own and currently favor domain models and data mappers, not an end all be all pattern, but seems to be appropriate to your question.
This is not a simple suggestion to implement for the first time, however i found two articles helpful to get started:
http://phpmaster.com/building-a-domain-model/
http://phpmaster.com/integrating-the-data-mappers/
and if you really want to get into it try:
http://survivethedeepend.com/
I hope this answers at least a part of your questions.
I am trying to create wish lists.
There are user and product models. A user has a wish list. A wish list has many products.
The reason I am making it user has wishlist and wishlist has products is so I can have a url like wish_lists/add/:product_id
I created a table called wish_lists with id, user_id, and name.
I also created a table called products_wish_lists with wish_list_id and product_id.
I made here is the wishlists controller:
class WishListsController extends AppController
{
var $hasOne = 'User';
var $hasMany = 'Product';
function beforeFilter()
{
parent::beforeFilter();
$this->Auth->deny('add');
}
function add($id)
{
$user = $this->Session->read("Auth.User");
$this->WishList->set(array(
'User.id' => $user['id'],
'Product.id'=>$id,
'WishList.name'=>'default'
));
if($this->WishList->save())
{
$this->Session->setFlash('This product has been added to your wishlist.', 'flash_good');
}
else
{
$this->Session->setFlash('Error: This product was not added to your wishlist.', 'flash_bad');
}
$this->redirect(array("controller"=>"products","action"=>"view",$id));
}
}
When I go to localhost/wish_lists/add/1 It tells me everytime that it saved. but no data is being added to the database.
Not sure what I am doing wrong?
I never do it that way, I always build a $data array to pass as parameter one to the save function.
I'm not sure, therefore, whether that syntax will allow you to specify the model as you have done, i.e. 'Model.field'. In any case, $this->WishList->save() will only save the Wishlist part.
Better, in my opinion, would be:
$saveData = array(
'User'=>array('id'=>$user['id']),
'Product'=>array('id'=>$id),
'WishList'=>array('name'=>'default'));
$this->WishList->saveAll($saveData);
(or something like that, I've been programming ColdFusion for the last three months and my PHP can be a bit addled)
you are setting the array wrong. it should be $data['User']['id'] = 123; $data['Product']['id'] = 321;
$this->Wishlist->saveAll($data);
There is no point saving the name as that can be found from the product table.
you can have a look at the code here for more ideas https://github.com/Infinitas-Plugins/shop
there is a generic component method in the following link that saves products to the cart or wishlist (different db's) as its pretty much the same thing.
https://github.com/Infinitas-Plugins/shop/blob/master/controllers/components/shop.php#L62