I am using a Module in yii, and the module will be used when a property of an application model is true.
How can I get all the model names available in my application so that i can establish relations on conditional basis between application models having the property and the module?
You can use below method to get class name:
public function modelName()
{
return __CLASS__;
}
and call it like this:
$model = new State();
echo $model->getModelName();
Related
I have the following tables
1. Environment
--------------
env_id
env_name
env_description
repo_id
2. Repository
--------------
repo_id
repo_name
repo_url
Now multiple environments can be associated with same repository. I am very new to Eloquent and so has a confusion that which kind of relation this is ? I have an api and I would like to return repo details when I access an environment endoint. So when I use Evironment::all(), I would like to get the associated Repository. How can I do this ?
I went through the examples given in the documentation, but it seems like I have a scenario which is not mentioned there.
That will be a One To Many(inverse) relationship.
//Environment Model
public function repository()
{
return $this->belongsTo('App\Repository');
}
//Repository Model
public function environments()
{
return $this->hasMany('App\Environment', 'repo_id');
}
Then you can return all the Environment with their relationship as follow:
Environment::with('repository')->get();
According to your description, it should be a one-to-many relationship between two tables. Therefore, in plain English sentences, it would be, the Repository has many Environments and the Environment model belongs to the Repository. Let's build up those two models.
Repository model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Repository extends Model
{
public function environments()
{
return $this->hasMany(Environment::class);
}
}
Environment model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Environment extends Model
{
public function repo()
{
return $this->belongsTo(Repository::class);
}
}
Notice: I name after Environment::repo() instead of Environment::repository().
If we called Environment::repository as a property on the Environment object inside a foreach loop, it would return null instead of Repository object. It may be eloquent's naming issue. To be honest, I don't know the reason so far. I'm using Laravel 7.
Once you're done with the creations of models, you can play with data using them. As you need to get the associated Repository object with Environment object, check out the following code:
<?php
$environments = Environment::all();
foreach ($environments as $environment) {
echo $environment->repo->repo_name . '<br>';
}
In PS 1.7 documentation, we can read multiple time that the PS override system is not recommended, an it's not allowed to publish module in the PS marketplace.
We have to only use hooks, and extend existing class, and I understood why.
But how to use the extended class instead of the core one in our custom theme ?
Let use a example :
I want to add a custom field for categories.
In a module I extend the CategoryCore class :
class Category extend CategoryCore{
private $bottom_description
...
}
Then to add the field in the category's admin page I can use some hook like displayBackOfficeCategory and actionBeforeAddCategory.
But I'm not sure for the front : the new variable have to be accessible in some theme templates files.
In my custom theme, in the category.tpl template, $category->bottom_description is undefined.
Fix this issue by overriding the CategoryController is easy,but how to do this only with hook ?
The only way I found is to use the actionFrontControllerSetMedia hook, like this :
function HookActionFrontControllerSetMedia(){
// get my custom Category object base on url
this->context->smarty->assign(["category_bottom_description"=>$category->buttom_description]);
}
This look tricky, and my new field is still not accessible in other context.
So what is the proper way to get this property available in my custom them ?
Ideally, the new property should be available every time we found a category object, like this : $category->bottom_description.
Do not forget to define a new field at category class because at the front you have not a class instance but an array which is converted within ObjectPresenter class. So follow this way. Extend your Category class and add all necessary definitions
class Category extends CategoryCore
{
public $bottom_description;
public function __construct($idCategory = null, $idLang = null, $idShop = null)
{
Category::$definition['fields']['bottom_description'] = array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml');
$this->bottom_description = 'bottom_description'; // just to add demo data
parent::__construct($idCategory, $idLang, $idShop);
}
}
and then the field bottom_description will be available in the category.tpl but like an array {$category.bottom_description}. Hope it will help you.
I have a entity in my symfony/sonata application which is not persisted via doctrine orm. Instead i would like to fill the data for these entities on demand by calling an api ...
How can i connect this custom managed entity with my existing model which is managed by doctrine orm?
Is there a way to exchange the doctrine managing part with my custom api calls? I know there are some repository functions like findAll() findBy() and so on ... is the solution to overwrite this functions?
Another approaches?
Thanks
I had a similar use case. I ended up with a solution which is roughly the following.
1) Create a custom ModelManager class. In my case I extended the one provided for Doctrine (Sonata\DoctrineORMAdminBundle\Model\ModelManager), but you can also directly implement Sonata\AdminBundle\Model\ModelManagerInterface.
Override the methdods you need to change (e.g. create(), update(), delete()).
# MyCustomModelManager.php
namespace AppBundle\Admin;
use Sonata\DoctrineORMAdminBundle\Model\ModelManager;
class MyCustomModelManager extends ModelManager {
public function create($object){ // Your custom implementation }
public function create($object){ // Your custom implementation }
public function create($object){ // Your custom implementation }
}
2) Register your new model manager as a service (not needed if you use Symfony 3.3 with the default container configuration, which includes automatic configuration of classes as services)
# services.yml
...
AppBundle\Admin\MyCustomModelManager:
arguments: [ '#doctrine' ]
...
3) Configure your admin class to use your custom model manager, for example:
app.admin.myadmin:
class: AppBundle\Admin\MyAdmin
tags:
- { name: sonata.admin, manager_type: orm }
arguments: [~, AppBundle\Entity\MyEntity, ~]
calls:
- [ setModelManager, [ '#AppBundle\Admin\MyCustomModelManager' ]]
Hope it helps :)
I have Model_Group that extends ORM.
I have Controller_Group that gets a new ORM:
public function before()
{
global $orm_group;
$orm_group = ORM::factory('Group');
}
...and it has various methods that use it to get different subsets of data, such as...
public function action_get_by_type()
{
global $orm_group;
$type = $this->request->param('type');
$result = $orm_group->where('type', '=', $type)->find_all();
}
Then I have another controller (in a separate module) that I want to use to manipulate the object and call the relevant view. Let's call it Controller_Pages.
$orm_object = // Get the $result from Controller_Group somehow!
$this->template->content = View::factory( 'page1' )
->set('orm_object', $orm_object)
What is the best way to pass the ORM object from Controller_Group to Controller_Pages? Is this a good idea? If not, why not, and what better way is there of doing it?
The reason for separating them out into different controllers is because I want to be able to re-use the methods in Controller_Group from other modules. Each module may want to deal with the object in a different way.
This is the way I would do it, but first I would like to note that you shouldn't use global in this context.
If you want to set your ORM model in the before function, just make a variable in your controller and add it like this.
public function before()
{
$this->orm_group = ORM::factory('type');
}
In your Model your should also add the functions to access data and keep the controllers as small as possible. You ORM model could look something like this.
public class Model_Group extends ORM {
//All your other code
public function get_by_type($type)
{
return $this->where('type', '=', $type)->find_all();
}
}
Than in your controllers you can do something like this.
public function action_index()
{
$type = $this->request->param('type');
$result = $this->orm_group->get_by_type($type);
}
I hope this helps.
I always create an helper class for stuff like this
Class Grouphelper{
public static function getGroupByType($type){
return ORM::factory('Group')->where('type','=',$type)->find_all();
}
}
Now you're been able to get the groups by type where you want:
Grouphelper::getGroupByType($type);
I'm working on a web app using the Lithium Framework with a MongoDB database.
On one page of the application - I want to display data from multiple object types. I understand the concept of relationships (i.e. belongsTo, hasMany, etc.) between models. But, my questions has to do with Controller relationships.
For example, assume I have two objects named "People" and "Companies". I want to show specific information about Companies on a "people" view. I have done the following:
1) In the "People" model, I've added the following line:
public $belongsTo = array('Companies');
2) In the "PeopleController" file, I've also included a reference to the Companies Model, such as:
use app\models\Companies;
Now, within the PeopleController, I want to call a method in the CompaniesController file.
Do I access this by directly calling the CompaniesController file? Or, do I have to go thru the Company model.
In either case, I'll need help with the syntax. I'm having rouble figuring out the best way this should be called.
Thanks in advance for your help!
You should rethink your structure - you controller method should really grab all the resources you need for that view, it doesn't matter what they are.
So if you have a url '/people/bob' and you want to get the company data for Bob just add that to the view method of your People controller. Something like
People::first(array('conditions' => array('name' => 'Bob'), 'with' => 'Companies'));
You could instantiate a CompaniesController (maybe passing in $this->request to the 'request' option in the process) and then call the method in it. However, a better way to organize it is to move the common functionality from CompaniesController to Companies and call it from both places.
use app\models\Companies does not really make a "reference." It simply indicates that Companies really means app\models\Companies. I think an "alias" is a better way to think of it. See http://php.net/manual/en/language.namespaces.importing.php.
Example:
// in app/models/Companies.php
namespace app\models;
class Companies extends \lithium\data\Model {
public static function doSomething() {
// do something related to companies.
}
}
// in app/controllers/CompaniesController.php
namespace app\controllers;
use app\models\Companies;
class CompaniesController extends \lithium\action\Controller {
public function index() {
$result = Companies::doSomething();
return array('some' => 'data', 'for' => 'the view');
}
}
// in app/controllers/PeopleController.php
namespace app\controllers;
use app\models\Companies;
class PeopleController extends \lithium\action\Controller {
public function index() {
$result = Companies::doSomething();
return array('some' => 'data', 'for' => 'the view');
}
}