Module dependency and relations - php

"Some commonly used features, such as user management, comment management, may be developed in terms of modules so that they can be reused easily in future projects." - http://www.yiiframework.com/doc/guide/1.1/en/basics.module
I have a lot of projects that requires a user. Every time quite the same database structure and features. Registration, login, logout etc.
Yii tells me that i can reuse modules. Cool... let's start:
I have 3 parts: User, Campaign and Website.
In this project the CampaignModule has a relation to the UserModule (campaign_user [user_id, campaign_id])
The WebsiteModule has a relation to the CampaignModule and to the UserModule.
I want to reuse the UserModule in other projects with features like registration, login, edit etc.
Actual situation:
After creating models with gii every one has relations and dependencies across the modules.
e.g.
UserModule: 'campaigns' => array(self::HAS_MANY, 'Campaign', 'user_id'),
To use the WebsiteModule it's necessary to include the User- and CampaignModule.
Now i even have to include Website- and CampaignModule to use the UserModule!
I also want to update the UserModule across many projects and maybe build a framework with some basic modules.
What is the right way to plan an architecture like this?

There is a yii-user module, what they do, is they allow you to specify additional relations for the User model, on the module configuration:
/**
* #return array relational rules.
*/
public function relations()
{
$relations = Yii::app()->getModule('user')->relations;
if (!isset($relations['profile']))
$relations['profile'] = array(self::HAS_ONE, 'Profile', 'user_id');
return $relations;
}
So you can do something like:
'modules'=>array(
'user' => array(
...
'relations' => array(
'categories' => array(CActiveRecord::HAS_MANY, 'Category', "user_id"),
'account' => array(CActiveRecord::HAS_ONE, 'Account', "user_id"),
),
...
),
),

Related

How can I call AppController's method based on database tables?

I am trying to make CRUD of all database tables in APP controller instead of all CRUD related functions in inherited controllers.
For example:
www.example.com/settings/edit/1
www.example.com/users/edit/1
www.example.com/news/edit/1
I want to shift this Edit functionality to App controller.
In that case, because of all controllers (settings, users, news) are inherited from APP so they can access AppController's method EDIT.
I want to access this without creating a file of inherited controller.
I am trying with this routes.
$routes->connect('/:table/edit/:recordId', ['controller' => 'app', 'action' => 'edit'],['pass' => ['table', 'id'], 'id' => '\d+']);
But its showing error
Missing argument 2 for App\Controller\AppController::edit()
while in controller I wrote :
public function edit($table, $recordId){
}
Any help regarding this will be really appreciable.
Thanks

Doubts about Yii2 RBAC

I've been developing web apps using Yii 1.1.14 so far, but now it's time for an upgrade.
The company where I work has developed its own Access Control system, and I was really OK with it until I saw what it was really like... A combination of 8 tables in the database (not counting the users table), with a bunch of foreign keys.
1 table for controllers
1 table for the actions
1 table for the menu categories
1 table for types of users
And the other tables basically just connect 2 or 3 of those tables at a time.
It works well, but in my point of view it's highly time consuming to maintain all those tables, and at some point, when your application goes online, if it hits a certain amount of users it could get really slow. specially because 2 of those tables have the user's table primary key as foreign key.
So I've decided that, when I start developing on Yii 2, I'm going to start using RBAC, so I started looking for tutorials online... Only finding many different versions of the same code with author's role, and permissions for create or update posts.
I found a combination of 5 videos on Youtube, but they are about Yii 1 RBAC. They were helpful because I managed to understand most of RBAC's functionality, but I still have some doubts that I'll
enumerate below. And keep in mind that for this Access Control system I'm using the DBManager class.
My Doubts
Yii 1's RBAC used to have 3 tables: auth_assignment, auth_item and auth_item_child. Now in Yii 2 RBAC, a new table appears that is called auth_rule and I still don't understand what that specific table is doing there, how to use it or how to populate it.
I see that it's possible to restrict the user's access to some actions by using the controller's behavior method, and assigning access to some actions depending on the user's role, but when it comes to this I have to split my question into 2:
2.1. First: If you can just restrict the access to actions by setting it up in the behaviors method, then what's the use of saving permissions to the auth_item table?
2.2. Second: If you DO decide to control access according to permissions, then how exactly do you do it, because I find myself writing the following type of code inside of every function and I don't think using RBAC is supposed to be this tedious. There has to be another way.
public function actionView($id)
{
if(Yii::$app->user->can('view-users')){
return $this->render('view', [
'model' => $this->findModel($id),
]);
}else{
#Redirect to a custom made action that will show a view
#with a custom error message
$this->redirect(['//site/notauthorized']);
}
}
Because of the Access Control System that we use right now, when a user logs in, a complex query is executed that will end up returning an array that will be saved as a session variable, and will be used to create a menu with as many dropdownlists as menu categories, that the controllers that the user has access to belong to. How can this be done with RBAC?
I can only really answer 2.2 of your question, as 3 doesn't sound at all like something an RBAC should do. You could, however, get the information you needed from the rules table most likely, provided you followed a naming convention that matched your controllers or actions.
On to answering 2.2 though:
You can simply set the behavior like such:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'actions' => ['view'],
'roles' => ['view-users'], //<-- Note, rule instead of role
],
]
]
}
This doesn't solve a different problem of 'view-own-users' style permissions, as this needs to inspect the ActiveRecord model (well, at least it does in my application). If You want to achieve this, take a look at my post in the Yii forums here:
http://www.yiiframework.com/forum/index.php/topic/60439-yii2-rbac-permissions-in-controller-behaviors/#entry269913
I use it in one of the simplest method,I use them in the behaviours of my controller.
public function behaviors()
{
return [
'access' => [
'class' => \yii\filters\AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['sysadmin'],
'actions' => ['index','view','update'],
],
[
'allow' => true,
'roles' => ['staff'],
'actions' => ['index','create','update','view'],
],
],
],
];
}
Here roles are the one created in the auth-item table in the database and they have been assigned for users in auth-assignment table. In the behaviours we just use it as above. In the above code sysadmin can have access to index, view and update action, whereas staff can have access to index,create, update and view action.
Yii2 needs a little setup when it comes to using RBAC under your controllers AccessControl. I got around it by making my own AccessRule file.
namespace app\components;
use Yii;
class AccessRule extends \yii\filters\AccessRule
{
protected function matchRole($user)
{
if (empty($this->roles)) {
return true;
}
foreach ($this->roles as $role) {
if(Yii::$app->authManager->checkAccess($user->identity->code, $role))
return true;
}
return false;
}
then in your controller u can use something like this:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'ruleConfig' => [
'class' => 'app\components\AccessRule'
],
'rules' => [
[
'actions' => ['index', 'resource-type'],
'allow'=> true,
'roles' => ['admin'],
],
],
],
];
}
Where admin is defined as a auth_item and the user is in the auth_item_assignments.
As I have created a new Rbac system for yii2. you can direct permission for a action and action will show you are not authorisez for this action.
By this you find that you will only provide access for action that need to identify.
I uploaded my detail here you can find lot of solution here.
This is the best solution i could come up with when facing the need to filter access by permissions, it's bothersome but can be useful if you're trying to create roles in a productive enviroment and want to use rbac.
use yii\web\ForbiddenHttpException;
if(Yii::$app->user->can('view-users')){
return $this->render('view', [
'model' => $this->findModel($id),
]);
}else{
throw new ForbiddenHttpException('You dont have access to this site');
}

Nested Multi-Module app with Phalcon PHP framework?

I know the multi module application structure of Phalcon, but is it possible to have a nested module structure like following example shows? I want to have a system, where I can hot-plug new sub-modules (for backend, frontend) to the system. Routes, menu entries etc. should get automatically extended when I copy a new module folder into the sub-module folder.
module-backend
controllers
models etc.
sub-modules
forum
controllers
models
etc.
news
controllers
models
etc.
users
controllers
models
etc.
module-frontend
controllers
models
sub-modules
like backend module structure
Is there a way with events to hot-plug such modules to the system?
yes you can. the first solution what i can think of is this:
while registering your loader in index.php:
$loader = new \Phalcon\Loader();
$loader->registerDirs(array(
$config->application->controllersDir,
$config->application->pluginsDir,
));
$loader->registerPrefixes(
array(
"Model_" => $config->application->modelsDir,
)
);
$loader->registerNamespaces(array(
'RemoteApi' => $config->application->librariesDir . 'RemoteApi/'
));
$loader->register();
notice registerPrefixes. you can register different prefix for different models like:
$loader->registerPrefixes(
array(
"FModel_" => $config->application->forumModels,
"NModel_" => $config->application->newsModels,
)
);
you can register prefixes to other things too. I also added this example
$loader->registerNamespaces(array(
'RemoteApi' => $config->application->librariesDir . 'RemoteApi/'
));
this way you can order your stuff under different namespace's.
You can approach my organization structure of modules in the application:
https://github.com/oleksandr-torosh/yona-cms
The modules are presented as separate entities:
https://github.com/oleksandr-torosh/yona-cms/tree/master/app/modules
Index
Page
Projects
Video
Likely for your application you do not need to use the standard multi-modular structure from the box

Setup CakePHP with an existing Database

I have a MySQL server database currently setup which has a few simple tables to track orders, such as tblOrders, tblUsers, tblProducts.
Although I have a website working with it fine now, I'd like to setup CakePHP to act as the server side framework for handling interaction with the database rather than using hand written queries in my PHP pages.
Is there a simple way to setup CakePHP with my existing Database/tables?
If I understand correctly, I will have a main MyApplication class which Extends Controller, as well as Order, User, Product, (... other tables) classes which each extend the MyApplication class.
It looks like the REST guide uses a method in the configuration file called Router::mapResources('recipes');. Will this create the controllers for each table with the default methods to use for REST?
I.e., in the /app/config/routes.php configuration file:
// /app/config/routes.php
Router::mapResources('tblOrders');
Router::mapResources('tblUsers');
Router::mapResources('tblProducts');
// /app/config/database.php
<?php
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/myStoreDB',
'persistent' => false,
'host' => 'localhost',
'login' => 'admin_user',
'password' => 'c4k3roxx!',
'database' => 'main_db',
'prefix' => ''
);
}
If you want Model, Controller and View code created for you, you're looking for baking.
Cake expects your database tables to follow a naming convention. I'm not sure how the bake will go because your tables don't match this convention. You may need to create your model classes by hand and specify the useTable attribute on each class. For example:
<?php
class Order extends AppModel {
public $useTable = 'tblOrders';
}
Once this is done, I expect the baking of Controllers and Views should work as normal. Note that with mapResources you still need Controller code. That function just generates routes.
If Cake is the only thing that will be touching this database, I recommend renaming tables and columns in line with the conventions it expects.

How to have Yii generate drop-down list from known users?

I am just starting learning to use yii, and already managed to do some basic stuff.
Let's say I have two simple tables: "users" and "projects" where the relation is 1 to many (one user can have many projects)
I have generated CRUD using GII, but in the "create/edit user page" this doesn't provide the dropdown but only a text field where I need to enter the user ID.
When editing a project, I would like to have a dropdown list where I can select a user (so the element should display a list of user names).
I assume GII is not able to generate the controller and view code for this
What would be the best practice for doing this?
I have already declared the relationships as instructed in http://www.yiiframework.com/doc/guide/1.1/en/database.arr
public function relations()
{
return array(
'projects_rel'=>array(self::BELONGS_TO, 'Users', 'user_id'),
);
}
and
public function relations()
{
return array(
'users_rel'=>array(self::HAS_MANY, 'Projects', 'project_id'),
);
}
Find the sample code to generate users list
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'project-form',
'enableAjaxValidation' => true,
));
?>
<?php echo $form->dropDownList($model, 'user_id',
CHtml::listData(Projects::model()->with('projects_rel')->findAll(), 'id', 'username'),
array('style'=>'width:150px;')
); ?>
Checkout these gii extension for generating extended CRUDs:
Gii Template Collection (FullModel, FullCRUD)
latest development on github
Giix
Both are able to render forms with relation inputs. GTC uses a relation widget for these inputs which can be customized.
Don't forget to uncomment
$this->performAjaxValidation($model)
on the Controller or you'll have to items created instead of one!

Categories