I've created a library class file in my CakePHP 2.0 app. It's a single PHP class called emailManager Which exists within a folder emailManager within CakePHP's libaray folder. I would love to know what is the simplest way to reference the database from this library class.
I would love to be able to do something like $this->AppModel->query("SELECT * FROM some_table_in_my_db"), that way I do not have to track DB configurations in separate places, but I'm not sure how to achieve this.
Also, I feel it is important to mention that the tables I am working with do not adhere to CakePHP table naming convention. They predate our use of CakePHP and so I cannot change my tables to fit CakePHP's model format. this is why I want generic database access via something like query
EDIT: I have constructed a temporary solution, but I know a better one is possible.
I have a model in my cake app called MySimpleConstuct and then in the library file I include the MySimpleConstruct Model as followed:
// import this model
$this->GivenModel = ClassRegistry::init('MySimpleConstruct');
$this->GivenModel = new MySimpleConstruct();
// Then it is possible to do as followed:
$table_data = $this->GivenModel->query('SELECT * FROM like_some_table_dude' WHERE 1);
This is not ideal so I still searching for a better solution.
Any help would be greatly appreciated.
#John Galt, I suppose it's not an exact duplicate but it is very similar and the resolution does appear to apply to your situation very directly.
The other technique you could consider using would be to instantiate the Library in the controller and than give it a reference of the model.
class TestController extends AppController {
function index(){
App::uses('TheLibrary', 'Lib');
$obj = new TheLibrary();
$obj->GivenModel = &$this->GivenModel;
}
}
-EDIT-
And then within the library you've written do something like this.
class TheLibrary {
var $GivenModel = null;
function some_query(){
return $this->GivenModel->query('SELECT * FROM like_some_table_dude WHERE 1');
}
}
The first code snippet is of the Controller instantiating your library and then giving the library a reference to the Model as the property GivenModel. The "&" symbol makes the assignment a reference (see How does the '&' symbol in PHP affect the outcome?). The second code snippet is of a sample of how the library would use that property.
I do understand that you are trying to use a model from the library and that is what the solution you have in your edit and my proposed solution both do. However I will note again that this is not proper MVC convention and you should reconsider how you are using Libraries.
Related
Can anyone share own experience and best practices implementing multilingual sites with Yii2? I want translate user input that is stored in database. For example article, that may have its name in three different languages, body and some translatable attributes as well.
Does Yii2 have built in features to translate the dynamic content? Or should I use third party extensions like these ones below:
https://github.com/creocoder/yii2-translateable
https://github.com/LAV45/yii2-translated-behavior
https://github.com/lajax/yii2-translate-manager
Your help would be appreciated.
Well, I can give you my point of view only based on what I have done.
There are to places to work translation
The non dynamic strings managed with i18n and messages system from
yii, that will help you with static content.
Working the translated routes dynamically with a bootstrapped class, that allows you to build this routs when the app is built.
And working with tables that have columns that support the translation like 'title_en, title_es', and as many as you need to translate. Actually in your admin interface you may want to use something like yandex to help you translating the content to this fields.
Now I will explain:
The i18n Message Translation is based on translating strings in your views, models, and in some cases like on the bootstrapped class.
You will en using Yii::t('app/main', 'Your name is {0}' as an example to translate strings that are stored on message php files.
Now if you translate stings you will want to translate the routes so you will en with routes like /articles and /articulos when you change the language.
for this purpose you will like to build a class that implements BootstrapInterface and that will be called from the process of bootstrapping your app.
So this is an example of my settings.php that I use for this
namespace app\base;
use Yii;
use yii\base\BootstrapInterface;
class settings implements BootstrapInterface {
public function __construct() { }
public function bootstrap($app) {
/// Dynamic translated routes
$t_articles = Yii::t('app/route', 'articles');
$app->getUrlManager()->addRules([
'/'.$t_articles => '/articles',
], false);
}
}
And remember to bootstrap the class in your config file «i.e. web.php»
'bootstrap' => [
'log',
'app\base\settings',
],
And finally to translate text from the database you may want to make a table that supports the translated text like:
CREATE TABLE articles (
id INT,
title_en VARCHAR(20),
title_es VARCHAR(20)
);
So when you call your app you can pull your data using something like the following on the action (only a simple example):
$articles = ArticlesA::find()->where(['id' => 1])->one();
$lang = $this->module->language;
return $thi
s->render('index',['articles'=>$articles, 'lang'=>$lang]);
or in the view as:
<p class="lead"><?=$articles['title_'.$lang]?></p>
I hope this explains the way I have been translating my apps.
Use a Google translator API or Yandex API to for smooth translations for multiple languages.
Few links that i have found on git
https://github.com/borodulin/yii2-i18n-google
Tutorial
RichWeber/yii2-google-translate-api
Google Api is a paid service however you can get free credit for 12 months if your a first time user
I have a web application that uses linq-to-sql queries (will soon be upgraded to linq-to-EF compiled queries) and for which there's data context and a database already in place. I want to create a demo version of the application and for the demo, I want to use an entirely different database file but that will have the same tables. So in essence, I'll have the same data structure for two different databases: one database for logged-in users and one database for demo users. I want to reuse many of the queries I've already written; they look like this:
public class FruitQueries
{
public List<SomeObjectModel> MyQuery(list of parameters)
{
using (MyDataContext TheDC = new MyDataContext())
{
var TheQueryResult = (from f in TheDC.Fruits
......).ToList();
return TheQueryResult;
}
}
public List<SomeObject> AnotherQuery(some other parameters) {...}
}
Now I think I know that this calls for dependency injection where the data context is passed in as a parameter but I'm not sure on the syntax. How do you reuse queries using dependency injection to make them work on two different databases? Right now I'm using a using statement and I want to keep this pattern; is that possible if I inject the DC as a parameter?
Thanks.
Since you already have a lot of code in place, probably the simplest thing to do is to inject a factory:
public interface IMyDataContextFactory
{
MyDataContext CreateNewContext();
}
All the code will roughly stay the same:
public List<SomeObjectModel> MyQuery(params)
{
using (var TheDC = this.factory.CreateNewContext())
{
var TheQueryResult = (from f in TheDC.Fruits
......).ToList();
return TheQueryResult;
}
}
You can let the injected IMyDataContextFactory decide how to construct a MyDataContext instance (based on the user). This would be trivial.
In the end it will probably be better to inject a MyDataContext (or an abstraction such as IUnitOfWork) into consumers, but this changes everything completely. Since this class is passed in from the outside, the consumer isn't responsible anymore for disposing it, but someone else is. Although disposing such instance isn't that hard with most DI container. It gets harder though when you want to share the same MyDataContext instance over multiple consumers (within the same web request for instance) and where do you call SubmitChanges?
Elaborating the previous answer
What you can do, is provide the connectionstring to the DC (would this qualify as contructor injection?)
using (MyDataContext TheDC = new MyDataContext(this.factory.CreateConString()))
This way, disposal is still handled by the consumer and you can continue your Using() approach. Your factory can read the two different connectionstrings from your webconfig and determine the right one to use, based on the user. (not that trivial as it may seem)
PS: I think the quickest way is to deploy the demo application to a different URL so they can have a separate web.config and you do not need to code anything but that does not answer your question.
Background
Okay I'm one of those guys who NEVER asks questions and who can usually find what I need from existing questions or forums....but alas I have spent the last few days trying to figure this one out and have come up with very little existing information.
I am using Flash Builder 4.6 for PHP Premium to build a Flex application that uses the PHP Zend Frameworks's AMF capabilities to map classes from PHP to Flex and to use them as objects to send back and forth instead of using XML or JSON. Right now I am doing it all on a single local machine for ease.
Issue
I am not having trouble mapping my own custom PHP classes into ActionScript/Flex classes but I cannot for the life of me manage to map a DateTime PHP class into an ActionScript Date class. I have read elsewhere that it automatically maps DateTime objects to Date objects but I have never gotten it to work.
Strangely though, I can get it to work if I replace all instances of, in my case, valueObjects.DateTime (the auto-generated ActionScript class) to Date in the _Super_Foo.as class that has the DateTime property. This basically forces Flex to interpret the data of that property as a Date. However, since all the _Super_XXX.as files are files that autogenerated by Flex, it gets rewritten any time I refresh or edit ANY PHP service that Flex is linking to in Flash Builder.
Remarks
I could of course do this the quick and dirty way by keeping the variable as a string (it's coming from MySQL in a DateTime field) and then just create some functions to convert it to a Date object on the client side but I need a more permanent and stable solution.
Example:
<?php
class Foo {
public $id; // int
public $name; // string
public $date; // DateTime
public $bar; // custom object
}
?>
should go to --->
package {
class Foo {
public var id:int;
public var name:String;
public var date:Date; // native class
public var bar:Bar;
}
}
but I am getting
package {
class Foo {
public var id:int;
public var name:String;
public var date:DateTime; // custom class
public var bar:Bar;
}
}
I have tried things such as the following:
in the gateway.php file
$server->setClassMap("Date", "DateTime");
using the Zend_Date object instead
$foo->date = new Zend_Date($blah);
and after trying to map it as well explicitly
$server->setClassMap("Date", "Zend_Date");
the change I currently have working in the _Super_Foo.as file (which gets written over frequently)
private var _internal_date : valueObjects.DateTime; // custom object
to
private var _internal_date : Date; // native object
I just need it to do this automatically like I have read it should.
Well I have to admit, that I usually use BlazeDS on Java and not Zend, but I have had similar problems in transfering Calendar objects (I wanted to prevent loosing the timezone data). For This BlazeDS supported so-called PropertyProxys, which are components that allow to takeover the serialization/deserialization process for certain types.
I would assume that ZEND would support a similar thing. So another option would actually be to make Zend zupport the full Flex type. I have searched a little and it seems that the entire terminology is different in Zend, but I think this stackoverflow article should explain it a little: Zend AMF custom dispatcher
Chris
In my experience, Zend Framework has taught me that it offers many features but many times they don't work exactly how you'd expect. For example:
Recently I was working with a bug in "digitalus-cms" (A blog-like framework built on top of ZF) that it couldn't post new articles with a hyphen in their title name. I tracked it down to Zend_Form_Element::filterName. It uses a regular expression that matches any character that falls into the category of: [^a-zA-Z0-9_\x7f-\xff] then removes it. This ends up removing hyphens from the names of form elements which wound up being the cause of the bug.
If Zend_Amf or Zend_Date doesn't work the way you want it to, find a workaround such as passing a unix timestamp number around so everything works the way it should. Then afterwards, you can write a class to extend off one of Zend's classes. Zend Framework is meant to be extended upon, that's the way the framework was built so you can fix issues like these on your own to get the framework to behave how you want it to. That's the whole point of wrappers. Go ahead, create some of your own wrapper classes and toss in some methods to interact with ZF so you can fine-tune everything.
As far as finding the cause of your issue, all I can tell you is keep on debugging and isolating code so you know what you are passing flex, and how flex responses to that. After you play around with it enough, I'm sure you'll find the culprit.
AmfPHP automatically maps it. http://www.silexlabs.org/amfphp/
I am looking for some help with designing some functionality in my application. I already have something similar designed but this problem is a little different.
Background:
In my application we have different Modules. Data in each module can be associated to other modules. Each Module is represented by an Object in our application.
Module 1 can be associated with Module 2 and Module 3. Currently I use a factory to provide the proper DAO for getting and saving this data.
It looks something like this:
class Module1Factory {
public static Module1BridgeDAO createModule1BridgeDAO(int moduleid) {
switch (moduleId)
{
case Module.Module2Id: return new Module1_Module2DAO();
case Module.Module3Id: return new Module1_Module3DAO();
default: return null;
}
}
}
Module1_Module2 and Module1_Module3 implement the same BridgeModule interface. In the database I have a Table for every module (Module1, Module2, Module3). I also have a bridge table for each module (they are many to many) Module1_Module2, Module1_Module3 etc.
The DAO basically handles all code needed to manage the association and retrieve its own instance data for the calling module. Now when we add new modules that associate with Module1 we simply implement the ModuleBridge interface and provide the common functionality.
New Development
We are adding a new module that will have the ability to be associated with other Modules as well as specific properties of that module. The module is basically providing the user the ability to add their custom forms to our other modules. That way they can collect additional information along with what we provide.
I want to start associating my Form module with other modules and their properties. Ie if Module1 has a property Category, I want to associate an instance From data with that property.
There are many Forms. If a users creates an instance of Module2, they may always want to also have certain form(s) attached to that Module2 instance. If they create an instance of Module2 and select Category 1, then I may want additional Form(s) created.
I prototyped something like this:
Form
FormLayout (contains the labels and gui controls)
FormModule (associates a form with all instances of a module)
Form Instance (create an instance of a form to be filled out)
As I thought about it I was thinking about making a new FormModule table/class/dao for each Module and Property that I add. So I might have:
FormModule1
FormModule1Property1
FormModule1Property2
FormModule1Property3
FormModule1Property4
FormModule2
FormModule3
FormModule3Property1
Then as I did previously, I would use a factory to get the proper DAO for dealing with all of these. I would hand it an array of ids representing different modules and properties and it would return all of the DAOs that I need to call getForms(). Which in turn would return all of the forms for that particular bridge.
Some points
This will be for a new module so I dont need to expand on the factory code I provided. I just wanted to show an example of what I have done in the past.
The new module can be associated with: Other Modules (ie globally for any instance of that module data), Other module properties (ie only if the Module instance has a certian value in one of its properties)
I want to make it easy for developers to add associations with other modules and properties easily
Can any one suggest any design patterns or strategy's for achieving this?
If anything is unclear please let me know.
Thank you,
Al
You can use springs Dependency Injection feature. This would help you achieve the flexibility of instantiating the objects using an xml configuration file.
So, my suggestion would be go with the Springs.
As we all know, when we derive a class and use polymorphism, someone, somewhere needs to know what class to instanciate. We can use factories, a big switch statement, if-else-if, etc. I just learnt from Bill K this is called Dependency Injection.
My Question: Is it good practice to use reflection and attributes as the dependency injection mechanism? That way, the list gets populated dynamically as we add new types.
Here is an example. Please no comment about how loading images can be done other ways, we know.
Suppose we have the following IImageFileFormat interface:
public interface IImageFileFormat
{
string[] SupportedFormats { get; };
Image Load(string fileName);
void Save(Image image, string fileName);
}
Different classes will implement this interface:
[FileFormat]
public class BmpFileFormat : IImageFileFormat { ... }
[FileFormat]
public class JpegFileFormat : IImageFileFormat { ... }
When a file needs to be loaded or saved, a manager needs to iterate through all known loader and call the Load()/Save() from the appropriate instance depending on their SupportedExtensions.
class ImageLoader
{
public Image Load(string fileName)
{
return FindFormat(fileName).Load(fileName);
}
public void Save(Image image, string fileName)
{
FindFormat(fileName).Save(image, fileName);
}
IImageFileFormat FindFormat(string fileName)
{
string extension = Path.GetExtension(fileName);
return formats.First(f => f.SupportedExtensions.Contains(extension));
}
private List<IImageFileFormat> formats;
}
I guess the important point here is whether the list of available loader (formats) should be populated by hand or using reflection.
By hand:
public ImageLoader()
{
formats = new List<IImageFileFormat>();
formats.Add(new BmpFileFormat());
formats.Add(new JpegFileFormat());
}
By reflection:
public ImageLoader()
{
formats = new List<IImageFileFormat>();
foreach(Type type in Assembly.GetExecutingAssembly().GetTypes())
{
if(type.GetCustomAttributes(typeof(FileFormatAttribute), false).Length > 0)
{
formats.Add(Activator.CreateInstance(type))
}
}
}
I sometimes use the later and it never occured to me that it could be a very bad idea. Yes, adding new classes is easy, but the mechanic registering those same classes is harder to grasp and therefore maintain than a simple coded-by-hand list.
Please discuss.
My personal preference is neither - when there is a mapping of classes to some arbitrary string, a configuration file is the place to do it IMHO. This way, you never need to modify the code - especially if you use a dynamic loading mechanism to add new dynamic libraries.
In general, I always prefer some method that allows me to write code once as much as possible - both your methods require altering already-written/built/deployed code (since your reflection route makes no provision for adding file format loaders in new DLLs).
Edit by Coincoin:
Reflection approach could be effectively combined with configuration files to locate the implmentations to be injected.
The type could be declared explicitely in the config file using canonical names, similar to MSBuild <UsingTask>
The config could locate the assemblies, but then we have to inject all matching types, ala Microsoft Visual Studio Packages.
Any other mechanism to match a value or set of condition to the needed type.
My vote is that the reflection method is nicer. With that method, adding a new file format only modifies one part of the code - the place where you define the class to handle the file format. Without reflection, you'll have to remember to modify the other class, the ImageLoader, as well
Isn't this pretty much what the Dependency Injection pattern is all about?
If you can isolate the dependencies then the mechanics will almost certainly be reflection based, but it will be configuration file driven so the messiness of the reflection can be pretty well encapsulated and isolated.
I believe with DI you simply say I need an object of type <interface> with some other parameters, and the DI system returns an object to you that satisfies your conditions.
This goes together with IoC (Inversion of Control) where the object being supplied may need something else, so that other thing is automatically created and installed into your object (being created by DI) before it's returned to the user.
I know this borders on the "no comment about loading images other ways", but why not just flip your dependencies -- rather than have ImageLoader depend on ImageFileFormats, have each IImageFileFormat depend on an ImageLoader? You'll gain a few things out of this:
Each time you add a new IImageFileFormat, you won't need to make any changes anywhere else (and you won't have to use reflection, either)
If you take it one step further and abstract ImageLoader, you can mock it in Unit Tests, making testing the concrete implementations of each IImageFileFormat that much easier
In vb.net, if all the image loaders will be in the same assembly, one could use partial classes and events to achieve the desired effect (have a class whose purpose is to fire an event when the image loaders should register themselves; each file containing image loaders can have use a "partial class" to add another event handler to that class); C# doesn't have a direct equivalent to vb.net's WithEvents syntax, but I suspect partial classes are a limited mechanism for achieving the same thing.