تحتوي مكتبة PHP هذه على
كما يحتوي أيضًا على العديد من الأمثلة/الفئات الجزئية التي تنفذ عملية مزامنة بيانات الاتصال من نظام المصدر إلى قاعدة بيانات جهات الاتصال/العملاء المتوقعين الخاصة بـ Sharpspring. يعمل هذا مع ذاكرة التخزين المؤقت المحلية لعملاء Sharpspring، لتقليل استدعاءات التحديث إلى Sharpspring REST API.
يمكن استخدام فئة العميل بشكل مستقل، على الرغم من أن هذه المكتبة لم يتم إنشاؤها لهذا الغرض. إذا كنت تريد الاهتمام ببناء المعلمات الخاصة بك وفك تشفير النتيجة بنفسك: تفضل. إنشاء مثيل له؛ استدعاء طريقة المكالمة (). لا تحتاج إلى بقية المكتبة.
الهدف من فئة الاتصال هو مساعدتك على عدم الخلط بين التواصل مع REST API الخاص بـ Sharpspring. ويحاول المساعدة في ذلك بالطرق التالية:
(لم تتم مناقشة فئة LocalLeadCache هنا.)
use SharpSpring RestApi Connection ;
use SharpSpring RestApi CurlClient ;
// One thing this library does not make super easy: starting. Separation of
// concerns is considered more important, so (since the actual API call was
// abstracted into CurlClient) creating a new connection takes 2 lines instead
// of 1:
$ client = new CurlClient ([ ' account_id ' => . . . , ' secret_key ' => . . . ]);
$ api = new Connection ( $ client );
// Get all leads updated after a certain time (notation in 'local' timezone,
// though there is no formal definition of what 'local' entails).
$ leads = $ api -> getLeadsDateRange ( ' 2017-01-15 10:00:00 ' );
يطرح الكود استثناءات لأي شيء غريب يواجهه... باستثناء شيء واحد: الخصائص الإضافية التي يراها في الاستجابة، إلى جانب قيمة (قيم) المصفوفة المتوقعة بواسطة طريقة API/الاتصال المحددة التي تتصل بها. يتم تجاهل هذه بشكل افتراضي؛ ليس من المتوقع أن يتم مواجهتهم على الإطلاق. إذا كنت تريد تسجيل هذه البيانات، فقم بتمرير كائن مسجل متوافق مع PSR-3 كوسيطة ثانية لمنشئ الاتصال.
في كائنات (مصفوفات) واجهة برمجة التطبيقات Sharpspring REST، تتم الإشارة إلى الحقول المخصصة حسب اسم النظام الخاص بها، والذي يتغير لكل حساب. لتمكين كتابة تعليمات برمجية أكثر عمومية، يحتوي كائن الاتصال على تعيين من الخاصية المخصصة إلى اسم نظام الحقل. عند تعيين هذا التعيين (مع اختيارك لأسماء الخصائص)، ستتم ترجمة أسماء الخصائص المخصصة لأي معلمات "كائنات" في استدعاءات REST API تلقائيًا إلى أسماء نظام الحقول المقابلة.
لنفترض أن لديك عملاء محتملين لمتجر الأحذية الخاص بك، مع حقل مخصص لحجم الحذاء الذي قمت بإنشائه من خلال واجهة مستخدم Sharpspring، والتي ظهر اسم نظامها كـ Shoe_size_384c1e3eacbb3. المثالان التاليان متكافئان:
$ api -> createLead ([
' firstName ' => ' Roderik ' ,
' emailAddress ' => ' [email protected] ' ,
' shoe_size_384c1e3eacbb3 ' => 12 ,
]);
$ api -> setCustomProperties ( ' lead ' , [ ' shoeSize ' => ' shoe_size_384c1e3eacbb3 ' ]);
$ api -> createLead ([
' firstName ' => ' Roderik ' ,
' emailAddress ' => ' [email protected] ' ,
' shoeSize ' => 12 ,
]);
// Note that system names will still be OK; after setCustomProperties is called,
// you can still send in [...,'shoe_size_384c1e3eacbb3' => 12, ...]. Just don't
// set values for _both_ the field name _and_ its property alias, because then
// the library does not guarantee which of the two will be used.
يتم التحويل التلقائي فقط لـ "الكائنات" في معلمات استدعاء واجهة برمجة التطبيقات (API). لا يتم التلاعب بالنتائج التي يتم إرجاعها من استدعاءات واجهة برمجة التطبيقات (API). إذا كنت تريد تحويل أسماء نظام الحقول المخصصة في نتائج واجهة برمجة التطبيقات مرة أخرى إلى أسماء خصائصك المخصصة، فستحتاج إلى القيام بذلك بشكل صريح:
$ api -> setCustomProperties ( ' lead ' , [ ' shoeSize ' => ' shoe_size_384c1e3eacbb3 ' ]);
$ leads = $ api -> getLeads ([ ' emailAddress ' => ' [email protected] ' ]);
$ lead = reset ( $ leads );
$ my_lead = $ api -> convertSystemNames ( ' lead ' , $ lead );
يعد استخدام المصفوفات لتمثيل "كائن" API أمرًا جيدًا. ولكن قد تفضل استخدام الكائنات/الفئات لهم. (يمنحك الإكمال التلقائي لـ IDE، مما يقلل أيضًا من احتمالية كتابة أسماء الخصائص بأحرف كبيرة بشكل خاطئ والتي لا تتعامل معها REST API).
الفئة الأساسية هي ValueObject وفي هذه اللحظة توجد فئة Lead التي تنفذ جميع الحقول المعروفة (مع تعليقات حول المكان الذي أصبحت فيه وثائق Sharpspring API قديمة).
المثال التالي يساوي ما سبق:
/**
* If you have custom fields, you will want to define your own subclass:
*/
class ShoeStoreLead extends Lead
{
// Define your own properties:
public $ shoeSize ;
}
$ api -> setCustomProperties ( ' lead ' , [ ' shoeSize ' => ' shoe_size_384c1e3eacbb3 ' ]);
// This is the create call from above. Note createLead() accepts ValueObjects as
// well as arrays.
$ lead = new ShoeStoreLead ();
$ lead -> firstName = ' Roderik ' ;
$ lead -> emailAddress = [email protected]';
$ lead -> shoeSize = 12 ;
$ api -> createLead ( $ lead );
// And this is the 'get' call which puts the result into a new object:
$ leads = $ api -> getLeads ([ ' emailAddress ' => ' [email protected] ' ]);
$ lead = reset ( $ leads );
$ my_lead = $ api -> convertSystemNames ( ' lead ' , $ lead );
$ my_lead_obj = new ShoeStoreLead ( $ my_lead );
من الواضح، إذا لم يكن لديك أي حقول مخصصة، فسيصبح هذا المثال أكثر بساطة (لأنك لا تحتاج إلى فئة فرعية من الرصاص أو استخدام setCustomProperties() / ConvertSystemNames()).
في المثال أعلاه، لا يعرف ValueObject أي شيء عن تعيين خصائصه لأسماء أنظمة الحقول؛ يعالج كائن الاتصال هذا من أجل عمليات الإنشاء/التحديث، وبعد عمليات "الحصول على" تحتاج إلى تحويلها بشكل صريح مرة أخرى إلى أسماء الخصائص المخصصة قبل إنشاء الكائن.
هناك أيضًا طريقة أخرى: يمكنك تعيين التعيين في ValueObject بدلاً من الاتصال.
$ mapping = [ ' shoeSize ' => ' shoe_size_384c1e3eacbb3 ' ];
// $api->setCustomProperties('lead', $mapping) is not called here.
// For create:
$ lead = new ShoeStoreLead ([], $ mapping );
$ lead -> firstName = ' Roderik ' ;
$ lead -> emailAddress = [email protected]';
$ lead -> shoeSize = 12 ;
$ api -> createLead ( $ lead );
// Note you could also add all the properties in the first argument of the
// constructor, instead of setting them individually - although that more or
// less defeats the purpose of using a ValueObject in the first place. Setting
// 'shoeSize' works just as well as 'shoe_size_384c1e3eacbb3', in that first
// argument. Just don't set values for _both_ the field name _and_ its property
// alias, because then the library does not guarantee which of the two will be
// used.
// For 'get':
$ leads = $ api -> getLeads ([ ' emailAddress ' => ' [email protected] ' ]);
$ lead = reset ( $ leads );
$ my_lead_obj = new ShoeStoreLead ( $ my_lead , $ mapping );
لذلك: بالنسبة لكائنات ValueObject التي تحتوي على حقول مخصصة، يوجد خيار تعيين اتصال أو تعيينه في ValueObject. يتمتع الأخير بميزة أن البيانات المستردة من REST API يتم تحويلها تلقائيًا في المُنشئ، ولكن العيب هو أنه يجب تعيين التعيين في كل مرة يتم فيها إنشاء كائن.
هناك طريقة أخرى: إما ترميز التعيين داخل الكائن، مثل:
// Override the parent's (empty) property mapping variable:
protected $_customProperties = ['shoeSize' => 'shoe_size_384c1e3eacbb3'];
... أو جعل مُنشئ فئة ValueObject الفرعية المخصصة الخاصة بك يقوم بتعيينها (أو اشتقاقها من مكان ما). من المحتمل أن يكون هذا رمزًا خاصًا بحالتك الخاصة.
اختر النهج المفضل لديك.
تم توثيق معظم السلوكيات الغريبة لـ Sharpspring REST API أو تخفيفها/إخفائها جزئيًا بواسطة هذه المكتبة. ومع ذلك، إذا كنت ستقوم بعمل جاد يعتمد على واجهة برمجة التطبيقات (API)، فهناك بعض الأشياء التي يجب أن تكون على دراية بها على الأقل، وتقرر ما إذا كنت بحاجة إلى أخذها في الاعتبار.
يتم تخزين القيم ذات الأحرف غير القياسية (تقريبًا: الأحرف التي سيتم ترميزها بواسطة htmlspecialchars()) في Sharpspring بشكل مختلف اعتمادًا على ما إذا تم إدراجها من خلال REST API أو تم إدخالها من خلال واجهة المستخدم. (وبالنسبة لواجهة المستخدم، تختلف الأمور أيضًا بين الحقول القياسية والمخصصة.) إن '<' أكثر غرابة: ففي بعض الأحيان يتم تخزينها بترميز مزدوج. التفاصيل الدموية موجودة في encoding.md. الطريقة الوحيدة التي تمكنت بها هذه المكتبة من التخفيف من هذا السلوك هي أن يقوم CurlClient دائمًا بفك تشفير أي حقول بتنسيق HTML، سواء كان ذلك ضروريًا أم لا. نظرًا لأن عملية فك ترميز HTML تتم بشفافية، فمن المحتمل ألا ترى هذا السلوك، ولكن يجب على التطبيق الجاد أن يأخذ في الاعتبار ما إذا كانت هذه مشكلة أم لا.
يمكن لاستدعاء updateLead تغيير عناوين البريد الإلكتروني للعميل المتوقع الحالي عن طريق إرسال (على الأقل) قيمة "المعرف" الموجودة مع عنوان البريد الإلكتروني الذي تم تغييره. ومع ذلك، إذا تم استخدام البريد الإلكتروني الذي تم تغييره في عميل متوقع آخر موجود بالفعل، فسوف تتجاهل واجهة برمجة التطبيقات (API) التحديث بصمت ولكنها ستستمر في الإبلاغ عن النجاح . تعد هذه مشكلة محتملة إذا كنت تقوم بنسخ قاعدة بيانات جهات اتصال موجودة حيث لا تكون عناوين البريد الإلكتروني فريدة بالضرورة، في Sharpspring. ستحتاج إلى التحقق مرة أخرى من تحديثاتك لمعرفة ما إذا كانت ناجحة أم لا. (أحد الأمثلة على هذه التعليمات البرمجية موجود في SharpspringSyncJob::finish().)
(أرحب بأية تقارير تفيد بإصلاح هذه الأخطاء. ربما يحدث ذلك؛ راجع "تحذير".)
يبدو أن Sharpspring تغير أحيانًا سلوك واجهة برمجة التطبيقات الخاصة بها دون إعلان أو وثائق/سجلات التغيير (لا تفعل أيًا منهما على الإطلاق، على حد علمي)، وحتى بدون زيادة إصدار واجهة برمجة التطبيقات المذكور في وثائق واجهة برمجة التطبيقات عبر الإنترنت التي يمكن العثور عليها خلف تسجيل الدخول إلى موقع عملائهم.
يبدو أن الدرس المستفاد من هذا هو أنه، كمطور تطبيقات، يجب عليك اختبار تطبيقك باستمرار لأنه لا يمكنك الوثوق في عدم قيام Sharpspring بخرق "العقد الضمني" معك. لأن شركة Sharpspring على ما يبدو لا تشعر أن لديها "عقدًا ضمنيًا" مع مطوري التطبيقات.
(كانت لدي بعض المشاعر المريبة حول هذا الأمر أثناء تطوير هذه المكتبة على مدار نصف عام، ولكن ما أستند إليه في ذلك هو التغيير في سلوك استدعاء getLeadsDateRange (مع تعيين المعلمة "الطابع الزمني" على "update") - الذي غيّر تنسيق التواريخ في المعلمات والمخرجات، ومحتويات المخرجات. راجع الكود المصدري، مما أدى إلى تأثير فوري - تم الإبلاغ عن الأخطاء - في أنظمة الإنتاج التي استخدمت فئة SharpspringSyncJob، والتي كانت تحتوي على ل لا يزال إصدار واجهة برمجة التطبيقات المنشور هو 1.117، وهو كذلك منذ نوفمبر 2016 على الأقل.
قد يكون سبب تغيير السلوك هو التناقضات التي أبلغت عنها (لقد تبادلت رسائل بريد إلكتروني قصيرة، وانتهت بإرسال قائمة بالمشكلات التي واجهتها مع واجهة برمجة التطبيقات الخاصة بهم)، وأنا سعيد لأنهم يقومون بإصلاح التناقضات، ولكن عدم وجود الاستجابة أو التغيير أو تغيير إصدار واجهة برمجة التطبيقات لا يزال يؤدي إلى الوجبات الجاهزة المذكورة أعلاه. وآمل بالطبع أن يتغير هذا في المستقبل وقد يتم حذف هذا التحذير، ولكنه يبدو مناسبًا الآن.)
اوه انظر! https://help.sharpspring.com/hc/en-us/articles/115001069228-Open-API-Overview يذكر الآن أن لديهم واجهة برمجة التطبيقات "v1" وواجهة برمجة التطبيقات "v1.2"! يبدو أن الثاني يقبل إدخال التاريخ بالتوقيت العالمي المنسق (وهو ما فعلته واجهة برمجة التطبيقات v1 الخاصة بهم حتى 26 يوليو 2017 تقريبًا). لا يوجد أي ذكر لتنسيق تواريخ الإخراج (والتي تم تغييرها أيضًا في الإصدار الأول)، لذلك سيحتاج ذلك إلى الاختبار. لا تعمل هذه المكتبة حاليًا إلا بواجهة برمجة التطبيقات (API v1) ويجب توسيعها. إنه ليس مدرجًا في قائمتي المختصرة، لذا فإن العلاقات العامة (أو مهمة مدفوعة الأجر؛)) مرحب بها.
لقد تم اختبار هذا الرمز مع العملاء المتوقعين وأعضاء القائمة. يوجد المزيد من استدعاءات واجهة برمجة التطبيقات (API) ولكن لم يتم اختبارها جميعًا على نطاق واسع وبعضها مفقود. من المأمول أن لا تتطلب إضافة مكالمات جديدة الكثير من العمل؛ نرحب بطلبات السحب.
فقط أرسل العلاقات العامة أو اتصل بي بطريقة أخرى.
إن "عملية الإنشاء" (انظر الأيقونة في الأعلى؛ ستظهر رسالة ناجحة/فاشلة مماثلة على المستفيدين الرئيسيين) تتحقق فقط من معايير التشفير مقابل PHP5.6 / PSR2. لا توجد اختبارات وحدة حتى الآن نظرًا لأن هذه مجرد طبقة رقيقة من التعليمات البرمجية التي تلتف حول Sharpspring. أخبرني إذا كنت تعتقد أنه يجب أن تكون هناك اختبارات وأيها / لماذا. (سيكون من الجيد أن يكون لديك مجموعة كاملة من الاختبارات مقابل واجهة برمجة تطبيقات Sharpspring المباشرة ، ولكن أعتقد أن هذه مشكلة مختلفة و/أو على الأقل تتطلب مزيدًا من التنسيق معهم...)
أحب المساهمة ببرامج مفتوحة المصدر للعالم وأحب فتح أنظمة شبه مغلقة وغير موثقة. أعطني صيحة إذا كان هذا مفيدًا أو إذا كان لديك مساهمة. اتصل بي إذا كنت بحاجة إلى إنجاز أعمال التكامل. (لدي خبرة في العديد من الأنظمة الأخرى.)
هذه المكتبة مرخصة بموجب ترخيص MIT - راجع ملف LICENSE.md للحصول على التفاصيل.