I am preparing a console application and making a connection to database using container of entity manager. This works fine. Code is below
protected function execute(InputInterface $input, OutputInterface $output)
{
// get Doctrine
$this->em = $this->getContainer()->get('doctrine.orm.entity_manager');
// find all disc that are not treated by Manager in last week i.e sysdate - 6
$pendingApprovals = $this->em->getRepository('GMRestBundle:TDtlsDisc')->getPendingManagerAppoval();
// for each unapproved disc, start sending emails
$repository = $this->em->getRepository('GMRestBundle:TDtlsDisc');
$emailReminder = new SubmitDisclosureController();
foreach($pendingApprovals as $labManagerReview) {
$tDtlsDiscEntity = $repository->findByDiscId($labManagerReview['DISC_ID']);
$emailReminder->sendMailToLabManager($tDtlsDiscEntity);
}
}
Now, the issue is it is giving error when I call thsi $emailReminder->sendMailToLabManager($tDtlsDiscEntity); which will in turn makes a connection of orm and get some data from database. This sendMailToLabManager is in SubmitDisclosureController and the code is below.
public function sendMailToLabManager($tDtlsDiscEntity)
{
$repository = $this->getDoctrine()->getRepository('GMRestBundle:TXrefDiscSso');
$entityRepository = $this->getDoctrine()->getRepository('GMRestBundle:TDtlsEntity');
$discId = $tDtlsDiscEntity->getDiscId();
.......
In console application, I am no able to use any controller which access DB by making another connection to doctrine object. Same controller if I called through another action controller in web, it works well.
Error: Call to a member function has() on null
I see this above error message now.
You should create a service which provides the function instead of using the controller. After that you have to insert the EntityManager via dependency injection in to the the service.
If your command extends ContainerAwareCommand you can use $this->get() inside your command to retrieve the service you have defined before.
Related
Our organization wants to develop a "LOST & FOUND System Application" using chatbot integrated in a website.
Whenever the user starts the conversation with the chatbot, the chatbot should ask the details of lost item or item found and it should store the details in database.
How can we do it ?
And can we use our own web-service because organization doesn't want to keep the database in Amazon's Server.
As someone who just implemented this very same situation (with a lot of help from #Sid8491), I can give some insight on how I managed it.
Note, I'm using C# because that's what the company I work for uses.
First, the bot requires input from the user to decide what intent is being called. For this, I implemented a PostText call to the Lex API.
PostTextRequest lexTextRequest = new PostTextRequest()
{
BotName = botName,
BotAlias = botAlias,
UserId = sessionId,
InputText = messageToSend
};
try
{
lexTextResponse = await awsLexClient.PostTextAsync(lexTextRequest);
}
catch (Exception ex)
{
throw new BadRequestException(ex);
}
Please note that this requires you to have created a Cognito Object to authenticate your AmazonLexClient (as shown below):
protected void InitLexService()
{
//Grab region for Lex Bot services
Amazon.RegionEndpoint svcRegionEndpoint = Amazon.RegionEndpoint.USEast1;
//Get credentials from Cognito
awsCredentials = new CognitoAWSCredentials(
poolId, // Identity pool ID
svcRegionEndpoint); // Region
//Instantiate Lex Client with Region
awsLexClient = new AmazonLexClient(awsCredentials, svcRegionEndpoint);
}
After we get the response from the bot, we use a simple switch case to correctly identify the method we need to call for our web application to run. The entire process is handled by our web application, and we use Lex only to identify the user's request and slot values.
//Call Amazon Lex with Text, capture response
var lexResponse = await awsLexSvc.SendTextMsgToLex(userMessage, sessionID);
//Extract intent and slot values from LexResponse
string intent = lexResponse.IntentName;
var slots = lexResponse.Slots;
//Use LexResponse's Intent to call the appropriate method
switch (intent)
{
case: /*Your intent name*/:
/*Call appropriate method*/;
break;
}
After that, it is just a matter of displaying the result to the user. Do let me know if you need more clarification!
UPDATE:
An example implementation of the slots data to write to SQL (again in C#) would look like this:
case "LostItem":
message = "Please fill the following form with the details of the item you lost.";
LostItem();
break;
This would then take you to the LostItem() method which you can use to fill up a form.
public void LostItem()
{
string itemName = string.Empty;
itemName = //Get from user
//repeat with whatever else you need for a complete item object
//Implement a SQL call to a stored procedure that inserts the object into your database.
//You can do a similar call to the database to retrieve an object as well
}
That should point you in the right direction hopefully. Google is your best friend if you need help with SQL stored procedures. Hopefully this helped!
Yes its possible.
You can send the requests to Lex from your website which will extract Intents and Entities.
Once you get these, you can write backend code in any language of your choice and use any DB you want.
In your use case, you might just want to use Lex. PostText will be main function you will be calling.
You will need to create an intent in Lex which will have multiple slots LosingDate, LosingPlace or whatever you want, then it will be able to get all these information from the user and pass it to your web application.
According to other asked questions like this one, I did many doings to prevent this request expired message but there is no solution for my issue.
In the long run I recognized that the message appears when I call a service method inside a controller which run on form action!
Here is my codes samples with some descriptions:
My route:
Route::post('Material/{id}', 'MaterialController#updateMaterial')->name('updateMaterial');
Material Controller Constructor:
public function __construct(CustomService $srv)
{
$this->middleware('admin')->only(['updateMaterial']);
$this->srv= $srv;
}
srv is a protected attribute in MaterialController class.
updateMaterial Method:
public function updateMaterial($id,Request $request)
{
$this->validate($request, [...]);
$material = $this->srv->updateMaterial($request, $id);
if ($material)
return view('panel._materials.edit-material')
->with('material', $material)
->with('success', 1);
}
I also have a provider for CustomService with name CustomServiceProvider and here is the register method of the provider:
public function register()
{
$this->app->bind(CustomService::class,function($app){
return new CustomService();
});
}
and I registered it as a provider in config/app.php.
So when I return something before calling service updateMaterial method, it's OK. but when the method runs, the issue appears!
I don'n have any idea about!
Update:
And here is updateMaterial of CustomService:
public function updateMaterial($request, $id)
{
$material = Material::find($id);
if (!$material)
return false;
if ($request->has('unit'))
$material->unit = $request['unit'];
if ($request->has('price'))
$material->price = $request['price'];
if ($request->has('type'))
$material->type = $request['type'];
if ($request->has('is_active'))
$material->is_active = $request['is_active'];
$material->updated_at = Carbon::now();
$material->save();
return $material;
}
I also create a new project with Laravel 5.5.0 and without adding any complexity I just added a post route and call it in form action, but nothing changed!
This is just an issue for Windows users on Local Environment. I suffered a lot with this also when on Windows. Once you deploy to your production server, you won't have any issue at all.
It's important to note that this is not an issue with Laravel 5.5 version only. I first saw this issue in version 5.2.
I think a good fix for this would maybe be using something like Homestead or Vessel from Fideloper. Honestly I only suffered this problem when using Windows.
I have a function in my class to send emails using SmtpClient.
public void Send(System.Net.Mail.MailMessage mail)
{
using (SmtpClient client = new SmtpClient())
{
client.Host = ConfigReader.SmtpHost;
client.Port = ConfigReader.SmtpPort;
client.EnableSsl = ConfigReader.SmtpEnableSsl;
client.UseDefaultCredentials = ConfigReader.SmtpDefaultCredentials;
client.Credentials = new NetworkCredential(ConfigReader.SmtpUserName, ConfigReader.SmtpPassword);
client.Send(mail);
}
}
I need to set Smtp configs using another class in this function. But it does not seem right to set configuration every time this function is called.
What's the better approach for this? If I load the configuration in some other Init function to be called only once, how would SmtpClient will be disposed off in that case?
You create your SmtpClient object locally and more over in using statement as the object disposes out of scope your function. You must configure your object every time when you create them.
I have a web service which is working find with the data proxy.
In this web service I have some functions I like to call and assign the results to a variable.
I found some example on this and below is what I have come up with.
Now all works but my event is being fired to late in the process. What I mean is once I call the getAdData() function and then call the webservice function getBleedAt() I need my event to fire off. what happening is the event is being fire at the end of the hold routine so I get my data to late.
I try using the dispatchEvent but can't get that to work. the web service function is returning a XML structure
public function getAdddata(adnum:String){
var WS:WebService = new WebService();
WS.getBleedAt.addEventListener("result", GetInfo);
WS.getBleedAt.resultFormat = 'e4x';
WS.loadWSDL(URL);
WS.getBleedAt(adnum);
}
private function GetInfo(evt:ResultEvent):void {
var myObj:Object = evt.result as Object;
trace(myObj.BleedAt.toString());
}
The call to the web service returns asynchronously so your result handler (the GetInfo method) is the earliest point at which the result data is available to you. Therefore, any code which needs to access the result data needs to be triggered from the GetInfo method.
Goal:
Retrieve data from Dynamics CRM 2011 to my database from SQL server R2 by using webservice through integration services (SSIS). Webservice needed to be located inside of SSIS. Gonna use the data for data warehouse.
Problem:
How do I do it?
We only write to Dynamics so I can't address the specific method name but the general idea below should get you started.
Assumptions
Two variables have been defined in your package and they are passed to the script component as ReadOnlyVariables: CrmOrganizationName, CrmWebServiceUrl.
A script component has been added to the dataflow as a Source component. On the Inputs and Outputs tab, an appropriate number of columns have been added to Output 0 (or whatever you define your output collection as) with appropriate data types.
Inside the script, add a web reference to your CRM instance. This code assumes it's called CrmSdk.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
// web reference
using CrmSdk;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void CreateNewOutputRows()
{
// Get a reference to the CRM SDK
CrmSdk.CrmService CrmService = new CrmSdk.CrmService();
// An Authentication Token is required because CRM requires an OrganizationName
// to identify the Organization to be used
CrmSdk.CrmAuthenticationToken token = new CrmSdk.CrmAuthenticationToken();
token.AuthenticationType = 0;
token.OrganizationName = this.Variables.CrmOrganizationName;
CrmService.CrmAuthenticationTokenValue = token;
// Use default credentials
CrmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Get the web service url from the config file
CrmService.Url = this.Variables.CrmWebServiceUrl;
//////////////////////////////////////////////////
// This code is approximate
// Use the appropriate service call to get retrieve
// data and then enumerate through it. For each
// row encountered, call the AddRow() method for
// your buffer and then populate fields. Be wary
// of NULLs
//////////////////////////////////////////////////
foreach (CrmSdk.entity person in CrmService.Get())
{
Output0Buffer.AddRow();
Output0Buffer.FirstName = person.FirstName;
Output0Buffer.LastName = person.LastName;
}
}
}
Caveats
There is no error handling, checks for nulls or anything elegant. The service should probably have been defined with the using statement, etc, etc, etc. It should provide an appropriate starting point for understanding how to consume a web service and load data into the pipeline.
The easiest solution for your requirement is to use a third-party library for SSIS. The commercial COZYROC SSIS+ library includes Dynamics CRM adapters, which support all deployment models: Premise, Live, Hosted, Federation, Office 365.